1
# -*- encoding: utf-8 -*-
2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
8
# This program is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21
##############################################################################
34
from widget.screen import Screen
36
from modules.gui.window.win_search import win_search
43
def __init__(self, model, id=None, attrs=None ,domain=None, context=None, window=None, view_ids=None,target=False,view_type=['form']):
52
window = service.LocalService('gui.main').window
54
self.dia = gtk.Dialog(_('OpenERP - Link'), window,
55
gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT)
57
if ('string' in attrs) and attrs['string']:
58
self.dia.set_title(self.dia.get_title() + ' - ' + attrs['string'])
60
self.dia.set_property('default-width', 760)
61
self.dia.set_property('default-height', 500)
62
self.dia.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
63
self.dia.set_icon(common.OPENERP_ICON)
65
self.accel_group = gtk.AccelGroup()
66
self.dia.add_accel_group(self.accel_group)
68
self.but_cancel = self.dia.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
69
self.but_cancel.add_accelerator('clicked', self.accel_group, gtk.keysyms.Escape, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE)
71
self.but_ok = self.dia.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
72
self.but_ok.add_accelerator('clicked', self.accel_group, gtk.keysyms.Return, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE)
74
scroll = gtk.ScrolledWindow()
75
scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
76
scroll.set_placement(gtk.CORNER_TOP_LEFT)
77
scroll.set_shadow_type(gtk.SHADOW_NONE)
78
self.dia.vbox.pack_start(scroll, expand=True, fill=True)
81
vp.set_shadow_type(gtk.SHADOW_NONE)
83
self.screen = Screen(model, view_ids=view_ids, domain=domain, context=context, window=self.dia, view_type=view_type)
85
self.screen.load([id])
88
vp.add(self.screen.widget)
90
x,y = self.screen.screen_container.size_get()
91
width, height = window.get_size()
93
vp.set_size_request(min(width - 20, x + 20),min(height - 60, y + 25))
95
vp.set_size_request(x,y)
99
def run(self, datas={}):
102
if res==gtk.RESPONSE_OK:
103
if self.screen.current_model.validate() and self.screen.save_current():
104
return (True, self.screen.current_model.name_get())
106
self.screen.display()
109
return (False, False)
112
self.window.present()
115
class many2one(interface.widget_interface):
116
def __init__(self, window, parent, model, attrs={}):
117
interface.widget_interface.__init__(self, window, parent, model, attrs)
119
self.widget = gtk.HBox(spacing=3)
120
self.widget.set_property('sensitive', True)
121
self.widget.connect('focus-in-event', lambda x,y: self._focus_in())
122
self.widget.connect('focus-out-event', lambda x,y: self._focus_out())
124
self.wid_text = gtk.Entry()
125
self.wid_text.set_property('width-chars', 13)
126
self.wid_text.connect('key_press_event', self.sig_key_press)
127
self.wid_text.connect('button_press_event', self._menu_open)
128
self.wid_text.connect_after('changed', self.sig_changed)
129
self.wid_text.connect_after('activate', self.sig_activate)
130
self.wid_text_focus_out_id = self.wid_text.connect_after('focus-out-event', self.sig_focus_out, True)
131
self.widget.pack_start(self.wid_text, expand=True, fill=True)
133
self.but_find = gtk.Button()
134
img_find = gtk.Image()
135
img_find.set_from_stock('gtk-find',gtk.ICON_SIZE_BUTTON)
136
self.but_find.set_image(img_find)
137
self.but_find.set_relief(gtk.RELIEF_NONE)
138
self.but_find.connect('clicked', self.sig_find)
139
self.but_find.set_alignment(0.5, 0.5)
140
self.but_find.set_property('can-focus', False)
142
self.tooltips = gtk.Tooltips()
143
self.tooltips.set_tip(self.but_find, _('Select a record'))
144
self.tooltips.enable()
147
self.but_open = gtk.Button()
148
img_open = gtk.Image()
149
img_open.set_from_stock('gtk-open',gtk.ICON_SIZE_BUTTON)
150
self.but_open.set_image(img_open)
151
self.but_open.set_relief(gtk.RELIEF_NONE)
152
self.but_open.connect('clicked', self.sig_edit)
153
self.but_open.set_alignment(0.5, 0.5)
154
self.but_open.set_property('can-focus', False)
156
self.tooltips = gtk.Tooltips()
157
self.tooltips.set_tip(self.but_find, _('Open this record'))
158
self.tooltips.enable()
160
self.widget.pack_start(self.but_open, padding=2, expand=False, fill=False)
161
self.widget.pack_start(self.but_find, padding=2, expand=False, fill=False)
164
self._readonly = False
165
self.model_type = attrs['relation']
166
self._menu_loaded = False
167
self._menu_entries.append((None, None, None))
168
self._menu_entries.append((_('Action'), lambda x: self.click_and_action('client_action_multi'),0))
169
self._menu_entries.append((_('Report'), lambda x: self.click_and_action('client_print_multi'),0))
171
if attrs.get('completion',False):
172
ids = rpc.session.rpc_exec_auth('/object', 'execute', self.attrs['relation'], 'name_search', '', [], 'ilike', {})
174
self.load_completion(ids,attrs)
176
def load_completion(self,ids,attrs):
177
self.completion = gtk.EntryCompletion()
178
self.completion.set_match_func(self.match_func, None)
179
self.completion.connect("match-selected", self.on_completion_match)
180
self.wid_text.set_completion(self.completion)
181
self.liststore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
182
self.completion.set_model(self.liststore)
183
self.completion.set_text_column(0)
184
for i,word in enumerate(ids):
185
if word[1][0] == '[':
186
i = word[1].find(']')
189
self.liststore.append([("%s %s" % (s,s2)),s2])
191
self.liststore.append([word[1],word[1]])
193
def match_func(self, completion, key_string, iter, data):
194
model = self.completion.get_model()
195
modelstr = model[iter][0].lower()
196
return modelstr.startswith(key_string)
198
def on_completion_match(self, completion, model, iter):
199
name = model[iter][1]
200
domain = self._view.modelfield.domain_get(self._view.model)
201
context = self._view.modelfield.context_get(self._view.model)
202
ids = rpc.session.rpc_exec_auth('/object', 'execute',
203
self.attrs['relation'], 'name_search', name, domain, 'ilike',
206
self._view.modelfield.set_client(self._view.model, ids[0])
207
self.display(self._view.model, self._view.modelfield)
210
win = win_search(self.attrs['relation'], sel_multi=False,
211
ids=map(lambda x: x[0], ids), context=context,
212
domain=domain, window=self._window)
215
name = rpc.session.rpc_exec_auth('/object', 'execute',
216
self.attrs['relation'], 'name_get', [ids[0]],
217
rpc.session.context)[0]
218
self._view.modelfield.set_client(self._view.model, name)
221
def _readonly_set(self, value):
222
self._readonly = value
223
self.wid_text.set_editable(not value)
224
#self.but_new.set_sensitive(not value)
226
def _color_widget(self):
229
def _menu_sig_pref(self, obj):
230
self._menu_sig_default_set()
232
def _menu_sig_default(self, obj):
233
res = rpc.session.rpc_exec_auth('/object', 'execute', self.attrs['model'], 'default_get', [self.attrs['name']])
235
def sig_find(self, widget, event=None, leave=False):
237
self.wid_text.disconnect(self.wid_text_focus_out_id)
238
if not self._readonly:
239
domain = self._view.modelfield.domain_get(self._view.model)
240
context = self._view.modelfield.context_get(self._view.model)
241
self.wid_text.grab_focus()
243
ids = rpc.session.rpc_exec_auth('/object', 'execute', self.attrs['relation'], 'name_search', leave and self.wid_text.get_text() or '', domain, 'ilike', context)
244
if (len(ids)==1) and leave:
245
self._view.modelfield.set_client(self._view.model, ids[0],
247
self.wid_text_focus_out_id = self.wid_text.connect_after('focus-out-event', self.sig_focus_out, True)
248
self.display(self._view.model, self._view.modelfield)
252
win = win_search(self.attrs['relation'], sel_multi=False, ids=map(lambda x: x[0], ids), context=context, domain=domain, parent=self._window)
255
name = rpc.session.rpc_exec_auth('/object', 'execute', self.attrs['relation'], 'name_get', [ids[0]], rpc.session.context)[0]
256
self._view.modelfield.set_client(self._view.model, name,
258
self.wid_text_focus_out_id = self.wid_text.connect_after('focus-out-event', self.sig_focus_out, True)
259
self.display(self._view.model, self._view.modelfield)
262
def sig_edit(self, widget, event=None, leave=False):
264
self.wid_text.disconnect(self.wid_text_focus_out_id)
266
domain = self._view.modelfield.domain_get(self._view.model)
267
context = self._view.modelfield.context_get(self._view.model)
268
dia = dialog(self.attrs['relation'], self._view.modelfield.get(self._view.model), attrs=self.attrs, window=self._window, domain=domain, context=context)
269
ok, value = dia.run()
271
self._view.modelfield.set_client(self._view.model, value,
274
self.wid_text_focus_out_id = self.wid_text.connect_after('focus-out-event', self.sig_focus_out, True)
275
self.display(self._view.model, self._view.modelfield)
278
def sig_focus_out(self, widget, event=None, leave=False):
279
res = self._view.modelfield.get_client(self._view.model)
280
if self.wid_text.get_text() and not res:
281
self.sig_find(widget, event, leave=True)
283
def sig_activate(self, widget, event=None, leave=False):
284
self.sig_find(widget, event, leave=True)
286
def sig_new(self, *args):
287
self.wid_text.disconnect(self.wid_text_focus_out_id)
288
domain = self._view.modelfield.domain_get(self._view.model)
289
context = self._view.modelfield.context_get(self._view.model)
290
dia = dialog(self.attrs['relation'], attrs=self.attrs, window=self._window, domain=domain ,context=context)
291
ok, value = dia.run()
293
self._view.modelfield.set_client(self._view.model, value)
294
self.display(self._view.model, self._view.modelfield)
296
self.wid_text_focus_out_id = self.wid_text.connect_after('focus-out-event', self.sig_focus_out, True)
298
def sig_key_press(self, widget, event, *args):
299
if event.keyval==gtk.keysyms.F1:
300
self.sig_new(widget, event)
301
elif event.keyval==gtk.keysyms.F2:
302
self.sig_activate(widget, event)
303
elif event.keyval==gtk.keysyms.F3:
304
self.sig_edit(widget, event)
305
elif event.keyval == gtk.keysyms.Tab:
306
if self._view.modelfield.get(self._view.model) or \
307
not self.wid_text.get_text():
309
self.sig_activate(widget, event, leave=True)
313
def sig_changed(self, *args):
315
if self._view.modelfield.get(self._view.model):
316
self._view.modelfield.set_client(self._view.model, False)
317
self.display(self._view.model, self._view.modelfield)
320
def set_value(self, model, model_field):
321
pass # No update of the model, the model is updated in real time !
323
def display(self, model, model_field):
326
self.wid_text.set_text('')
328
super(many2one, self).display(model, model_field)
330
res = model_field.get_client(model)
331
self.wid_text.set_text((res and str(res)) or '')
332
self.but_open.set_sensitive(bool(res))
335
def _menu_open(self, obj, event):
336
if event.button == 3:
337
value = self._view.modelfield.get(self._view.model)
338
if not self._menu_loaded:
339
resrelate = rpc.session.rpc_exec_auth('/object', 'execute', 'ir.values', 'get', 'action', 'client_action_relate', [(self.model_type, False)], False, rpc.session.context)
340
resrelate = map(lambda x:x[2], resrelate)
341
self._menu_entries.append((None, None, None))
343
x['string'] = x['name']
344
f = lambda action: lambda x: self.click_and_relate(action)
345
self._menu_entries.append(('... '+x['name'], f(x), 0))
346
self._menu_loaded = True
349
for stock_id,callback,sensitivity in self._menu_entries:
351
item = gtk.ImageMenuItem(stock_id)
353
item.connect("activate",callback)
354
item.set_sensitive(bool(sensitivity or value))
356
item=gtk.SeparatorMenuItem()
359
menu.popup(None,None,None,event.button,event.time)
363
def click_and_relate(self, action):
367
id = self._view.modelfield.get(self._view.model)
369
common.message(_('You must select a record to use the relation !'))
371
screen = Screen(self.attrs['relation'])
373
act['domain'] = screen.current_model.expr_eval(act['domain'], check_load=False)
374
act['context'] = str(screen.current_model.expr_eval(act['context'], check_load=False))
375
obj = service.LocalService('action.main')
376
value = obj._exec_action(act, data, context)
379
def click_and_action(self, type):
380
id = self._view.modelfield.get(self._view.model)
381
obj = service.LocalService('action.main')
382
res = obj.exec_keyword(type, {'model':self.model_type, 'id': id or False, 'ids':[id], 'report_type': 'pdf'})
386
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: