markup must not be translatable
[openerp-client.git] / bin / modules / gui / window / form.py
blob6b74ce357e179e9786b4fc0aac8ff9923c389161
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
4 # Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved.
6 # $Id$
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
13 # Service Company
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 ##############################################################################
31 import types
32 import gettext
34 import gtk
35 import gobject
36 from gtk import glade
38 import rpc
39 import win_selection
40 import win_search
41 import win_export
42 import win_import
43 import win_list
45 from gtk.gdk import Color
47 import common
48 import service
49 import options
50 import copy
52 import gc
54 from observator import oregistry
55 from widget.screen import Screen
58 class form(object):
60 def __init__(self, model, res_id=False, domain=None, view_type=None,
61 view_ids=None, window=None, context=None, name=False, limit=80,
62 auto_refresh=False):
63 if not view_type:
64 view_type = ['form','tree']
65 if domain is None:
66 domain = []
67 if view_ids is None:
68 view_ids = []
69 if context is None:
70 context = {}
72 fields = {}
73 self.model = model
74 self.window = window
75 self.previous_action = None
76 self.glade = glade.XML(common.terp_path("terp.glade"),'win_form_container',gettext.textdomain())
77 self.widget = self.glade.get_widget('win_form_container')
78 self.widget.show_all()
79 self.fields = fields
80 self.domain = domain
81 self.context = context
83 self.screen = Screen(self.model, view_type=view_type,
84 context=self.context, view_ids=view_ids, domain=domain,
85 hastoolbar=options.options['form.toolbar'], show_search=True,
86 window=self.window, limit=limit, readonly=bool(auto_refresh))
87 self.screen.signal_connect(self, 'record-message', self._record_message)
88 self.screen.widget.show()
89 oregistry.add_receiver('misc-message', self._misc_message)
91 if not name:
92 self.name = self.screen.current_view.title
93 else:
94 self.name = name
95 vp = gtk.Viewport()
96 vp.set_shadow_type(gtk.SHADOW_NONE)
97 vp.add(self.screen.widget)
98 vp.show()
99 self.sw = gtk.ScrolledWindow()
100 self.sw.set_shadow_type(gtk.SHADOW_NONE)
101 self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
102 self.sw.add(vp)
103 self.sw.show()
105 self.has_backup = False
106 self.backup = {}
108 self.widget.pack_start(self.sw)
109 self.handlers = {
110 'but_new': self.sig_new,
111 'but_copy': self.sig_copy,
112 'but_save': self.sig_save,
113 'but_save_as': self.sig_save_as,
114 'but_import': self.sig_import,
115 'but_print_repeat': self.sig_print_repeat,
116 'but_remove': self.sig_remove,
117 'but_search': self.sig_search,
118 'but_previous': self.sig_previous,
119 'but_next': self.sig_next,
120 'but_goto_id': self.sig_goto,
121 'but_log': self.sig_logs,
122 'but_print': self.sig_print,
123 'but_reload': self.sig_reload,
124 'but_print_html': self.sig_print_html,
125 'but_action': self.sig_action,
126 'but_switch': self.sig_switch,
127 'but_attach': self.sig_attach,
128 'but_close': self.sig_close,
130 if res_id:
131 if isinstance(res_id, int):
132 res_id = [res_id]
133 self.screen.load(res_id)
134 else:
135 if self.screen.current_view.view_type == 'form':
136 self.sig_new(autosave=False)
137 if self.screen.current_view.view_type in ('tree', 'graph', 'calendar'):
138 self.screen.search_filter()
140 if auto_refresh and int(auto_refresh):
141 gobject.timeout_add(int(auto_refresh) * 1000, self.sig_reload)
143 def sig_goto(self, *args):
144 if not self.modified_save():
145 return
146 glade2 = glade.XML(common.terp_path("terp.glade"),'dia_goto_id',gettext.textdomain())
147 widget = glade2.get_widget('goto_spinbutton')
148 win = glade2.get_widget('dia_goto_id')
149 win.set_transient_for(self.window)
150 win.show_all()
152 response = win.run()
153 win.destroy()
154 if response == gtk.RESPONSE_OK:
155 self.screen.load( [int(widget.get_value())] )
157 def destroy(self):
158 oregistry.remove_receiver('misc-message', self._misc_message)
159 self.screen.signal_unconnect(self)
160 self.screen.destroy()
161 del self.screen
162 del self.glade
163 del self.widget
164 self.sw.destroy()
165 del self.sw
166 gc.collect()
168 def ids_get(self):
169 return self.screen.ids_get()
171 def id_get(self):
172 return self.screen.id_get()
174 def sig_attach(self, widget=None):
175 id = self.screen.id_get()
176 if id:
177 import win_attach
178 win = win_attach.win_attach(self.model, id, parent=self.window)
179 win.go()
180 else:
181 self.message_state(_('No record selected ! You can only attach to existing record.'), color='red')
182 return True
184 def sig_switch(self, widget=None, mode=None):
185 if not self.modified_save():
186 return
187 self.screen.switch_view()
189 def _id_get(self):
190 return self.screen.id_get()
192 def sig_logs(self, widget=None):
193 id = self._id_get()
194 if not id:
195 self.message_state(_('You have to select a record !'), color='red')
196 return False
197 res = rpc.session.rpc_exec_auth('/object', 'execute', self.model, 'perm_read', [id])
198 message = ''
199 for line in res:
200 todo = [
201 ('id', _('ID')),
202 ('create_uid', _('Creation User')),
203 ('create_date', _('Creation Date')),
204 ('write_uid', _('Latest Modification by')),
205 ('write_date', _('Latest Modification Date'))
207 for (key,val) in todo:
208 if line[key] and key in ('create_uid','write_uid','uid'):
209 line[key] = line[key][1]
210 message+=val+': '+str(line[key] or '/')+'\n'
211 common.message(message)
212 return True
214 def sig_remove(self, widget=None):
215 if not self._id_get():
216 msg = _('Record is not saved ! \n Do You want to Clear Current Record ?')
217 else:
218 if self.screen.current_view.view_type == 'form':
219 msg = _('Are you sure to remove this record ?')
220 else:
221 msg = _('Are you sure to remove those records ?')
222 if common.sur(msg):
223 id = self.screen.remove(unlink=True)
224 if not id:
225 self.message_state(_('Resources cleared.'), color='darkgreen')
226 else:
227 self.message_state(_('Resources successfully removed.'), color='darkgreen')
229 def sig_import(self, widget=None):
230 fields = []
231 while(self.screen.view_to_load):
232 self.screen.load_view_to_load()
233 win = win_import.win_import(self.model, self.screen.fields, fields, parent=self.window)
234 res = win.go()
236 def sig_save_as(self, widget=None):
237 fields = []
238 while(self.screen.view_to_load):
239 self.screen.load_view_to_load()
240 win = win_export.win_export(self.model, self.screen.ids_get(), self.screen.fields, fields, parent=self.window, context=self.context)
241 res = win.go()
243 def sig_new(self, widget=None, autosave=True):
244 if autosave:
245 if not self.modified_save():
246 return
247 self.screen.new()
248 self.message_state('')
250 def sig_copy(self, *args):
251 if not self.modified_save():
252 return
253 res_id = self._id_get()
254 ctx = self.context.copy()
255 ctx.update(rpc.session.context)
256 new_id = rpc.session.rpc_exec_auth('/object', 'execute', self.model, 'copy', res_id, {}, ctx)
257 if new_id:
258 self.screen.load([new_id])
259 self.message_state(_('Working now on the duplicated document !'))
261 def _form_save(self, auto_continue=True):
262 pass
264 def sig_save(self, widget=None, sig_new=True, auto_continue=True):
265 id = self.screen.save_current()
266 if id:
267 self.message_state(_('Document Saved.'), color="darkgreen")
268 else:
269 self.message_state(_('Invalid form, correct red fields !'), color="red")
270 return bool(id)
272 def sig_previous(self, widget=None):
273 if not self.modified_save():
274 return
275 self.screen.display_prev()
276 self.message_state('')
278 def sig_next(self, widget=None):
279 if not self.modified_save():
280 return
281 self.screen.display_next()
282 self.message_state('')
284 def sig_reload(self, test_modified=True):
285 if not hasattr(self, 'screen'):
286 return False
287 if test_modified and self.screen.is_modified():
288 res = common.sur_3b(_('This record has been modified\n' \
289 'do you want to save it ?'))
290 if res == 'ok':
291 self.sig_save()
292 elif res == 'ko':
293 pass
294 else:
295 return False
296 if self.screen.current_view.view_type == 'form':
297 self.screen.cancel_current()
298 self.screen.display()
299 else:
300 id = self.screen.id_get()
301 self.screen.search_filter()
302 for model in self.screen.models:
303 if model.id == id:
304 self.screen.current_model = model
305 self.screen.display()
306 break
307 self.message_state('')
308 return True
310 def sig_action(self, keyword='client_action_multi', previous=False, report_type='pdf', adds={}):
311 ids = self.screen.ids_get()
312 if self.screen.current_model:
313 id = self.screen.current_model.id
314 else:
315 id = False
316 if self.screen.current_view.view_type == 'form':
317 id = self.screen.save_current()
318 if not id:
319 return False
320 ids = [id]
321 if self.screen.current_view.view_type == 'tree':
322 sel_ids = self.screen.current_view.sel_ids_get()
323 if sel_ids:
324 ids = sel_ids
325 if len(ids):
326 print 'ICI', self.screen.context
327 obj = service.LocalService('action.main')
328 if previous and self.previous_action:
329 obj._exec_action(self.previous_action[1], {'model':self.screen.resource, 'id': id or False, 'ids':ids, 'report_type': report_type}, self.screen.context)
330 else:
331 res = obj.exec_keyword(keyword, {'model':self.screen.resource, 'id': id or False, 'ids':ids, 'report_type': report_type}, adds, self.screen.context)
332 if res:
333 self.previous_action = res
334 self.sig_reload(test_modified=False)
335 else:
336 self.message_state(_('You must select one or several records !'),color='red')
338 def sig_print_repeat(self):
339 self.sig_action('client_print_multi', True)
341 def sig_print_html(self):
342 self.sig_action('client_print_multi', report_type='html')
344 def sig_print(self):
345 self.sig_action('client_print_multi', adds={_('Print Screen'): {'report_name':'printscreen.list', 'name':_('Print Screen'), 'type':'ir.actions.report.xml'}})
347 def sig_search(self, widget=None):
348 if not self.modified_save():
349 return
350 dom = self.domain
351 win = win_search.win_search(self.model, domain=self.domain, context=self.context, parent=self.window)
352 res = win.go()
353 if res:
354 self.screen.clear()
355 self.screen.load(res)
357 def message_state(self, message, context='message', color=None):
358 sb = self.glade.get_widget('stat_state')
359 if color is not None:
360 message = '<span foreground="%s">%s</span>' % (color, message)
361 sb.set_label(message)
363 def _record_message(self, screen, signal_data):
364 if not signal_data[3]:
365 msg = _('No record selected')
366 else:
367 name = '_'
368 if signal_data[0]>=0:
369 name = str(signal_data[0]+1)
370 name2 = _('New document')
371 if signal_data[3]:
372 name2 = _('Editing document (id: ')+str(signal_data[3])+')'
373 msg = _('Record: ') + name + ' / ' + str(signal_data[1]) + \
374 _(' of ') + str(signal_data[2]) + ' - ' + name2
375 sb = self.glade.get_widget('stat_form')
376 cid = sb.get_context_id('message')
377 sb.push(cid, msg)
379 def _misc_message(self, obj, message, color=None):
380 self.message_state(message, color=color)
382 def modified_save(self, reload=True):
383 if self.screen.is_modified():
384 value = common.sur_3b(_('This record has been modified\ndo you want to save it ?'))
385 if value == 'ok':
386 return self.sig_save()
387 elif value == 'ko':
388 if reload:
389 self.sig_reload(test_modified=False)
390 return True
391 else:
392 return False
393 return True
395 def sig_close(self, urgent=False):
396 return self.modified_save(reload=False)
398 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: