Refactoring
- Better naming in model - Group extends list - Add an index to Group - New common windows for dialog of many2one, one2many and many2many - one2many and many2many dialog use the same screen than the widget - Reduce the number of option in Screen - Remove RPCProxy to handle logout exception on every server call - Better naming of event signals - Fix on_change detection for many2many for issue1400
This commit is contained in:
1 parent
00d12fd71c
commit
999f2737a0
43 files changed
+2468
-2766
No files matched your search
@@ -1,3 +1,13 @@
|
||||
* Refactoring:
|
||||
* Better naming in model
|
||||
* Group extends list
|
||||
* Add an index to Group
|
||||
* New common windows for dialog of many2one, one2many and many2many
|
||||
* one2many and many2many dialog use the same screen than the widget
|
||||
* Reduce the number of option in Screen
|
||||
* Remove RPCProxy to handle logout exception on every server call
|
||||
* Better naming of event signals
|
||||
* Fix on_change detection for many2many for issue1400
|
||||
* Add PySON to replace python string evaluation
|
||||
* Don't show "Spell Checking" option if gtkspell is not present
|
||||
* Use the same internal model for many2many and one2many fields
|
||||
|
||||
+19
-18
@@ -52,8 +52,7 @@ class Form(SignalEvent):
|
||||
|
||||
self.screen = Screen(self.model, self.window, view_type=view_type,
|
||||
context=self.context, view_ids=view_ids, domain=domain,
|
||||
hastoolbar=CONFIG['form.toolbar'], show_search=True,
|
||||
limit=limit, readonly=bool(auto_refresh), form=self,
|
||||
limit=limit, readonly=bool(auto_refresh),
|
||||
search_value=search_value)
|
||||
self.screen.signal_connect(self, 'record-message', self._record_message)
|
||||
self.screen.signal_connect(self, 'record-modified', self._record_modified)
|
||||
@@ -227,9 +226,9 @@ class Form(SignalEvent):
|
||||
return True
|
||||
|
||||
def update_attachment_count(self, reload=False):
|
||||
value = self.screen.current_model
|
||||
if value:
|
||||
attachment_count = value.get_attachment_count(reload=reload)
|
||||
record = self.screen.current_record
|
||||
if record:
|
||||
attachment_count = record.get_attachment_count(reload=reload)
|
||||
else:
|
||||
attachment_count = 0
|
||||
self.signal('attachment-count', attachment_count)
|
||||
@@ -296,19 +295,21 @@ class Form(SignalEvent):
|
||||
self.message_info(_('Records removed!'), 'green')
|
||||
|
||||
def sig_import(self, widget=None):
|
||||
fields = []
|
||||
while(self.screen.view_to_load):
|
||||
self.screen.load_view_to_load()
|
||||
win = WinImport(self.model, self.screen.fields, fields,
|
||||
parent=self.window)
|
||||
fields = {}
|
||||
for name, field in self.screen.group.fields.iteritems():
|
||||
fields[name] = field.attrs
|
||||
win = WinImport(self.model, fields, parent=self.window)
|
||||
win.run()
|
||||
|
||||
def sig_save_as(self, widget=None):
|
||||
fields = []
|
||||
while(self.screen.view_to_load):
|
||||
while self.screen.view_to_load:
|
||||
self.screen.load_view_to_load()
|
||||
win = WinExport(self.model, self.ids_get(),
|
||||
self.screen.fields, fields, parent=self.window,
|
||||
fields = {}
|
||||
for name, field in self.screen.group.fields.iteritems():
|
||||
fields[name] = field.attrs
|
||||
win = WinExport(self.model, self.ids_get(), fields, parent=self.window,
|
||||
context=self.context)
|
||||
win.run()
|
||||
|
||||
@@ -373,9 +374,9 @@ class Form(SignalEvent):
|
||||
else:
|
||||
obj_id = self.id_get()
|
||||
self.screen.search_filter()
|
||||
for model in self.screen.models:
|
||||
if model.id == obj_id:
|
||||
self.screen.current_model = model
|
||||
for record in self.screen.group:
|
||||
if record.id == obj_id:
|
||||
self.screen.current_record = record
|
||||
self.screen.display(set_cursor=True)
|
||||
break
|
||||
self.message_info('')
|
||||
@@ -383,8 +384,8 @@ class Form(SignalEvent):
|
||||
|
||||
def sig_action(self, keyword='form_action'):
|
||||
ids = self.ids_get()
|
||||
if self.screen.current_model:
|
||||
obj_id = self.screen.current_model.id
|
||||
if self.screen.current_record:
|
||||
obj_id = self.screen.current_record.id
|
||||
else:
|
||||
obj_id = False
|
||||
if self.screen.current_view.view_type == 'form':
|
||||
@@ -403,7 +404,7 @@ class Form(SignalEvent):
|
||||
if 'active_id' in ctx:
|
||||
del ctx['active_id']
|
||||
res = Action.exec_keyword(keyword, self.window, {
|
||||
'model': self.screen.resource,
|
||||
'model': self.screen.model_name,
|
||||
'id': obj_id or False,
|
||||
'ids': ids,
|
||||
}, context=ctx, alwaysask=True)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
"Preference"
|
||||
import gettext
|
||||
import gtk
|
||||
from tryton.rpc import RPCProxy
|
||||
import tryton.rpc as rpc
|
||||
import copy
|
||||
from tryton.gui.window.view_form.screen import Screen
|
||||
@@ -35,19 +34,13 @@ class Preference(object):
|
||||
|
||||
self.win.set_default_response(gtk.RESPONSE_OK)
|
||||
|
||||
user = RPCProxy('res.user')
|
||||
|
||||
args = ('model', 'res.user', 'get_preferences_fields_view',
|
||||
rpc.CONTEXT)
|
||||
try:
|
||||
res = user.get_preferences_fields_view(rpc.CONTEXT)
|
||||
res = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
if not common.process_exception(exception, parent):
|
||||
self.win.destroy()
|
||||
self.win = None
|
||||
return
|
||||
try:
|
||||
res = user.get_preferences_fields_view(rpc.CONTEXT)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, parent)
|
||||
res = common.process_exception(exception, parent, *args)
|
||||
if not res:
|
||||
self.win.destroy()
|
||||
self.win = None
|
||||
return
|
||||
@@ -59,15 +52,17 @@ class Preference(object):
|
||||
fields = res['fields']
|
||||
self.screen = Screen('res.user', self.win, view_type=[])
|
||||
self.screen.new(default=False)
|
||||
self.screen.add_view_custom(arch, fields, display=True)
|
||||
self.screen.add_view(arch, fields, display=True)
|
||||
|
||||
args = ('model', 'res.user', 'get_preferences', False, rpc.CONTEXT)
|
||||
try:
|
||||
preferences = user.get_preferences(False, rpc.CONTEXT)
|
||||
preferences = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, parent)
|
||||
self.win.destroy()
|
||||
raise
|
||||
self.screen.current_model.set(preferences)
|
||||
preferences = common.process_exception(exception, parent, *args)
|
||||
if not preferences:
|
||||
self.win.destroy()
|
||||
raise
|
||||
self.screen.current_record.set(preferences)
|
||||
|
||||
width, height = self.screen.screen_container.size_get()
|
||||
parent_width, parent_height = parent.get_size()
|
||||
@@ -85,7 +80,7 @@ class Preference(object):
|
||||
res = False
|
||||
while True:
|
||||
if self.win.run() == gtk.RESPONSE_OK:
|
||||
if self.screen.current_model.validate():
|
||||
if self.screen.current_record.validate():
|
||||
vals = copy.copy(self.screen.get(get_modifiedonly=True))
|
||||
if 'password' in vals:
|
||||
password = common.ask(_('Current Password:'),
|
||||
@@ -94,12 +89,14 @@ class Preference(object):
|
||||
break
|
||||
else:
|
||||
password = False
|
||||
user = RPCProxy('res.user')
|
||||
args = ('model', 'res.user', 'set_preferences', vals,
|
||||
password, rpc.CONTEXT)
|
||||
try:
|
||||
user.set_preferences(vals, password, rpc.CONTEXT)
|
||||
rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.win)
|
||||
continue
|
||||
if not common.process_exception(exception, self.win,
|
||||
*args):
|
||||
continue
|
||||
res = True
|
||||
break
|
||||
else:
|
||||
|
||||
@@ -402,9 +402,8 @@ class Tree(SignalEvent):
|
||||
return res
|
||||
|
||||
def sig_save_as(self, widget=None):
|
||||
win = WinExport(self.model, self.ids_get(),
|
||||
self.tree_res.fields, [], parent=self.window,
|
||||
context=self.context)
|
||||
win = WinExport(self.model, self.ids_get(), self.tree_res.fields,
|
||||
parent=self.window, context=self.context)
|
||||
win.run()
|
||||
|
||||
def sig_close(self):
|
||||
|
||||
@@ -146,7 +146,9 @@ class Action(object):
|
||||
self.screen = Screen(self.action['res_model'], self._window,
|
||||
view_type=self.action['view_mode'], context=self.context,
|
||||
view_ids=view_ids, domain=self.domain, readonly=True)
|
||||
alignment.add(self.screen.widget)
|
||||
self.screen.screen_container.alternate_view = True
|
||||
self.screen.switch_view(view_type=self.action['view_mode'])
|
||||
alignment.add(self.screen.screen_container.alternate_viewport)
|
||||
name = self.screen.current_view.title
|
||||
self.screen.signal_connect(self, 'record-message', self._sig_label)
|
||||
elif self.action['view_type'] == 'tree':
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from tryton.rpc import RPCProxy
|
||||
import tryton.rpc as rpc
|
||||
from tryton.common import DT_FORMAT, DHM_FORMAT, HM_FORMAT, datetime_strftime
|
||||
import tryton.common as common
|
||||
from tryton.pyson import PYSONDecoder
|
||||
import time
|
||||
import datetime
|
||||
@@ -10,7 +10,7 @@ from decimal import Decimal
|
||||
import logging
|
||||
|
||||
|
||||
class ModelField(object):
|
||||
class Field(object):
|
||||
'''
|
||||
get: return the values to write to the server
|
||||
get_client: return the value for the client widget (form_gtk)
|
||||
@@ -32,128 +32,128 @@ class CharField(object):
|
||||
self.internal = False
|
||||
self.default_attrs = {}
|
||||
|
||||
def sig_changed(self, model):
|
||||
if self.get_state_attrs(model).get('readonly', False):
|
||||
def sig_changed(self, record):
|
||||
if self.get_state_attrs(record).get('readonly', False):
|
||||
return
|
||||
if self.attrs.get('on_change', False):
|
||||
model.on_change(self.name, self.attrs['on_change'])
|
||||
record.on_change(self.name, self.attrs['on_change'])
|
||||
if self.attrs.get('change_default', False):
|
||||
model.cond_default(self.attrs['name'], self.get(model))
|
||||
model.on_change_with(self.name)
|
||||
record.cond_default(self.attrs['name'], self.get(record))
|
||||
record.on_change_with(self.name)
|
||||
|
||||
def domain_get(self, model):
|
||||
return model.expr_eval(self.attrs.get('domain', []))
|
||||
def domain_get(self, record):
|
||||
return record.expr_eval(self.attrs.get('domain', []))
|
||||
|
||||
def context_get(self, model, check_load=True, eval_context=True):
|
||||
def context_get(self, record, check_load=True, eval_context=True):
|
||||
context = {}
|
||||
context.update(self.parent.context)
|
||||
if eval_context:
|
||||
context.update(model.expr_eval(self.attrs.get('context', {}),
|
||||
context.update(record.expr_eval(self.attrs.get('context', {}),
|
||||
check_load=check_load))
|
||||
return context
|
||||
|
||||
def validate(self, model):
|
||||
def validate(self, record):
|
||||
res = True
|
||||
if bool(int(self.get_state_attrs(model).get('required') or 0)):
|
||||
if not self.get(model) \
|
||||
and not bool(int(self.get_state_attrs(model
|
||||
if bool(int(self.get_state_attrs(record).get('required') or 0)):
|
||||
if not self.get(record) \
|
||||
and not bool(int(self.get_state_attrs(record
|
||||
).get('readonly') or 0)):
|
||||
res = False
|
||||
self.get_state_attrs(model)['valid'] = res
|
||||
self.get_state_attrs(record)['valid'] = res
|
||||
return res
|
||||
|
||||
def set(self, model, value, modified=False):
|
||||
model.value[self.name] = value
|
||||
def set(self, record, value, modified=False):
|
||||
record.value[self.name] = value
|
||||
if modified:
|
||||
model.modified = True
|
||||
model.modified_fields.setdefault(self.name)
|
||||
record.modified = True
|
||||
record.modified_fields.setdefault(self.name)
|
||||
return True
|
||||
|
||||
def get(self, model, check_load=True, readonly=True, modified=False):
|
||||
return model.value.get(self.name, False) or False
|
||||
def get(self, record, check_load=True, readonly=True, modified=False):
|
||||
return record.value.get(self.name, False) or False
|
||||
|
||||
def get_eval(self, model, check_load=True):
|
||||
return self.get(model, check_load=check_load, readonly=True,
|
||||
def get_eval(self, record, check_load=True):
|
||||
return self.get(record, check_load=check_load, readonly=True,
|
||||
modified=False)
|
||||
|
||||
def set_client(self, model, value, force_change=False):
|
||||
internal = model.value.get(self.name, False)
|
||||
prev_modified = model.modified
|
||||
self.set(model, value)
|
||||
if (internal or False) != (model.value.get(self.name, False) or False):
|
||||
model.modified = True
|
||||
model.modified_fields.setdefault(self.name)
|
||||
def set_client(self, record, value, force_change=False):
|
||||
internal = record.value.get(self.name, False)
|
||||
prev_modified = record.modified
|
||||
self.set(record, value)
|
||||
if (internal or False) != (record.value.get(self.name, False) or False):
|
||||
record.modified = True
|
||||
record.modified_fields.setdefault(self.name)
|
||||
try:
|
||||
self.sig_changed(model)
|
||||
self.sig_changed(record)
|
||||
except:
|
||||
model.value[self.name] = internal
|
||||
model.modified = prev_modified
|
||||
record.value[self.name] = internal
|
||||
record.modified = prev_modified
|
||||
return
|
||||
model.signal('record-changed', model)
|
||||
record.signal('record-changed')
|
||||
|
||||
def get_client(self, model):
|
||||
return model.value[self.name] or False
|
||||
def get_client(self, record):
|
||||
return record.value.get(self.name) or False
|
||||
|
||||
def set_default(self, model, value, modified=False):
|
||||
res = self.set(model, value, modified=modified)
|
||||
def set_default(self, record, value, modified=False):
|
||||
res = self.set(record, value, modified=modified)
|
||||
return res
|
||||
|
||||
def set_on_change(self, model, value):
|
||||
return self.set(model, value, modified=True)
|
||||
def set_on_change(self, record, value):
|
||||
return self.set(record, value, modified=True)
|
||||
|
||||
def get_default(self, model):
|
||||
return self.get(model)
|
||||
def get_default(self, record):
|
||||
return self.get(record)
|
||||
|
||||
def create(self, model):
|
||||
def create(self, record):
|
||||
return False
|
||||
|
||||
def state_set(self, model, states=('readonly', 'required', 'invisible')):
|
||||
state_changes = model.expr_eval(self.attrs.get('states', {}),
|
||||
def state_set(self, record, states=('readonly', 'required', 'invisible')):
|
||||
state_changes = record.expr_eval(self.attrs.get('states', {}),
|
||||
check_load=False)
|
||||
for key in states:
|
||||
if key == 'readonly' and self.attrs.get(key, False):
|
||||
continue
|
||||
if key in state_changes:
|
||||
self.get_state_attrs(model)[key] = state_changes[key]
|
||||
self.get_state_attrs(record)[key] = state_changes[key]
|
||||
elif key in self.attrs:
|
||||
self.get_state_attrs(model)[key] = self.attrs[key]
|
||||
if model.mgroup.readonly:
|
||||
self.get_state_attrs(model)['readonly'] = True
|
||||
self.get_state_attrs(record)[key] = self.attrs[key]
|
||||
if record.group.readonly:
|
||||
self.get_state_attrs(record)['readonly'] = True
|
||||
if 'value' in state_changes:
|
||||
value = state_changes['value']
|
||||
if value:
|
||||
self.set(model, value, modified=True)
|
||||
self.set(record, value, modified=True)
|
||||
|
||||
def get_state_attrs(self, model):
|
||||
if self.name not in model.state_attrs:
|
||||
model.state_attrs[self.name] = self.attrs.copy()
|
||||
if model.mgroup.readonly:
|
||||
model.state_attrs[self.name]['readonly'] = True
|
||||
return model.state_attrs[self.name]
|
||||
def get_state_attrs(self, record):
|
||||
if self.name not in record.state_attrs:
|
||||
record.state_attrs[self.name] = self.attrs.copy()
|
||||
if record.group.readonly:
|
||||
record.state_attrs[self.name]['readonly'] = True
|
||||
return record.state_attrs[self.name]
|
||||
|
||||
def get_timestamp(self, model):
|
||||
def get_timestamp(self, record):
|
||||
return {}
|
||||
|
||||
|
||||
class SelectionField(CharField):
|
||||
|
||||
def set(self, model, value, modified=False):
|
||||
def set(self, record, value, modified=False):
|
||||
if isinstance(value, (list, tuple)):
|
||||
value = value[0]
|
||||
return super(SelectionField, self).set(model, value,
|
||||
return super(SelectionField, self).set(record, value,
|
||||
modified=modified)
|
||||
|
||||
|
||||
class DateTimeField(CharField):
|
||||
|
||||
def set_client(self, model, value, force_change=False):
|
||||
def set_client(self, record, value, force_change=False):
|
||||
if value:
|
||||
value = datetime.datetime(*time.strptime(value, DHM_FORMAT)[:6])
|
||||
return super(DateTimeField, self).set_client(model, value,
|
||||
return super(DateTimeField, self).set_client(record, value,
|
||||
force_change=force_change)
|
||||
|
||||
def get_client(self, model):
|
||||
value = super(DateTimeField, self).get_client(model)
|
||||
def get_client(self, record):
|
||||
value = super(DateTimeField, self).get_client(record)
|
||||
if not value:
|
||||
return False
|
||||
return datetime_strftime(value, DHM_FORMAT)
|
||||
@@ -161,14 +161,14 @@ class DateTimeField(CharField):
|
||||
|
||||
class DateField(CharField):
|
||||
|
||||
def set_client(self, model, value, force_change=False):
|
||||
def set_client(self, record, value, force_change=False):
|
||||
if value:
|
||||
value = datetime.date(*time.strptime(value, DT_FORMAT)[:3])
|
||||
return super(DateField, self).set_client(model, value,
|
||||
return super(DateField, self).set_client(record, value,
|
||||
force_change=force_change)
|
||||
|
||||
def get_client(self, model):
|
||||
value = super(DateField, self).get_client(model)
|
||||
def get_client(self, record):
|
||||
value = super(DateField, self).get_client(record)
|
||||
if not value:
|
||||
return False
|
||||
return datetime_strftime(value, DT_FORMAT)
|
||||
@@ -176,77 +176,78 @@ class DateField(CharField):
|
||||
|
||||
class FloatField(CharField):
|
||||
|
||||
def set_client(self, model, value, force_change=False):
|
||||
internal = model.value[self.name]
|
||||
prev_modified = model.modified
|
||||
self.set(model, value)
|
||||
digits = model.expr_eval(self.attrs.get('digits', (12, 2)))
|
||||
if abs(float(internal or 0.0) - float(model.value[self.name] or 0.0)) \
|
||||
def set_client(self, record, value, force_change=False):
|
||||
internal = record.value.get(self.name)
|
||||
prev_modified = record.modified
|
||||
self.set(record, value)
|
||||
digits = record.expr_eval(self.attrs.get('digits', (12, 2)))
|
||||
if abs(float(internal or 0.0) - float(record.value[self.name] or 0.0)) \
|
||||
>= (10.0**(-int(digits[1]))):
|
||||
if not self.get_state_attrs(model).get('readonly', False):
|
||||
model.modified = True
|
||||
model.modified_fields.setdefault(self.name)
|
||||
if not self.get_state_attrs(record).get('readonly', False):
|
||||
record.modified = True
|
||||
record.modified_fields.setdefault(self.name)
|
||||
try:
|
||||
self.sig_changed(model)
|
||||
self.sig_changed(record)
|
||||
except:
|
||||
model.value[self.name] = internal
|
||||
model.modified = prev_modified
|
||||
model.signal('record-changed', model)
|
||||
record.value[self.name] = internal
|
||||
record.modified = prev_modified
|
||||
record.signal('record-changed')
|
||||
|
||||
|
||||
class NumericField(CharField):
|
||||
|
||||
def set_client(self, model, value, force_change=False):
|
||||
def set_client(self, record, value, force_change=False):
|
||||
value = Decimal(str(value))
|
||||
internal = model.value[self.name]
|
||||
prev_modified = model.modified
|
||||
self.set(model, value)
|
||||
digits = model.expr_eval(self.attrs.get('digits', (12, 2)))
|
||||
if abs((internal or Decimal('0.0')) - (model.value[self.name] or Decimal('0.0'))) \
|
||||
internal = record.value.get(self.name)
|
||||
prev_modified = record.modified
|
||||
self.set(record, value)
|
||||
digits = record.expr_eval(self.attrs.get('digits', (12, 2)))
|
||||
if abs((internal or Decimal('0.0')) - \
|
||||
(record.value[self.name] or Decimal('0.0'))) \
|
||||
>= Decimal(str(10.0**(-int(digits[1])))):
|
||||
if not self.get_state_attrs(model).get('readonly', False):
|
||||
model.modified = True
|
||||
model.modified_fields.setdefault(self.name)
|
||||
if not self.get_state_attrs(record).get('readonly', False):
|
||||
record.modified = True
|
||||
record.modified_fields.setdefault(self.name)
|
||||
try:
|
||||
self.sig_changed(model)
|
||||
self.sig_changed(record)
|
||||
except:
|
||||
model.value[self.name] = internal
|
||||
model.modified = prev_modified
|
||||
record.value[self.name] = internal
|
||||
record.modified = prev_modified
|
||||
return
|
||||
model.signal('record-changed', model)
|
||||
record.signal('record-changed')
|
||||
|
||||
|
||||
class IntegerField(CharField):
|
||||
|
||||
def get(self, model, check_load=True, readonly=True, modified=False):
|
||||
return model.value.get(self.name, 0) or 0
|
||||
def get(self, record, check_load=True, readonly=True, modified=False):
|
||||
return record.value.get(self.name) or 0
|
||||
|
||||
def get_client(self, model):
|
||||
return model.value[self.name] or 0
|
||||
def get_client(self, record):
|
||||
return record.value.get(self.name) or 0
|
||||
|
||||
class BooleanField(CharField):
|
||||
|
||||
def set_client(self, model, value, force_change=False):
|
||||
def set_client(self, record, value, force_change=False):
|
||||
value = bool(value)
|
||||
internal = bool(model.value.get(self.name, False))
|
||||
prev_modified = model.modified
|
||||
self.set(model, value)
|
||||
if internal != bool(model.value.get(self.name, False)):
|
||||
model.modified = True
|
||||
model.modified_fields.setdefault(self.name)
|
||||
internal = bool(record.value.get(self.name, False))
|
||||
prev_modified = record.modified
|
||||
self.set(record, value)
|
||||
if internal != bool(record.value.get(self.name, False)):
|
||||
record.modified = True
|
||||
record.modified_fields.setdefault(self.name)
|
||||
try:
|
||||
self.sig_changed(model)
|
||||
self.sig_changed(record)
|
||||
except:
|
||||
model.value[self.name] = internal
|
||||
model.modified = prev_modified
|
||||
record.value[self.name] = internal
|
||||
record.modified = prev_modified
|
||||
return
|
||||
model.signal('record-changed', model)
|
||||
record.signal('record-changed')
|
||||
|
||||
def get(self, model, check_load=True, readonly=True, modified=False):
|
||||
return bool(model.value.get(self.name, False))
|
||||
def get(self, record, check_load=True, readonly=True, modified=False):
|
||||
return bool(record.value.get(self.name, False))
|
||||
|
||||
def get_client(self, model):
|
||||
return bool(model.value[self.name])
|
||||
def get_client(self, record):
|
||||
return bool(record.value.get(self.name))
|
||||
|
||||
|
||||
class M2OField(CharField):
|
||||
@@ -254,350 +255,358 @@ class M2OField(CharField):
|
||||
internal = (id, name)
|
||||
'''
|
||||
|
||||
def create(self, model):
|
||||
def create(self, record):
|
||||
return (False, '')
|
||||
|
||||
def get(self, model, check_load=True, readonly=True, modified=False):
|
||||
if model.value[self.name]:
|
||||
if isinstance(model.value[self.name], (int, basestring, long)):
|
||||
self.set(model, model.value[self.name])
|
||||
if isinstance(model.value[self.name], (int, basestring, long)):
|
||||
return model.value[self.name]
|
||||
return model.value[self.name][0] or False
|
||||
def get(self, record, check_load=True, readonly=True, modified=False):
|
||||
if record.value.get(self.name):
|
||||
if isinstance(record.value[self.name], (int, basestring, long)):
|
||||
self.set(record, record.value[self.name])
|
||||
if isinstance(record.value[self.name], (int, basestring, long)):
|
||||
return record.value[self.name]
|
||||
return record.value[self.name][0] or False
|
||||
return False
|
||||
|
||||
def get_client(self, model):
|
||||
#model._check_load()
|
||||
if model.value[self.name]:
|
||||
if isinstance(model.value[self.name], (int, basestring, long)):
|
||||
self.set(model, model.value[self.name])
|
||||
if isinstance(model.value[self.name], (int, basestring, long)):
|
||||
return model.value[self.name]
|
||||
return model.value[self.name][1]
|
||||
def get_client(self, record):
|
||||
if record.value.get(self.name):
|
||||
if isinstance(record.value[self.name], (int, basestring, long)):
|
||||
self.set(record, record.value[self.name])
|
||||
if isinstance(record.value[self.name], (int, basestring, long)):
|
||||
return record.value[self.name]
|
||||
return record.value[self.name][1]
|
||||
return False
|
||||
|
||||
def set(self, model, value, modified=False):
|
||||
def set(self, record, value, modified=False):
|
||||
if value and isinstance(value, (int, long)):
|
||||
rpc2 = RPCProxy(self.attrs['relation'])
|
||||
args = ('model', self.attrs['relation'], 'read', value,
|
||||
['rec_name'], rpc.CONTEXT)
|
||||
try:
|
||||
result = rpc2.read(value, ['rec_name'], rpc.CONTEXT)
|
||||
except:
|
||||
return
|
||||
result = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
result = common.process_exception(exception, record.window,
|
||||
*args)
|
||||
if not result:
|
||||
return
|
||||
value = value, result['rec_name']
|
||||
if value and len(value) != 2:
|
||||
value = (False, '')
|
||||
model.value[self.name + '.rec_name'] = ''
|
||||
record.value[self.name + '.rec_name'] = ''
|
||||
else:
|
||||
if value:
|
||||
model.value[self.name + '.rec_name'] = value[1]
|
||||
record.value[self.name + '.rec_name'] = value[1]
|
||||
else:
|
||||
model.value[self.name + '.rec_name'] = ''
|
||||
model.value[self.name] = value or (False, '')
|
||||
record.value[self.name + '.rec_name'] = ''
|
||||
record.value[self.name] = value or (False, '')
|
||||
if modified:
|
||||
model.modified = True
|
||||
model.modified_fields.setdefault(self.name)
|
||||
record.modified = True
|
||||
record.modified_fields.setdefault(self.name)
|
||||
|
||||
def set_client(self, model, value, force_change=False):
|
||||
internal = model.value[self.name]
|
||||
prev_modified = model.modified
|
||||
self.set(model, value)
|
||||
if (internal[0] or False) != (model.value[self.name][0] or False):
|
||||
model.modified = True
|
||||
model.modified_fields.setdefault(self.name)
|
||||
def set_client(self, record, value, force_change=False):
|
||||
internal = record.value.get(self.name)
|
||||
prev_modified = record.modified
|
||||
self.set(record, value)
|
||||
if (internal[0] or False) != (record.value[self.name][0] or False):
|
||||
record.modified = True
|
||||
record.modified_fields.setdefault(self.name)
|
||||
try:
|
||||
self.sig_changed(model)
|
||||
self.sig_changed(record)
|
||||
except:
|
||||
model.value[self.name] = internal
|
||||
model.modified = prev_modified
|
||||
record.value[self.name] = internal
|
||||
record.modified = prev_modified
|
||||
return
|
||||
model.signal('record-changed', model)
|
||||
record.signal('record-changed')
|
||||
elif force_change:
|
||||
try:
|
||||
self.sig_changed(model)
|
||||
self.sig_changed(record)
|
||||
except:
|
||||
model.value[self.name] = internal
|
||||
record.value[self.name] = internal
|
||||
return
|
||||
model.signal('record-changed', model)
|
||||
record.signal('record-changed')
|
||||
|
||||
def context_get(self, model, check_load=True, eval_context=True):
|
||||
context = super(M2OField, self).context_get(model,
|
||||
def context_get(self, record, check_load=True, eval_context=True):
|
||||
context = super(M2OField, self).context_get(record,
|
||||
check_load=check_load, eval_context=eval_context)
|
||||
if eval_context and self.attrs.get('datetime_field'):
|
||||
context['_datetime'] = model.get_eval(
|
||||
context['_datetime'] = record.get_eval(
|
||||
check_load=check_load)[self.attrs.get('datetime_field')]
|
||||
return context
|
||||
|
||||
|
||||
class O2MField(CharField):
|
||||
'''
|
||||
internal = ModelRecordGroup of the related objects
|
||||
internal = Group of the related objects
|
||||
'''
|
||||
|
||||
def __init__(self, parent, attrs):
|
||||
super(O2MField, self).__init__(parent, attrs)
|
||||
self.context = {}
|
||||
|
||||
def create(self, model):
|
||||
from group import ModelRecordGroup
|
||||
mod = ModelRecordGroup(self.attrs['relation'], {}, model.window,
|
||||
parent=model, parent_name=self.attrs.get('relation_field', ''),
|
||||
def create(self, record):
|
||||
from group import Group
|
||||
group = Group(self.attrs['relation'], {}, record.window,
|
||||
parent=record, parent_name=self.attrs.get('relation_field', ''),
|
||||
context=self.context,
|
||||
parent_datetime_field=self.attrs.get('datetime_field'))
|
||||
mod.signal_connect(mod, 'model-changed', self._model_changed)
|
||||
return mod
|
||||
group.signal_connect(group, 'group-changed', self._group_changed)
|
||||
return group
|
||||
|
||||
def _model_changed(self, group, model):
|
||||
if model.modified:
|
||||
model.parent.modified = True
|
||||
model.parent.modified_fields.setdefault(self.name)
|
||||
self.sig_changed(model.parent)
|
||||
model.parent.signal('record-changed', model.parent)
|
||||
def _group_changed(self, group, record):
|
||||
record.parent.modified = True
|
||||
record.parent.modified_fields.setdefault(self.name)
|
||||
self.sig_changed(record.parent)
|
||||
record.parent.signal('record-changed')
|
||||
|
||||
def get_client(self, model):
|
||||
return model.value[self.name]
|
||||
def get_client(self, record):
|
||||
return record.value.get(self.name)
|
||||
|
||||
def get(self, model, check_load=True, readonly=True, modified=False):
|
||||
if not model.value[self.name]:
|
||||
def get(self, record, check_load=True, readonly=True, modified=False):
|
||||
if record.value.get(self.name) is None:
|
||||
return []
|
||||
result = [('add', [])]
|
||||
for model2 in model.value[self.name].models:
|
||||
if model2.id > 0:
|
||||
values = model2.get(check_load=check_load, get_readonly=readonly,
|
||||
for record2 in record.value[self.name]:
|
||||
if record2.id > 0:
|
||||
values = record2.get(check_load=check_load, get_readonly=readonly,
|
||||
get_modifiedonly=modified)
|
||||
if model2.is_modified() and values:
|
||||
result.append(('write', model2.id, values))
|
||||
if record2.is_modified() and values:
|
||||
result.append(('write', record2.id, values))
|
||||
else:
|
||||
result[0][1].append(model2.id)
|
||||
result[0][1].append(record2.id)
|
||||
else:
|
||||
result.append(('create',
|
||||
model2.get(check_load=check_load, get_readonly=readonly)))
|
||||
if model.value[self.name].model_removed:
|
||||
record2.get(check_load=check_load, get_readonly=readonly)))
|
||||
if record.value[self.name].record_removed:
|
||||
result.append(('unlink', [x.id for x in \
|
||||
model.value[self.name].model_removed]))
|
||||
if model.value[self.name].model_deleted:
|
||||
record.value[self.name].record_removed]))
|
||||
if record.value[self.name].record_deleted:
|
||||
result.append(('delete', [x.id for x in \
|
||||
model.value[self.name].model_deleted]))
|
||||
record.value[self.name].record_deleted]))
|
||||
return result
|
||||
|
||||
def get_timestamp(self, model):
|
||||
if not model.value[self.name]:
|
||||
def get_timestamp(self, record):
|
||||
if record.value.get(self.name) is None:
|
||||
return {}
|
||||
result = {}
|
||||
for model2 in (model.value[self.name].models \
|
||||
+ model.value[self.name].model_removed \
|
||||
+ model.value[self.name].model_deleted):
|
||||
result.update(model2.get_timestamp())
|
||||
for record2 in (record.value[self.name] \
|
||||
+ record.value[self.name].record_removed \
|
||||
+ record.value[self.name].record_deleted):
|
||||
result.update(record2.get_timestamp())
|
||||
return result
|
||||
|
||||
def get_eval(self, model, check_load=True):
|
||||
def get_eval(self, record, check_load=True):
|
||||
result = []
|
||||
if not model.value[self.name]:
|
||||
if record.value.get(self.name) is None:
|
||||
return []
|
||||
for model2 in model.value[self.name].models:
|
||||
result.append(model2.get_eval(check_load=check_load))
|
||||
for record2 in record.value[self.name]:
|
||||
result.append(record2.get_eval(check_load=check_load))
|
||||
return result
|
||||
|
||||
def set(self, model, value, modified=False):
|
||||
from group import ModelRecordGroup
|
||||
mod = ModelRecordGroup(self.attrs['relation'], {}, model.window,
|
||||
parent=model, parent_name=self.attrs.get('relation_field', ''),
|
||||
def set(self, record, value, modified=False):
|
||||
from group import Group
|
||||
group = record.value.get(self.name)
|
||||
if group is not None:
|
||||
group.signal_unconnect(group)
|
||||
group = Group(self.attrs['relation'], {}, record.window,
|
||||
parent=record, parent_name=self.attrs.get('relation_field', ''),
|
||||
context=self.context,
|
||||
parent_datetime_field=self.attrs.get('datetime_field'))
|
||||
mod.signal_connect(mod, 'model-changed', self._model_changed)
|
||||
mod.model_deleted.extend(x for x in model.value[self.name].models
|
||||
if x.id > 0)
|
||||
mod.model_deleted.extend(model.value[self.name].model_deleted)
|
||||
mod.model_removed.extend(model.value[self.name].model_removed)
|
||||
model.value[self.name] = mod
|
||||
model.value[self.name].load(value, display=False)
|
||||
record.value[self.name] = group
|
||||
record.value[self.name].load(value, display=False)
|
||||
group.signal_connect(group, 'group-changed', self._group_changed)
|
||||
if modified:
|
||||
model.modified = True
|
||||
model.modified_fields.setdefault(self.name)
|
||||
record.modified = True
|
||||
record.modified_fields.setdefault(self.name)
|
||||
|
||||
def set_client(self, model, value, force_change=False):
|
||||
self.set(model, value)
|
||||
model.signal('record-changed', model)
|
||||
def set_client(self, record, value, force_change=False):
|
||||
pass
|
||||
|
||||
def set_default(self, model, value, modified=False):
|
||||
from group import ModelRecordGroup
|
||||
def set_default(self, record, value, modified=False):
|
||||
from group import Group
|
||||
|
||||
if value and len(value) and isinstance(value[0], (int, long)):
|
||||
return self.set(model, value, modified=modified)
|
||||
return self.set(record, value, modified=modified)
|
||||
|
||||
fields = {}
|
||||
if value and len(value):
|
||||
context = self.context_get(model)
|
||||
rpc2 = RPCProxy(self.attrs['relation'])
|
||||
context = self.context_get(record)
|
||||
field_names = []
|
||||
for val in value:
|
||||
for fieldname in val.keys():
|
||||
if fieldname not in field_names:
|
||||
field_names.append(fieldname)
|
||||
args = ('model', self.attrs['relation'], 'fields_get',
|
||||
field_names, context)
|
||||
try:
|
||||
fields_name = []
|
||||
for val in value:
|
||||
for fieldname in val.keys():
|
||||
if fieldname not in fields_name:
|
||||
fields_name.append(fieldname)
|
||||
fields = rpc2.fields_get(fields_name, context)
|
||||
except:
|
||||
return False
|
||||
fields = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
fields = common.process_exception(exception, record.window,
|
||||
*args)
|
||||
if not fields:
|
||||
return False
|
||||
|
||||
mod = ModelRecordGroup(
|
||||
self.attrs['relation'], fields, model.window, parent=model,
|
||||
group = record.value.get(self.name)
|
||||
if group is not None:
|
||||
group.signal_unconnect(group)
|
||||
group = Group(
|
||||
self.attrs['relation'], fields, record.window, parent=record,
|
||||
parent_name=self.attrs.get('relation_field', ''),
|
||||
context=self.context,
|
||||
parent_datetime_field=self.attrs.get('datetime_field'))
|
||||
mod.signal_connect(model.value[self.name],
|
||||
'model-changed', self._model_changed)
|
||||
mod.model_deleted.extend(x for x in model.value[self.name].models
|
||||
group.signal_connect(group,
|
||||
'group-changed', self._group_changed)
|
||||
group.record_deleted.extend(x for x in record.value[self.name]
|
||||
if x.id > 0)
|
||||
mod.model_deleted.extend(model.value[self.name].model_deleted)
|
||||
mod.model_removed.extend(model.value[self.name].model_removed)
|
||||
model.value[self.name] = mod
|
||||
mod = None
|
||||
for record in (value or []):
|
||||
mod = model.value[self.name].model_new(default=False)
|
||||
mod.set_default(record, modified=modified)
|
||||
model.value[self.name].model_add(mod)
|
||||
model.value[self.name].current_model = mod
|
||||
#mod.signal('record-changed')
|
||||
group.record_deleted.extend(record.value[self.name].record_deleted)
|
||||
group.record_removed.extend(record.value[self.name].record_removed)
|
||||
record.value[self.name] = group
|
||||
for vals in (value or []):
|
||||
new_record = record.value[self.name].new(default=False)
|
||||
new_record.set_default(vals, modified=modified)
|
||||
group.add(new_record)
|
||||
return True
|
||||
|
||||
def set_on_change(self, model, value):
|
||||
def set_on_change(self, record, value):
|
||||
if isinstance(value, (list, tuple)):
|
||||
return self.set(model, value, modified=True)
|
||||
return self.set(record, value, modified=True)
|
||||
|
||||
if value and (value.get('add') or value.get('update')):
|
||||
context = self.context_get(model)
|
||||
rpc2 = RPCProxy(self.attrs['relation'])
|
||||
context = self.context_get(record)
|
||||
field_names = []
|
||||
for val in (value.get('add', []) + value.get('update', [])):
|
||||
for fieldname in val.keys():
|
||||
if fieldname not in field_names:
|
||||
field_names.append(fieldname)
|
||||
args = ('model', self.attrs['relation'], 'fields_get',
|
||||
field_names, context)
|
||||
try:
|
||||
fields_name = []
|
||||
for val in (value.get('add', []) + value.get('update', [])):
|
||||
for fieldname in val.keys():
|
||||
if fieldname not in fields_name:
|
||||
fields_name.append(fieldname)
|
||||
fields = rpc2.fields_get(fields_name, context)
|
||||
except:
|
||||
return False
|
||||
fields = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
fields = common.process_exception(exception, record.window,
|
||||
*args)
|
||||
if not fields:
|
||||
return False
|
||||
|
||||
to_remove = []
|
||||
for mod in model.value[self.name]:
|
||||
if not mod.id:
|
||||
to_remove.append(mod)
|
||||
for record2 in record.value[self.name]:
|
||||
if not record2.id:
|
||||
to_remove.append(record2)
|
||||
if value and value.get('remove'):
|
||||
for model_id in value['remove']:
|
||||
mod = model.value[self.name].get_by_id(model_id)
|
||||
if mod:
|
||||
to_remove.append(mod)
|
||||
for mod in to_remove:
|
||||
model.value[self.name].remove(mod, signal=False)
|
||||
for record_id in value['remove']:
|
||||
record2 = record.value[self.name].get(record_id)
|
||||
if record2 is not None:
|
||||
to_remove.append(record2)
|
||||
for record2 in to_remove:
|
||||
record.value[self.name].remove(record2, signal=False)
|
||||
|
||||
mod = None
|
||||
if value and value.get('add') or value.get('update', []):
|
||||
model.value[self.name].add_fields(fields, model.value[self.name],
|
||||
signal=False)
|
||||
for record in value.get('add', []):
|
||||
mod = model.value[self.name].model_new(default=False)
|
||||
model.value[self.name].model_add(mod)
|
||||
mod.set(record, modified=True, signal=False)
|
||||
record.value[self.name].add_fields(fields, signal=False)
|
||||
for vals in value.get('add', []):
|
||||
new_record = record.value[self.name].new(default=False,
|
||||
signal=False)
|
||||
record.value[self.name].add(new_record)
|
||||
new_record.set(vals, modified=True, signal=False)
|
||||
|
||||
for record in value.get('update', []):
|
||||
if 'id' not in record:
|
||||
for vals in value.get('update', []):
|
||||
if 'id' not in vals:
|
||||
continue
|
||||
mod = model.value[self.name].get_by_id(record['id'])
|
||||
if mod:
|
||||
mod.set(record, modified=True, signal=False)
|
||||
model.value[self.name].current_model = mod
|
||||
record2 = record.value[self.name].get(vals['id'])
|
||||
if record2 is not None:
|
||||
record2.set(vals, modified=True, signal=False)
|
||||
return True
|
||||
|
||||
def get_default(self, model):
|
||||
res = [x.get_default() for x in model.value[self.name].models or []]
|
||||
def get_default(self, record):
|
||||
res = [x.get_default() for x in record.value.get(self.name) or []]
|
||||
return res
|
||||
|
||||
def validate(self, model):
|
||||
def validate(self, record):
|
||||
res = True
|
||||
for model2 in model.value[self.name].models:
|
||||
if not model2.loaded:
|
||||
for record2 in record.value[self.name]:
|
||||
if not record2.loaded:
|
||||
continue
|
||||
if not model2.validate():
|
||||
if not model2.is_modified():
|
||||
model.value[self.name].models.remove(model2)
|
||||
if not record2.validate():
|
||||
if not record2.is_modified():
|
||||
record.value[self.name].remove(record2)
|
||||
else:
|
||||
res = False
|
||||
if not super(O2MField, self).validate(model):
|
||||
if not super(O2MField, self).validate(record):
|
||||
res = False
|
||||
self.get_state_attrs(model)['valid'] = res
|
||||
self.get_state_attrs(record)['valid'] = res
|
||||
return res
|
||||
|
||||
def state_set(self, model, states=('readonly', 'required', 'invisible')):
|
||||
super(O2MField, self).state_set(model, states=states)
|
||||
if self.get_state_attrs(model).get('readonly', False):
|
||||
model.value[self.name].readonly = True
|
||||
def state_set(self, record, states=('readonly', 'required', 'invisible')):
|
||||
super(O2MField, self).state_set(record, states=states)
|
||||
if self.get_state_attrs(record).get('readonly', False):
|
||||
record.value[self.name].readonly = True
|
||||
else:
|
||||
model.value[self.name].readonly = False
|
||||
record.value[self.name].readonly = False
|
||||
|
||||
def get_removed_ids(self, model):
|
||||
return [x.id for x in model.value[self.name].model_removed]
|
||||
def get_removed_ids(self, record):
|
||||
return [x.id for x in record.value[self.name].record_removed]
|
||||
|
||||
|
||||
class M2MField(O2MField):
|
||||
|
||||
def get_default(self, model):
|
||||
return [x.id for x in model.value[self.name].models
|
||||
if x.id > 0]
|
||||
def get_default(self, record):
|
||||
return [x.id for x in record.value.get(self.name) or [] if x.id > 0]
|
||||
|
||||
def get_eval(self, model, check_load=True):
|
||||
return [x.id for x in model.value[self.name].models]
|
||||
def get_eval(self, record, check_load=True):
|
||||
return [x.id for x in record.value.get(self.name) or []]
|
||||
|
||||
def set(self, model, value, modified=False):
|
||||
from group import ModelRecordGroup
|
||||
mod = ModelRecordGroup(self.attrs['relation'], {}, model.window,
|
||||
parent=model, parent_name=self.attrs.get('relation_field', ''),
|
||||
def set(self, record, value, modified=False):
|
||||
from group import Group
|
||||
group = record.value.get(self.name)
|
||||
if group is not None:
|
||||
group.signal_unconnect(group)
|
||||
group = Group(self.attrs['relation'], {}, record.window,
|
||||
parent=record, parent_name=self.attrs.get('relation_field', ''),
|
||||
context=self.context,
|
||||
parent_datetime_field=self.attrs.get('datetime_field'))
|
||||
mod.signal_connect(mod, 'model-changed', self._model_changed)
|
||||
mod.model_removed.extend(model.value[self.name].models)
|
||||
mod.model_deleted.extend(model.value[self.name].model_deleted)
|
||||
mod.model_removed.extend(model.value[self.name].model_removed)
|
||||
model.value[self.name] = mod
|
||||
model.value[self.name].load(value, display=False)
|
||||
if record.value.get(self.name):
|
||||
group.record_removed.extend(record.value[self.name])
|
||||
group.record_deleted.extend(record.value[self.name].record_deleted)
|
||||
group.record_removed.extend(record.value[self.name].record_removed)
|
||||
record.value[self.name] = group
|
||||
record.value[self.name].load(value, display=False)
|
||||
group.signal_connect(group, 'group-changed', self._group_changed)
|
||||
if modified:
|
||||
model.modified = True
|
||||
model.modified_fields.setdefault(self.name)
|
||||
record.modified = True
|
||||
record.modified_fields.setdefault(self.name)
|
||||
|
||||
|
||||
class ReferenceField(CharField):
|
||||
|
||||
def get_client(self, model):
|
||||
if model.value[self.name]:
|
||||
return model.value[self.name]
|
||||
def get_client(self, record):
|
||||
if record.value.get(self.name):
|
||||
return record.value[self.name]
|
||||
return False
|
||||
|
||||
def get(self, model, check_load=True, readonly=True, modified=False):
|
||||
if model.value[self.name]:
|
||||
if isinstance(model.value[self.name][1], (list, tuple)):
|
||||
return '%s,%s' % (model.value[self.name][0],
|
||||
str(model.value[self.name][1][0]))
|
||||
def get(self, record, check_load=True, readonly=True, modified=False):
|
||||
if record.value.get(self.name):
|
||||
if isinstance(record.value[self.name][1], (list, tuple)):
|
||||
return '%s,%s' % (record.value[self.name][0],
|
||||
str(record.value[self.name][1][0]))
|
||||
else:
|
||||
return '%s,%s' % (model.value[self.name][0],
|
||||
str(model.value[self.name][1]))
|
||||
return '%s,%s' % (record.value[self.name][0],
|
||||
str(record.value[self.name][1]))
|
||||
return False
|
||||
|
||||
def set_client(self, model, value, force_change=False):
|
||||
internal = model.value[self.name]
|
||||
prev_modified = model.modified
|
||||
#model.value[self.name] = value
|
||||
self.set(model, value)
|
||||
if (internal or False) != (model.value[self.name] or False):
|
||||
model.modified = True
|
||||
model.modified_fields.setdefault(self.name)
|
||||
def set_client(self, record, value, force_change=False):
|
||||
internal = record.value.get(self.name)
|
||||
prev_modified = record.modified
|
||||
self.set(record, value)
|
||||
if (internal or False) != (record.value[self.name] or False):
|
||||
record.modified = True
|
||||
record.modified_fields.setdefault(self.name)
|
||||
try:
|
||||
self.sig_changed(model)
|
||||
self.sig_changed(record)
|
||||
except:
|
||||
model.value[self.name] = internal
|
||||
model.modified = prev_modified
|
||||
record.value[self.name] = internal
|
||||
record.modified = prev_modified
|
||||
return
|
||||
model.signal('record-changed', model)
|
||||
record.signal('record-changed')
|
||||
|
||||
def set(self, model, value, modified=False):
|
||||
def set(self, record, value, modified=False):
|
||||
if not value:
|
||||
model.value[self.name] = False
|
||||
record.value[self.name] = False
|
||||
return
|
||||
ref_model, (ref_id, ref_str) = value
|
||||
if ref_model:
|
||||
@@ -605,28 +614,32 @@ class ReferenceField(CharField):
|
||||
if not ref_id:
|
||||
ref_str = ''
|
||||
if not ref_str and ref_id:
|
||||
rpc2 = RPCProxy(ref_model)
|
||||
args = ('model', ref_model, 'read', ref_id,
|
||||
['rec_name'], rpc.CONTEXT)
|
||||
try:
|
||||
result = rpc2.read(ref_id, ['rec_name'],
|
||||
rpc.CONTEXT)['rec_name']
|
||||
except:
|
||||
return
|
||||
result = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
result = common.process_exception(exception, record.window,
|
||||
*args)
|
||||
if not result:
|
||||
return
|
||||
result = result['rec_name']
|
||||
if result:
|
||||
model.value[self.name] = ref_model, (ref_id, result)
|
||||
model.value[self.name + '.rec_name'] = result
|
||||
record.value[self.name] = ref_model, (ref_id, result)
|
||||
record.value[self.name + '.rec_name'] = result
|
||||
else:
|
||||
model.value[self.name] = ref_model, (0, '')
|
||||
model.value[self.name + '.rec_name'] = ''
|
||||
record.value[self.name] = ref_model, (0, '')
|
||||
record.value[self.name + '.rec_name'] = ''
|
||||
else:
|
||||
model.value[self.name] = ref_model, (ref_id, ref_str)
|
||||
model.value[self.name + '.rec_name'] = ref_str
|
||||
record.value[self.name] = ref_model, (ref_id, ref_str)
|
||||
record.value[self.name + '.rec_name'] = ref_str
|
||||
else:
|
||||
model.value[self.name] = ref_model, (ref_id, ref_id)
|
||||
if self.name + '.rec_name' in model.value:
|
||||
del model.value[self.name + '.rec_name']
|
||||
record.value[self.name] = ref_model, (ref_id, ref_id)
|
||||
if self.name + '.rec_name' in record.value:
|
||||
del record.value[self.name + '.rec_name']
|
||||
if modified:
|
||||
model.modified = True
|
||||
model.modified_fields.setdefault(self.name)
|
||||
record.modified = True
|
||||
record.modified_fields.setdefault(self.name)
|
||||
|
||||
TYPES = {
|
||||
'char': CharField,
|
||||
|
||||
@@ -1,120 +1,114 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from tryton.rpc import RPCProxy
|
||||
import tryton.rpc as rpc
|
||||
from record import ModelRecord
|
||||
import field
|
||||
from record import Record
|
||||
from field import Field, O2MField
|
||||
from tryton.signal_event import SignalEvent
|
||||
import tryton.common as common
|
||||
|
||||
|
||||
class ModelList(list):
|
||||
def __init__(self, screen):
|
||||
super(ModelList, self).__init__()
|
||||
self.lock_signal = False
|
||||
self.__screen = screen
|
||||
class Group(SignalEvent, list):
|
||||
|
||||
def insert(self, pos, obj):
|
||||
if pos >= 1:
|
||||
self.__getitem__(pos - 1).next[id(self)] = obj
|
||||
if pos < self.__len__():
|
||||
obj.next[id(self)] = self.__getitem__(pos)
|
||||
else:
|
||||
obj.next[id(self)] = None
|
||||
super(ModelList, self).insert(pos, obj)
|
||||
if not self.lock_signal:
|
||||
self.__screen.signal('record-changed', ('record-added', pos))
|
||||
|
||||
def append(self, obj):
|
||||
if self.__len__() >= 1:
|
||||
self.__getitem__(self.__len__() - 1).next[id(self)] = obj
|
||||
obj.next[id(self)] = None
|
||||
super(ModelList, self).append(obj)
|
||||
if not self.lock_signal:
|
||||
self.__screen.signal('record-changed', ('record-added', -1))
|
||||
|
||||
def remove(self, obj):
|
||||
idx = self.index(obj)
|
||||
if idx >= 1:
|
||||
if idx + 1 < self.__len__():
|
||||
self.__getitem__(idx - 1).next[id(self)] = self.__getitem__(idx + 1)
|
||||
else:
|
||||
self.__getitem__(idx - 1).next[id(self)] = None
|
||||
super(ModelList, self).remove(obj)
|
||||
if not self.lock_signal:
|
||||
self.__screen.signal('record-changed', ('record-removed', idx))
|
||||
|
||||
def clear(self):
|
||||
while self:
|
||||
self.pop()
|
||||
if not self.lock_signal:
|
||||
self.__screen.signal('record-changed',
|
||||
('record-removed', len(self)))
|
||||
|
||||
def move(self, obj, pos):
|
||||
self.lock_signal = True
|
||||
if self.__len__() > pos:
|
||||
idx = self.index(obj)
|
||||
self.remove(obj)
|
||||
if pos > idx:
|
||||
pos -= 1
|
||||
self.insert(pos, obj)
|
||||
else:
|
||||
self.remove(obj)
|
||||
self.append(obj)
|
||||
self.lock_signal = False
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
super(ModelList, self).__setitem__(key, value)
|
||||
if not self.lock_signal:
|
||||
self.__screen.signal('record-changed', ('record-changed', key))
|
||||
|
||||
|
||||
class ModelRecordGroup(SignalEvent):
|
||||
|
||||
def __init__(self, resource, fields, window, ids=None, parent=None,
|
||||
def __init__(self, model_name, fields, window, ids=None, parent=None,
|
||||
parent_name='', context=None, readonly=False,
|
||||
parent_datetime_field=None):
|
||||
super(ModelRecordGroup, self).__init__()
|
||||
super(Group, self).__init__()
|
||||
self.lock_signal = False
|
||||
self.window = window
|
||||
self.parent = parent
|
||||
self.parent_name = parent_name
|
||||
self.parent_datetime_field = parent_datetime_field
|
||||
self._context = context or {}
|
||||
self.resource = resource
|
||||
self.rpc = RPCProxy(resource)
|
||||
self.fields = fields
|
||||
self.mfields = {}
|
||||
ModelRecordGroup.mfields_load(fields.keys(), self)
|
||||
self.models = ModelList(self)
|
||||
self.model_name = model_name
|
||||
self.fields = {}
|
||||
self.load_fields(fields)
|
||||
self.current_idx = None
|
||||
self.load(ids)
|
||||
self.model_removed = []
|
||||
self.model_deleted = []
|
||||
self.record_removed = []
|
||||
self.record_deleted = []
|
||||
self.on_write = set()
|
||||
self.readonly = readonly
|
||||
if self._context.get('_datetime'):
|
||||
self.readonly = True
|
||||
self.__id2record = {}
|
||||
|
||||
def insert(self, pos, record):
|
||||
if pos >= 1:
|
||||
self.__getitem__(pos - 1).next[id(self)] = record
|
||||
if pos < self.__len__():
|
||||
record.next[id(self)] = self.__getitem__(pos)
|
||||
else:
|
||||
record.next[id(self)] = None
|
||||
super(Group, self).insert(pos, record)
|
||||
self.__id2record[record.id] = record
|
||||
if not self.lock_signal:
|
||||
self.signal('group-list-changed', ('record-added', pos))
|
||||
|
||||
def append(self, record):
|
||||
if self.__len__() >= 1:
|
||||
self.__getitem__(self.__len__() - 1).next[id(self)] = record
|
||||
record.next[id(self)] = None
|
||||
super(Group, self).append(record)
|
||||
self.__id2record[record.id] = record
|
||||
if not self.lock_signal:
|
||||
self.signal('group-list-changed', ('record-added', -1))
|
||||
|
||||
def _remove(self, record):
|
||||
idx = self.index(record)
|
||||
if idx >= 1:
|
||||
if idx + 1 < self.__len__():
|
||||
self.__getitem__(idx - 1).next[id(self)] = \
|
||||
self.__getitem__(idx + 1)
|
||||
else:
|
||||
self.__getitem__(idx - 1).next[id(self)] = None
|
||||
super(Group, self).remove(record)
|
||||
del self.__id2record[record.id]
|
||||
if not self.lock_signal:
|
||||
self.signal('group-list-changed', ('record-removed', idx))
|
||||
|
||||
def clear(self):
|
||||
while len(self):
|
||||
self.pop()
|
||||
if not self.lock_signal:
|
||||
self.signal('group-list-changed', ('record-removed', len(self)))
|
||||
self.record_removed = []
|
||||
self.record_deleted = []
|
||||
|
||||
def move(self, record, pos):
|
||||
self.lock_signal = True
|
||||
if self.__len__() > pos:
|
||||
idx = self.index(record)
|
||||
self._remove(record)
|
||||
if pos > idx:
|
||||
pos -= 1
|
||||
self.insert(pos, record)
|
||||
else:
|
||||
self._remove(record)
|
||||
self.append(record)
|
||||
self.lock_signal = False
|
||||
|
||||
def __setitem__(self, i, value):
|
||||
super(Group, self).__setitem__(i, value)
|
||||
if not self.lock_signal:
|
||||
self.signal('group-list-changed', ('record-changed', key))
|
||||
|
||||
def __repr__(self):
|
||||
return '<ModelRecordGroup %s at %s>' % (self.resource, id(self))
|
||||
return '<Group %s at %s>' % (self.model_name, id(self))
|
||||
|
||||
@staticmethod
|
||||
def mfields_load(fkeys, models):
|
||||
for fname in fkeys:
|
||||
fvalue = models.fields[fname]
|
||||
modelfield = field.ModelField(fvalue['type'])
|
||||
fvalue['name'] = fname
|
||||
models.mfields[fname] = modelfield(models, fvalue)
|
||||
if isinstance(models.mfields[fname], field.O2MField) \
|
||||
and '_datetime' in models._context:
|
||||
models.mfields[fname].context.update({
|
||||
'_datetime': models._context['_datetime'],
|
||||
def load_fields(self, fields):
|
||||
for name, attr in fields.iteritems():
|
||||
field = Field(attr['type'])
|
||||
attr['name'] = name
|
||||
self.fields[name] = field(self, attr)
|
||||
if isinstance(self.fields[name], O2MField) \
|
||||
and '_datetime' in self._context:
|
||||
self.fields[name].context.update({
|
||||
'_datetime': self._context['_datetime'],
|
||||
})
|
||||
|
||||
def save(self):
|
||||
for model in self.models:
|
||||
saved = model.save()
|
||||
for record in self:
|
||||
saved = record.save()
|
||||
self.writen(saved)
|
||||
|
||||
def writen(self, ids):
|
||||
@@ -127,97 +121,63 @@ class ModelRecordGroup(SignalEvent):
|
||||
return ids
|
||||
|
||||
def reload(self, ids):
|
||||
for model in self.models:
|
||||
if model.id in ids and not model.modified:
|
||||
model._loaded.clear()
|
||||
for record in self:
|
||||
if record.id in ids and not record.modified:
|
||||
record._loaded.clear()
|
||||
|
||||
def on_write_ids(self, ids):
|
||||
if not self.on_write:
|
||||
return False
|
||||
res = []
|
||||
for fnct in self.on_write:
|
||||
args = ('model', self.model_name, fnct, ids, self.context)
|
||||
try:
|
||||
res += getattr(self.rpc, fnct)(ids, self.context)
|
||||
res += rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
return False
|
||||
res2 = common.process_exception(exception, self.window, *args)
|
||||
if not res2:
|
||||
return False
|
||||
res += res2
|
||||
return list({}.fromkeys(res))
|
||||
|
||||
def _load_for(self, values):
|
||||
if len(values)>10:
|
||||
self.models.lock_signal = True
|
||||
id2values = dict((value['id'], value) for value in values)
|
||||
for model in self.models:
|
||||
if model.id in id2values:
|
||||
model.set(id2values[model.id])
|
||||
if len(values)>10:
|
||||
self.models.lock_signal = False
|
||||
self.signal('record-cleared')
|
||||
|
||||
def load(self, ids, display=True, modified=False):
|
||||
if not ids:
|
||||
return True
|
||||
|
||||
old_ids = [x.id for x in self.models]
|
||||
old_ids = [x.id for x in self]
|
||||
ids = [x for x in ids if x not in old_ids]
|
||||
if not ids:
|
||||
return True
|
||||
|
||||
if len(ids) > 10:
|
||||
self.models.lock_signal = True
|
||||
newmod = None
|
||||
newmods = []
|
||||
if len(ids) > 1:
|
||||
self.lock_signal = True
|
||||
new_records = []
|
||||
for id in ids:
|
||||
newmod = ModelRecord(self.resource, id, self.window,
|
||||
new_record = Record(self.model_name, id, self.window,
|
||||
parent=self.parent, parent_name=self.parent_name, group=self)
|
||||
self.models.append(newmod)
|
||||
newmods.append(newmod)
|
||||
newmod.signal_connect(self, 'record-changed', self._record_changed)
|
||||
newmod.signal_connect(self, 'record-modified', self._record_modified)
|
||||
for model in self.model_removed[:]:
|
||||
if model.id in ids:
|
||||
self.model_removed.remove(model)
|
||||
for model in self.model_deleted[:]:
|
||||
if model.id in ids:
|
||||
self.model_deleted.remove(model)
|
||||
if len(ids) > 10:
|
||||
self.models.lock_signal = False
|
||||
self.signal('record-cleared')
|
||||
self.append(new_record)
|
||||
new_records.append(new_record)
|
||||
new_record.signal_connect(self, 'record-changed', self._record_changed)
|
||||
new_record.signal_connect(self, 'record-modified', self._record_modified)
|
||||
for record in self.record_removed[:]:
|
||||
if record.id in ids:
|
||||
self.record_removed.remove(record)
|
||||
for record in self.record_deleted[:]:
|
||||
if record.id in ids:
|
||||
self.record_deleted.remove(record)
|
||||
if self.lock_signal:
|
||||
self.lock_signal = False
|
||||
self.signal('group-cleared')
|
||||
|
||||
ctx = rpc.CONTEXT.copy()
|
||||
ctx.update(self.context)
|
||||
if self.fields:
|
||||
try:
|
||||
values = self.rpc.read(ids[:80], self.fields.keys() + \
|
||||
[x + '.rec_name' for x in self.fields
|
||||
if self.fields[x]['type'] in \
|
||||
('many2one', 'reference')] + \
|
||||
['_timestamp'], ctx)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
return False
|
||||
if not values:
|
||||
return False
|
||||
self._load_for(values)
|
||||
if new_records and display:
|
||||
self.signal('group-changed', new_records[0])
|
||||
|
||||
if newmod and display:
|
||||
self.signal('model-changed', newmod)
|
||||
|
||||
if modified and newmods:
|
||||
for newmod in newmods:
|
||||
newmod.modified = True
|
||||
# send record-changed only once
|
||||
if newmod.parent:
|
||||
newmod.signal('record-changed', newmod.parent)
|
||||
if new_records and modified:
|
||||
new_records[0].signal('record-changed')
|
||||
|
||||
self.current_idx = 0
|
||||
return True
|
||||
|
||||
def clear(self):
|
||||
self.models.clear()
|
||||
self.model_removed = []
|
||||
self.model_deleted = []
|
||||
|
||||
def _get_context(self):
|
||||
ctx = rpc.CONTEXT.copy()
|
||||
ctx.update(self._context)
|
||||
@@ -225,176 +185,146 @@ class ModelRecordGroup(SignalEvent):
|
||||
ctx['_datetime'] = self.parent.get_eval(check_load=False)\
|
||||
[self.parent_datetime_field]
|
||||
return ctx
|
||||
|
||||
context = property(_get_context)
|
||||
|
||||
def model_add(self, model, position=-1, modified=True):
|
||||
#TODO To be checked
|
||||
if not model.mgroup is self:
|
||||
def add(self, record, position=-1, modified=True):
|
||||
if not record.group is self:
|
||||
fields = {}
|
||||
for i in model.mgroup.fields:
|
||||
fields[model.mgroup.fields[i]['name']] = \
|
||||
model.mgroup.fields[i]
|
||||
self.add_fields(fields, self)
|
||||
self.add_fields(self.fields, model.mgroup)
|
||||
model.mgroup = self
|
||||
for i in record.group.fields:
|
||||
fields[record.group.fields[i].attrs['name']] = \
|
||||
record.group.fields[i].attrs
|
||||
self.add_fields(fields)
|
||||
record.group = self
|
||||
|
||||
if position == -1:
|
||||
self.models.append(model)
|
||||
self.append(record)
|
||||
else:
|
||||
self.models.insert(position, model)
|
||||
self.insert(position, record)
|
||||
self.current_idx = position
|
||||
model.parent = self.parent
|
||||
model.parent_name = self.parent_name
|
||||
model.window = self.window
|
||||
record.parent = self.parent
|
||||
record.parent_name = self.parent_name
|
||||
record.window = self.window
|
||||
if modified:
|
||||
model.modified = True
|
||||
model.signal_connect(self, 'record-changed', self._record_changed)
|
||||
model.signal_connect(self, 'record-modified', self._record_modified)
|
||||
return model
|
||||
|
||||
def model_move(self, model, position=0):
|
||||
self.models.move(model, position)
|
||||
record.modified = True
|
||||
record.signal_connect(self, 'record-changed', self._record_changed)
|
||||
record.signal_connect(self, 'record-modified', self._record_modified)
|
||||
return record
|
||||
|
||||
def set_sequence(self, field='sequence'):
|
||||
index = 0
|
||||
for model in self.models:
|
||||
if model[field]:
|
||||
if index >= model[field].get(model):
|
||||
for record in self:
|
||||
if record[field]:
|
||||
if index >= record[field].get(record):
|
||||
index += 1
|
||||
model[field].set(model, index, modified=True)
|
||||
record[field].set(record, index, modified=True)
|
||||
else:
|
||||
index = model[field].get(model)
|
||||
index = record[field].get(record)
|
||||
|
||||
def model_new(self, default=True, domain=None, context=None):
|
||||
newmod = ModelRecord(self.resource, None, self.window, group=self,
|
||||
def new(self, default=True, domain=None, context=None, signal=True):
|
||||
record = Record(self.model_name, None, self.window, group=self,
|
||||
parent=self.parent, parent_name=self.parent_name, new=True)
|
||||
newmod.signal_connect(self, 'record-changed', self._record_changed)
|
||||
newmod.signal_connect(self, 'record-modified', self._record_modified)
|
||||
record.signal_connect(self, 'record-changed', self._record_changed)
|
||||
record.signal_connect(self, 'record-modified', self._record_modified)
|
||||
if default:
|
||||
ctx = {}
|
||||
ctx.update(context or {})
|
||||
ctx.update(self.context)
|
||||
newmod.default_get(domain, ctx)
|
||||
self.signal('model-changed', newmod)
|
||||
return newmod
|
||||
record.default_get(domain, ctx)
|
||||
if signal:
|
||||
self.signal('group-changed', record)
|
||||
return record
|
||||
|
||||
def model_remove(self, model):
|
||||
idx = self.models.index(model)
|
||||
self.models.remove(model)
|
||||
if model.parent:
|
||||
model.parent.modified = True
|
||||
if self.models:
|
||||
self.current_idx = min(idx, len(self.models)-1)
|
||||
def remove(self, record, remove=False, modified=True, signal=True):
|
||||
idx = self.index(record)
|
||||
if self[idx].id > 0:
|
||||
if remove:
|
||||
self.record_removed.append(self[idx])
|
||||
else:
|
||||
self.record_deleted.append(self[idx])
|
||||
if record.parent:
|
||||
record.parent.modified = True
|
||||
if modified:
|
||||
record.modified = True
|
||||
self._remove(self[idx])
|
||||
|
||||
if len(self):
|
||||
self.current_idx = min(idx, len(self) - 1)
|
||||
else:
|
||||
self.current_idx = None
|
||||
|
||||
def _record_changed(self, model, signal_data):
|
||||
self.signal('model-changed', model)
|
||||
if signal:
|
||||
record.signal('record-changed', record.parent)
|
||||
|
||||
def _record_modified(self, model, signal_data):
|
||||
self.signal('record-modified', model)
|
||||
def _record_changed(self, record, signal_data):
|
||||
self.signal('group-changed', record)
|
||||
|
||||
def _record_modified(self, record, signal_data):
|
||||
self.signal('record-modified', record)
|
||||
|
||||
def prev(self):
|
||||
if self.models and self.current_idx is not None:
|
||||
self.current_idx = (self.current_idx - 1) % len(self.models)
|
||||
elif self.models:
|
||||
if len(self) and self.current_idx is not None:
|
||||
self.current_idx = (self.current_idx - 1) % len(self)
|
||||
elif len(self):
|
||||
self.current_idx = 0
|
||||
else:
|
||||
return None
|
||||
return self.models[self.current_idx]
|
||||
return self[self.current_idx]
|
||||
|
||||
def next(self):
|
||||
if self.models and self.current_idx is not None:
|
||||
self.current_idx = (self.current_idx + 1) % len(self.models)
|
||||
elif self.models:
|
||||
if len(self) and self.current_idx is not None:
|
||||
self.current_idx = (self.current_idx + 1) % len(self)
|
||||
elif len(self):
|
||||
self.current_idx = 0
|
||||
else:
|
||||
return None
|
||||
return self.models[self.current_idx]
|
||||
return self[self.current_idx]
|
||||
|
||||
def remove(self, model, remove=False, modified=True, signal=True):
|
||||
idx = self.models.index(model)
|
||||
if self.models[idx].id > 0:
|
||||
if remove:
|
||||
self.model_removed.append(self.models[idx])
|
||||
else:
|
||||
self.model_deleted.append(self.models[idx])
|
||||
if model.parent:
|
||||
model.parent.modified = True
|
||||
if modified:
|
||||
model.modified = True
|
||||
self.models.remove(self.models[idx])
|
||||
if signal:
|
||||
model.signal('record-changed', model.parent)
|
||||
|
||||
def add_fields_custom(self, fields, models):
|
||||
to_add = []
|
||||
for field_add in fields.iterkeys():
|
||||
if not field_add in models.fields:
|
||||
models.fields[field_add] = fields[field_add]
|
||||
models.fields[field_add]['name'] = field_add
|
||||
to_add.append(field_add)
|
||||
else:
|
||||
models.fields[field_add].update(fields[field_add])
|
||||
ModelRecordGroup.mfields_load(to_add, models)
|
||||
for fname in to_add:
|
||||
for model in models.models:
|
||||
model.value[fname] = self.mfields[fname].create(model)
|
||||
return to_add
|
||||
|
||||
def add_fields(self, fields, models, context=None, signal=True):
|
||||
def add_fields(self, fields, context=None, signal=True):
|
||||
if context is None:
|
||||
context = {}
|
||||
to_add = self.add_fields_custom(fields, models)
|
||||
models = models.models
|
||||
if not len(models):
|
||||
|
||||
to_add = {}
|
||||
for name, attr in fields.iteritems():
|
||||
if name not in self.fields:
|
||||
to_add[name] = attr
|
||||
else:
|
||||
self.fields[name].attrs.update(attr)
|
||||
self.load_fields(to_add)
|
||||
for name in to_add:
|
||||
for record in self:
|
||||
record.value[name] = self.fields[name].create(record)
|
||||
|
||||
if not len(self):
|
||||
return True
|
||||
|
||||
old = []
|
||||
new = []
|
||||
for model in models:
|
||||
if model.id > 0:
|
||||
if model.is_modified():
|
||||
old.append(model.id)
|
||||
else:
|
||||
new.append(model)
|
||||
for record in self:
|
||||
if record.id <= 0:
|
||||
new.append(record)
|
||||
ctx = context.copy()
|
||||
if len(old) and len(to_add):
|
||||
ctx.update(rpc.CONTEXT)
|
||||
ctx.update(self.context)
|
||||
try:
|
||||
values = self.rpc.read(old, to_add + \
|
||||
[x + '.rec_name' for x in to_add
|
||||
if self.fields[x]['type'] \
|
||||
in ('many2one', 'reference')], ctx)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
return False
|
||||
if values:
|
||||
for value in values:
|
||||
value_id = value['id']
|
||||
if 'id' not in to_add:
|
||||
del value['id']
|
||||
self[value_id].set(value, signal=False)
|
||||
|
||||
if len(new) and len(to_add):
|
||||
ctx.update(self.context)
|
||||
args = ('model', self.model_name, 'default_get', to_add.keys(), ctx)
|
||||
try:
|
||||
values = self.rpc.default_get(to_add, ctx)
|
||||
values = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
return False
|
||||
for field_to_add in to_add:
|
||||
if field_to_add not in values:
|
||||
values[field_to_add] = False
|
||||
for mod in new:
|
||||
mod.set_default(values, signal=signal)
|
||||
values = common.process_exception(exception, self.window, *args)
|
||||
if not values:
|
||||
return False
|
||||
for name in to_add:
|
||||
if name not in values:
|
||||
values[name] = False
|
||||
for record in new:
|
||||
record.set_default(values, signal=signal)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.models)
|
||||
def get(self, id):
|
||||
'Return record with the id'
|
||||
return self.__id2record.get(id)
|
||||
|
||||
def get_by_id(self, m_id):
|
||||
for model in self.models:
|
||||
if model.id == m_id:
|
||||
return model
|
||||
|
||||
__getitem__ = get_by_id
|
||||
def id_changed(self, old_id):
|
||||
'Update index for old id'
|
||||
record = self.__id2record[old_id]
|
||||
self.__id2record[record.id] = record
|
||||
del self.__id2record[old_id]
|
||||
@@ -1,15 +1,13 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
import re
|
||||
import time
|
||||
from tryton.rpc import RPCProxy
|
||||
import tryton.rpc as rpc
|
||||
from tryton.signal_event import SignalEvent
|
||||
import tryton.common as common
|
||||
from tryton.pyson import PYSONDecoder
|
||||
import field
|
||||
import datetime
|
||||
import tryton.common as common
|
||||
import logging
|
||||
import time
|
||||
|
||||
|
||||
class EvalEnvironment(dict):
|
||||
@@ -43,96 +41,91 @@ class EvalEnvironment(dict):
|
||||
__repr__ = __str__
|
||||
|
||||
def __contains__(self, item):
|
||||
return item in self.parent.mgroup.mfields
|
||||
return item in self.parent.group.fields
|
||||
|
||||
|
||||
class ModelRecord(SignalEvent):
|
||||
class Record(SignalEvent):
|
||||
|
||||
id = -1
|
||||
|
||||
|
||||
def __init__(self, resource, obj_id, window, group=None, parent=None,
|
||||
def __init__(self, model_name, obj_id, window, group=None, parent=None,
|
||||
parent_name='', new=False):
|
||||
global ID_COUNT
|
||||
super(ModelRecord, self).__init__()
|
||||
super(Record, self).__init__()
|
||||
self.window = window
|
||||
self.resource = resource
|
||||
self.rpc = RPCProxy(self.resource)
|
||||
self.id = obj_id or ModelRecord.id
|
||||
self.model_name = model_name
|
||||
self.id = obj_id or Record.id
|
||||
if self.id < 0:
|
||||
ModelRecord.id -= 1
|
||||
Record.id -= 1
|
||||
self._loaded = set()
|
||||
self.parent = parent
|
||||
self.parent_name = parent_name
|
||||
self.mgroup = group
|
||||
self.group = group
|
||||
if group is not None:
|
||||
assert model_name == group.model_name
|
||||
self.value = {}
|
||||
self.state_attrs = {}
|
||||
self.__modified = False
|
||||
self.modified_fields = {}
|
||||
self._timestamp = None
|
||||
self.attachment_count = -1
|
||||
self.next = {}
|
||||
for key, val in self.mgroup.mfields.items():
|
||||
self.next = {} # Used in Group list
|
||||
for key, val in self.group.fields.items():
|
||||
self.value[key] = val.create(self)
|
||||
if (new and val.attrs['type']=='one2many') \
|
||||
and (val.attrs.get('mode','tree,form').startswith('form')):
|
||||
mod = self.value[key].model_new()
|
||||
self.value[key].model_add(mod)
|
||||
record = self.value[key].new()
|
||||
self.value[key].add(record)
|
||||
|
||||
def __getitem__(self, name):
|
||||
if name not in self._loaded and self.id > 0:
|
||||
ids = [self.id]
|
||||
if self in self.mgroup.models:
|
||||
idx = self.mgroup.models.index(self)
|
||||
length = len(self.mgroup.models)
|
||||
if self in self.group:
|
||||
idx = self.group.index(self)
|
||||
length = len(self.group)
|
||||
n = 1
|
||||
while len(ids) < 80 and (idx - n >= 0 or \
|
||||
idx + n < length) and n < 100:
|
||||
if idx - n >= 0:
|
||||
model = self.mgroup.models[idx - n]
|
||||
if name not in model._loaded and model.id > 0:
|
||||
ids.append(model.id)
|
||||
record = self.group[idx - n]
|
||||
if name not in record._loaded and record.id > 0:
|
||||
ids.append(record.id)
|
||||
if idx + n < length:
|
||||
model = self.mgroup.models[idx + n]
|
||||
if name not in model._loaded and model.id > 0:
|
||||
ids.append(model.id)
|
||||
record = self.group[idx + n]
|
||||
if name not in record._loaded and record.id > 0:
|
||||
ids.append(record.id)
|
||||
n += 1
|
||||
ctx = rpc.CONTEXT.copy()
|
||||
ctx.update(self.context_get())
|
||||
args = (ids, self.mgroup.mfields.keys() + \
|
||||
[x + '.rec_name' for x in self.mgroup.mfields.keys()
|
||||
if self.mgroup.fields[x]['type'] \
|
||||
args = ('model', self.model_name, 'read',
|
||||
ids, self.group.fields.keys() + \
|
||||
[x + '.rec_name' for x in self.group.fields.keys()
|
||||
if self.group.fields[x].attrs['type'] \
|
||||
in ('many2one', 'reference')] + \
|
||||
['_timestamp'], ctx)
|
||||
try:
|
||||
values = self.rpc.read(*args)
|
||||
values = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
try:
|
||||
values = self.rpc.read(args)
|
||||
except:
|
||||
values = common.process_exception(exception, self.window, *args)
|
||||
if not values:
|
||||
log = logging.getLogger('record')
|
||||
log.error('%s' % exception.args[-1])
|
||||
values = [{'id': x} for x in ids]
|
||||
model_set = None
|
||||
id2value = dict((value['id'], value) for value in values)
|
||||
if ids != [self.id]:
|
||||
for model in self.mgroup.models:
|
||||
value = id2value.get(model.id)
|
||||
if value:
|
||||
model.set(value, signal=False)
|
||||
model_set = model
|
||||
for id in ids:
|
||||
record = self.group.get(id)
|
||||
value = id2value.get(id)
|
||||
if record and value:
|
||||
record.set(value, signal=False)
|
||||
else:
|
||||
value = id2value.get(self.id)
|
||||
if value:
|
||||
self.set(value, signal=False)
|
||||
model_set = self
|
||||
if model_set:
|
||||
model_set.signal('record-changed')
|
||||
return self.mgroup.mfields.get(name, False)
|
||||
return self.group.fields.get(name, False)
|
||||
|
||||
def __repr__(self):
|
||||
return '<ModelRecord %s@%s>' % (self.id, self.resource)
|
||||
return '<Record %s@%s>' % (self.id, self.model_name)
|
||||
|
||||
def get_modified(self):
|
||||
return self.__modified
|
||||
@@ -148,7 +141,7 @@ class ModelRecord(SignalEvent):
|
||||
return self.modified
|
||||
|
||||
def fields_get(self):
|
||||
return self.mgroup.mfields
|
||||
return self.group.fields
|
||||
|
||||
def _check_load(self):
|
||||
if not self.loaded:
|
||||
@@ -157,7 +150,7 @@ class ModelRecord(SignalEvent):
|
||||
return False
|
||||
|
||||
def get_loaded(self):
|
||||
return set(self.mgroup.mfields.keys()) == self._loaded
|
||||
return set(self.group.fields.keys()) == self._loaded
|
||||
|
||||
loaded = property(get_loaded)
|
||||
|
||||
@@ -166,12 +159,12 @@ class ModelRecord(SignalEvent):
|
||||
if check_load:
|
||||
self._check_load()
|
||||
value = []
|
||||
for name, mfield in self.mgroup.mfields.items():
|
||||
for name, field in self.group.fields.iteritems():
|
||||
if (get_readonly or \
|
||||
not mfield.get_state_attrs(self).get('readonly', False)) \
|
||||
not field.get_state_attrs(self).get('readonly', False)) \
|
||||
and (not get_modifiedonly \
|
||||
or mfield.name in self.modified_fields):
|
||||
value.append((name, mfield.get(self, check_load=check_load,
|
||||
or field.name in self.modified_fields):
|
||||
value.append((name, field.get(self, check_load=check_load,
|
||||
readonly=get_readonly, modified=get_modifiedonly)))
|
||||
value = dict(value)
|
||||
if includeid:
|
||||
@@ -182,8 +175,8 @@ class ModelRecord(SignalEvent):
|
||||
if check_load:
|
||||
self._check_load()
|
||||
value = {}
|
||||
for name, mfield in self.mgroup.mfields.items():
|
||||
value[name] = mfield.get_eval(self, check_load=check_load)
|
||||
for name, field in self.group.fields.iteritems():
|
||||
value[name] = field.get_eval(self, check_load=check_load)
|
||||
value['id'] = self.id
|
||||
return value
|
||||
|
||||
@@ -192,23 +185,25 @@ class ModelRecord(SignalEvent):
|
||||
self.reload()
|
||||
|
||||
def get_timestamp(self):
|
||||
result = {self.resource + ',' + str(self.id): self._timestamp}
|
||||
for name, mfield in self.mgroup.mfields.items():
|
||||
result.update(mfield.get_timestamp(self))
|
||||
result = {self.model_name + ',' + str(self.id): self._timestamp}
|
||||
for name, field in self.group.fields.iteritems():
|
||||
result.update(field.get_timestamp(self))
|
||||
return result
|
||||
|
||||
def save(self, force_reload=True):
|
||||
self._check_load()
|
||||
if self.id < 0:
|
||||
value = self.get(get_readonly=True)
|
||||
args = ('model', self.resource, 'create', value, self.context_get())
|
||||
args = ('model', self.model_name, 'create', value, self.context_get())
|
||||
try:
|
||||
self.id = rpc.execute(*args)
|
||||
res = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
res = common.process_exception(exception, self.window, *args)
|
||||
if not res:
|
||||
return False
|
||||
self.id = res
|
||||
old_id = self.id
|
||||
self.id = res
|
||||
self.group.id_changed(old_id)
|
||||
else:
|
||||
if not self.is_modified():
|
||||
return self.id
|
||||
@@ -216,7 +211,7 @@ class ModelRecord(SignalEvent):
|
||||
context = self.context_get()
|
||||
context = context.copy()
|
||||
context['_timestamp'] = self.get_timestamp()
|
||||
args = ('model', self.resource, 'write', [self.id], value, context)
|
||||
args = ('model', self.model_name, 'write', [self.id], value, context)
|
||||
try:
|
||||
if not rpc.execute(*args):
|
||||
return False
|
||||
@@ -226,35 +221,41 @@ class ModelRecord(SignalEvent):
|
||||
self._loaded.clear()
|
||||
if force_reload:
|
||||
self.reload()
|
||||
if self.mgroup:
|
||||
self.mgroup.writen(self.id)
|
||||
if self.group:
|
||||
self.group.writen(self.id)
|
||||
return self.id
|
||||
|
||||
def default_get(self, domain=None, context=None):
|
||||
if len(self.mgroup.fields):
|
||||
if len(self.group.fields):
|
||||
args = ('model', self.model_name, 'default_get',
|
||||
self.group.fields.keys(), context)
|
||||
try:
|
||||
val = self.rpc.default_get(self.mgroup.fields.keys(), context)
|
||||
vals = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
val = self.rpc.default_get(self.mgroup.fields.keys(), context)
|
||||
self.set_default(val)
|
||||
vals = common.process_exception(exception, self.window, *args)
|
||||
if not vals:
|
||||
return
|
||||
self.set_default(vals)
|
||||
|
||||
def rec_name(self):
|
||||
ctx = rpc.CONTEXT.copy()
|
||||
ctx.update(self.context_get())
|
||||
args = ('model', self.model_name, 'read', self.id, ['rec_name'], ctx)
|
||||
try:
|
||||
name = self.rpc.read(self.id, ['rec_name'], ctx)['rec_name']
|
||||
res = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
name = self.rpc.read(self.id, ['rec_name'], ctx)['rec_name']
|
||||
return name
|
||||
res = common.process_exception(exception, self.window, *args)
|
||||
if not res:
|
||||
return ''
|
||||
return res['rec_name']
|
||||
|
||||
def validate_set(self):
|
||||
change = self._check_load()
|
||||
for mfield in self.mgroup.mfields.itervalues():
|
||||
self._check_load()
|
||||
change = False
|
||||
for field in self.group.fields.itervalues():
|
||||
change = change or \
|
||||
not mfield.get_state_attrs(self).get('valid', True)
|
||||
mfield.get_state_attrs(self)['valid'] = True
|
||||
not field.get_state_attrs(self).get('valid', True)
|
||||
field.get_state_attrs(self)['valid'] = True
|
||||
if change:
|
||||
self.signal('record-changed')
|
||||
return change
|
||||
@@ -262,43 +263,44 @@ class ModelRecord(SignalEvent):
|
||||
def validate(self):
|
||||
self._check_load()
|
||||
res = True
|
||||
for mfield in self.mgroup.mfields.itervalues():
|
||||
if not mfield.validate(self):
|
||||
for field in self.group.fields.itervalues():
|
||||
if not field.validate(self):
|
||||
res = False
|
||||
return res
|
||||
|
||||
def _get_invalid_fields(self):
|
||||
res = []
|
||||
for fname, mfield in self.mgroup.mfields.items():
|
||||
if not mfield.get_state_attrs(self).get('valid', True):
|
||||
res.append((fname, mfield.attrs['string']))
|
||||
for fname, field in self.group.fields.iteritems():
|
||||
if not field.get_state_attrs(self).get('valid', True):
|
||||
res.append((fname, field.attrs['string']))
|
||||
return dict(res)
|
||||
|
||||
invalid_fields = property(_get_invalid_fields)
|
||||
|
||||
def context_get(self):
|
||||
return self.mgroup.context
|
||||
return self.group.context
|
||||
|
||||
def get_default(self):
|
||||
self._check_load()
|
||||
value = dict([(name, mfield.get_default(self))
|
||||
for name, mfield in self.mgroup.mfields.items()])
|
||||
value = dict([(name, field.get_default(self))
|
||||
for name, field in self.group.fields.iteritems()])
|
||||
return value
|
||||
|
||||
def set_default(self, val, signal=True, modified=False):
|
||||
for fieldname, value in val.items():
|
||||
if fieldname not in self.mgroup.mfields:
|
||||
if fieldname not in self.group.fields:
|
||||
continue
|
||||
if isinstance(self.mgroup.mfields[fieldname], field.M2OField):
|
||||
if isinstance(self.group.fields[fieldname], field.M2OField):
|
||||
if fieldname + '.rec_name' in val:
|
||||
value = (value, val[fieldname + '.rec_name'])
|
||||
elif isinstance(self.mgroup.mfields[fieldname], field.ReferenceField):
|
||||
elif isinstance(self.group.fields[fieldname], field.ReferenceField):
|
||||
if value:
|
||||
ref_model, ref_id = value.split(',', 1)
|
||||
if fieldname + '.rec_name' in val:
|
||||
value = ref_model, (ref_id, val[fieldname + '.rec_name'])
|
||||
else:
|
||||
value = ref_model, (ref_id, ref_id)
|
||||
self.mgroup.mfields[fieldname].set_default(self, value,
|
||||
self.group.fields[fieldname].set_default(self, value,
|
||||
modified=modified)
|
||||
self._loaded.add(fieldname)
|
||||
if signal:
|
||||
@@ -310,25 +312,25 @@ class ModelRecord(SignalEvent):
|
||||
if fieldname == '_timestamp':
|
||||
self._timestamp = value
|
||||
continue
|
||||
if fieldname not in self.mgroup.mfields:
|
||||
if fieldname not in self.group.fields:
|
||||
continue
|
||||
if isinstance(self.mgroup.mfields[fieldname], field.O2MField):
|
||||
if isinstance(self.group.fields[fieldname], field.O2MField):
|
||||
later[fieldname] = value
|
||||
continue
|
||||
if isinstance(self.mgroup.mfields[fieldname], field.M2OField):
|
||||
if isinstance(self.group.fields[fieldname], field.M2OField):
|
||||
if fieldname + '.rec_name' in val:
|
||||
value = (value, val[fieldname + '.rec_name'])
|
||||
elif isinstance(self.mgroup.mfields[fieldname], field.ReferenceField):
|
||||
elif isinstance(self.group.fields[fieldname], field.ReferenceField):
|
||||
if value:
|
||||
ref_model, ref_id = value.split(',', 1)
|
||||
if fieldname + '.rec_name' in val:
|
||||
value = ref_model, (ref_id, val[fieldname + '.rec_name'])
|
||||
else:
|
||||
value = ref_model, (ref_id, ref_id)
|
||||
self.mgroup.mfields[fieldname].set(self, value, modified=modified)
|
||||
self.group.fields[fieldname].set(self, value, modified=modified)
|
||||
self._loaded.add(fieldname)
|
||||
for fieldname, value in later.iteritems():
|
||||
self.mgroup.mfields[fieldname].set(self, value, modified=modified)
|
||||
self.group.fields[fieldname].set(self, value, modified=modified)
|
||||
self._loaded.add(fieldname)
|
||||
self.modified = modified
|
||||
if not self.modified:
|
||||
@@ -348,8 +350,8 @@ class ModelRecord(SignalEvent):
|
||||
if check_load:
|
||||
self._check_load()
|
||||
ctx = rpc.CONTEXT.copy()
|
||||
for name, mfield in self.mgroup.mfields.items():
|
||||
ctx[name] = mfield.get_eval(self, check_load=check_load)
|
||||
for name, field in self.group.fields.items():
|
||||
ctx[name] = field.get_eval(self, check_load=check_load)
|
||||
|
||||
ctx['context'] = self.context_get()
|
||||
ctx['active_id'] = self.id
|
||||
@@ -363,8 +365,8 @@ class ModelRecord(SignalEvent):
|
||||
def _get_on_change_args(self, args):
|
||||
res = {}
|
||||
values = {}
|
||||
for name, mfield in self.mgroup.mfields.iteritems():
|
||||
values[name] = mfield.get_eval(self, check_load=False)
|
||||
for name, field in self.group.fields.iteritems():
|
||||
values[name] = field.get_eval(self, check_load=False)
|
||||
if self.parent and self.parent_name:
|
||||
values['_parent_' + self.parent_name] = EvalEnvironment(self.parent,
|
||||
False)
|
||||
@@ -385,41 +387,41 @@ class ModelRecord(SignalEvent):
|
||||
ids = [self.id]
|
||||
ctx = rpc.CONTEXT.copy()
|
||||
ctx.update(self.context_get())
|
||||
args = ('model', self.model_name, 'on_change_' + fieldname,
|
||||
ids, args, ctx)
|
||||
try:
|
||||
res = getattr(self.rpc, 'on_change_' + fieldname)(ids, args,
|
||||
ctx)
|
||||
res = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
res = getattr(self.rpc, 'on_change_' + fieldname)(ids, args,
|
||||
ctx)
|
||||
if res:
|
||||
later = {}
|
||||
for fieldname, value in res.items():
|
||||
if fieldname not in self.mgroup.mfields:
|
||||
continue
|
||||
if isinstance(self.mgroup.mfields[fieldname], field.O2MField):
|
||||
later[fieldname] = value
|
||||
continue
|
||||
if isinstance(self.mgroup.mfields[fieldname], field.M2OField):
|
||||
res = common.process_exception(exception, self.window, *args)
|
||||
if not res:
|
||||
return
|
||||
later = {}
|
||||
for fieldname, value in res.items():
|
||||
if fieldname not in self.group.fields:
|
||||
continue
|
||||
if isinstance(self.group.fields[fieldname], field.O2MField):
|
||||
later[fieldname] = value
|
||||
continue
|
||||
if isinstance(self.group.fields[fieldname], field.M2OField):
|
||||
if fieldname + '.rec_name' in res:
|
||||
value = (value, res[fieldname + '.rec_name'])
|
||||
elif isinstance(self.group.fields[fieldname],
|
||||
field.ReferenceField):
|
||||
if value:
|
||||
ref_mode, ref_id = value.split(',', 1)
|
||||
if fieldname + '.rec_name' in res:
|
||||
value = (value, res[fieldname + '.rec_name'])
|
||||
elif isinstance(self.mgroup.mfields[fieldname],
|
||||
field.ReferenceField):
|
||||
if value:
|
||||
ref_mode, ref_id = value.split(',', 1)
|
||||
if fieldname + '.rec_name' in res:
|
||||
value = ref_model, (ref_id,
|
||||
res[fieldname + '.rec_name'])
|
||||
else:
|
||||
value = ref_model, (ref_id, ref_id)
|
||||
self.mgroup.mfields[fieldname].set_on_change(self, value)
|
||||
for fieldname, value in later.items():
|
||||
self.mgroup.mfields[fieldname].set_on_change(self, value)
|
||||
self.signal('record-changed')
|
||||
value = ref_model, (ref_id,
|
||||
res[fieldname + '.rec_name'])
|
||||
else:
|
||||
value = ref_model, (ref_id, ref_id)
|
||||
self.group.fields[fieldname].set_on_change(self, value)
|
||||
for fieldname, value in later.items():
|
||||
self.group.fields[fieldname].set_on_change(self, value)
|
||||
self.signal('record-changed')
|
||||
|
||||
def on_change_with(self, field_name):
|
||||
for fieldname in self.mgroup.mfields:
|
||||
on_change_with = self.mgroup.mfields[fieldname].attrs.get(
|
||||
for fieldname in self.group.fields:
|
||||
on_change_with = self.group.fields[fieldname].attrs.get(
|
||||
'on_change_with')
|
||||
if not on_change_with:
|
||||
continue
|
||||
@@ -431,37 +433,39 @@ class ModelRecord(SignalEvent):
|
||||
ids = [self.id]
|
||||
ctx = rpc.CONTEXT.copy()
|
||||
ctx.update(self.context_get())
|
||||
args = ('model', self.model_name, 'on_change_with_' + fieldname,
|
||||
ids, args, ctx)
|
||||
try:
|
||||
res = getattr(self.rpc, 'on_change_with_' + fieldname)(ids,
|
||||
args, ctx)
|
||||
res = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
res = getattr(self.rpc, 'on_change_with_' + fieldname)(ids,
|
||||
args, ctx)
|
||||
self.mgroup.mfields[fieldname].set_on_change(self, res)
|
||||
res = common.process_exception(exception, self.window, *args)
|
||||
if not res:
|
||||
return
|
||||
self.group.fields[fieldname].set_on_change(self, res)
|
||||
|
||||
def cond_default(self, field_name, value):
|
||||
ir_default = RPCProxy('ir.default')
|
||||
ctx = rpc.CONTEXT.copy()
|
||||
ctx.update(self.context_get())
|
||||
args = ('model', 'ir.default', 'get_default', self.model_name,
|
||||
field_name + '=' + str(value), ctx)
|
||||
try:
|
||||
self.set_default(ir_default.get_default(self.resource,
|
||||
field_name + '=' + str(value), ctx))
|
||||
res = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
self.set_default(ir_default.get_default(self.resource,
|
||||
field_name + '=' + str(value), ctx))
|
||||
res = common.process_exception(exception, self.window, *args)
|
||||
if not res:
|
||||
return
|
||||
self.set_default(res)
|
||||
|
||||
def get_attachment_count(self, reload=False):
|
||||
if self.id < 0:
|
||||
return 0
|
||||
if self.attachment_count < 0 or reload:
|
||||
ir_attachment = RPCProxy('ir.attachment')
|
||||
args = ('model', 'ir.attachment', 'search_count', [
|
||||
('res_model', '=', self.model_name),
|
||||
('res_id', '=', self.id),
|
||||
])
|
||||
try:
|
||||
self.attachment_count = ir_attachment.search_count([
|
||||
('res_model', '=', self.resource),
|
||||
('res_id', '=', self.id),
|
||||
])
|
||||
self.attachment_count = rpc.execute(*args)
|
||||
except:
|
||||
return 0
|
||||
return self.attachment_count
|
||||
@@ -1,27 +1,25 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
"Screen"
|
||||
import xml.dom.minidom
|
||||
from tryton.rpc import RPCProxy
|
||||
import tryton.rpc as rpc
|
||||
from tryton.gui.window.view_form.model.group import ModelRecordGroup
|
||||
from tryton.gui.window.view_form.model.group import Group
|
||||
from tryton.gui.window.view_form.view.screen_container import ScreenContainer
|
||||
from tryton.gui.window.view_form.widget_search import Form
|
||||
from tryton.signal_event import SignalEvent
|
||||
from tryton.common import node_attributes
|
||||
import gobject
|
||||
from tryton.config import CONFIG
|
||||
import tryton.common as common
|
||||
import gobject
|
||||
import copy
|
||||
import xml.dom.minidom
|
||||
|
||||
|
||||
class Screen(SignalEvent):
|
||||
"Screen"
|
||||
|
||||
def __init__(self, model_name, window, view_ids=None, view_type=None,
|
||||
parent=None, parent_name='', context=None, views_preload=None,
|
||||
tree_saves=True, domain=None, create_new=False, row_activate=None,
|
||||
hastoolbar=False, default_get=None, show_search=False, limit=None,
|
||||
readonly=False, form=None, exclude_field=None, sort=None,
|
||||
context=None, views_preload=None, domain=None, row_activate=None,
|
||||
limit=None, readonly=False, exclude_field=None, sort=None,
|
||||
search_value=None):
|
||||
if view_ids is None:
|
||||
view_ids = []
|
||||
@@ -33,48 +31,35 @@ class Screen(SignalEvent):
|
||||
views_preload = {}
|
||||
if domain is None:
|
||||
domain = []
|
||||
if default_get is None:
|
||||
default_get = {}
|
||||
|
||||
super(Screen, self).__init__()
|
||||
|
||||
self.__current_model = None
|
||||
self.show_search = show_search
|
||||
self.search_count = 0
|
||||
self.hastoolbar = hastoolbar
|
||||
self.default_get = default_get
|
||||
if not row_activate:
|
||||
# TODO change for a function that switch to form view
|
||||
self.row_activate = self.switch_view
|
||||
else:
|
||||
self.row_activate = row_activate
|
||||
self.create_new = create_new
|
||||
self.name = model_name
|
||||
self.domain = domain
|
||||
self.views_preload = views_preload
|
||||
self.resource = model_name
|
||||
self.rpc = RPCProxy(model_name)
|
||||
self.model_name = model_name
|
||||
self.context = context
|
||||
self.views = []
|
||||
self.fields = {}
|
||||
self.view_ids = view_ids
|
||||
self.models = None
|
||||
self.parent = parent
|
||||
self.parent_name = parent_name
|
||||
self.parent = None
|
||||
self.parent_name = None
|
||||
self.window = window
|
||||
models = ModelRecordGroup(model_name, self.fields, self.window,
|
||||
parent=self.parent, parent_name=parent_name, context=self.context,
|
||||
self.__group = None
|
||||
self.group = Group(model_name, {}, self.window, context=self.context,
|
||||
readonly=readonly)
|
||||
self.models_set(models)
|
||||
self.current_model = None
|
||||
self.__current_record = None
|
||||
self.current_record = None
|
||||
self.screen_container = ScreenContainer()
|
||||
self.filter_widget = None
|
||||
self.widget = self.screen_container.widget_get()
|
||||
self.__current_view = 0
|
||||
self.tree_saves = tree_saves
|
||||
self.limit = limit
|
||||
self.search_value = search_value
|
||||
self.form = form
|
||||
self.fields_view_tree = None
|
||||
self.exclude_field = exclude_field
|
||||
self.sort = sort
|
||||
@@ -89,8 +74,11 @@ class Screen(SignalEvent):
|
||||
self.screen_container.set(view.widget)
|
||||
self.display()
|
||||
|
||||
def __repr__(self):
|
||||
return '<Screen %s at %s>' % (self.model_name, id(self))
|
||||
|
||||
def search_active(self, active=True):
|
||||
if active and self.show_search:
|
||||
if active and not self.parent:
|
||||
if not self.filter_widget:
|
||||
if not self.fields_view_tree:
|
||||
ctx = {}
|
||||
@@ -98,13 +86,14 @@ class Screen(SignalEvent):
|
||||
ctx.update(self.context)
|
||||
try:
|
||||
self.fields_view_tree = rpc.execute('model',
|
||||
self.name, 'fields_view_get', False,
|
||||
self.model_name, 'fields_view_get', False,
|
||||
'tree', ctx)
|
||||
except:
|
||||
return
|
||||
self.filter_widget = Form(self.fields_view_tree['arch'],
|
||||
self.fields_view_tree['fields'], self.name, self.window,
|
||||
self.domain, (self, self.search_filter), self.context)
|
||||
self.fields_view_tree['fields'], self.model_name,
|
||||
self.window, self.domain, (self, self.search_filter),
|
||||
self.context)
|
||||
self.screen_container.add_filter(self.filter_widget.widget,
|
||||
self.search_filter, self.search_clear)
|
||||
self.filter_widget.set_limit(self.limit)
|
||||
@@ -126,7 +115,7 @@ class Screen(SignalEvent):
|
||||
offset = self.filter_widget.get_offset()
|
||||
values = self.filter_widget.value
|
||||
else:
|
||||
values = [('id', 'in', [x.id for x in self.models])]
|
||||
values = [('id', 'in', [x.id for x in self.group])]
|
||||
ctx = {}
|
||||
ctx.update(rpc.CONTEXT)
|
||||
ctx.update(self.context)
|
||||
@@ -137,21 +126,21 @@ class Screen(SignalEvent):
|
||||
values = self.domain
|
||||
try:
|
||||
try:
|
||||
ids = rpc.execute('model', self.name, 'search', values,
|
||||
ids = rpc.execute('model', self.model_name, 'search', values,
|
||||
offset, limit, self.sort, ctx)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
ids = rpc.execute('model', self.name, 'search', values,
|
||||
ids = rpc.execute('model', self.model_name, 'search', values,
|
||||
offset, limit, self.sort, ctx)
|
||||
if not only_ids:
|
||||
if len(ids) == limit:
|
||||
try:
|
||||
self.search_count = rpc.execute('model', self.name,
|
||||
'search_count', values, ctx)
|
||||
self.search_count = rpc.execute('model',
|
||||
self.model_name, 'search_count', values, ctx)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
self.search_count = rpc.execute('model', self.name,
|
||||
'search_count', values, ctx)
|
||||
self.search_count = rpc.execute('model',
|
||||
self.model_name, 'search_count', values, ctx)
|
||||
else:
|
||||
self.search_count = len(ids)
|
||||
except:
|
||||
@@ -160,76 +149,79 @@ class Screen(SignalEvent):
|
||||
return ids
|
||||
self.clear()
|
||||
self.load(ids)
|
||||
return True
|
||||
return bool(ids)
|
||||
|
||||
def models_set(self, models):
|
||||
if self.models:
|
||||
self.models.signal_unconnect(self)
|
||||
self.models = models
|
||||
self.parent = models.parent
|
||||
self.parent_name = models.parent_name
|
||||
if len(models.models):
|
||||
self.current_model = models.models[0]
|
||||
def __get_group(self):
|
||||
return self.__group
|
||||
|
||||
def __set_group(self, group):
|
||||
fields = {}
|
||||
if self.group is not None:
|
||||
self.group.signal_unconnect(self)
|
||||
for name, field in self.group.fields.iteritems():
|
||||
fields[name] = field.attrs
|
||||
self.__group = group
|
||||
self.parent = group.parent
|
||||
self.parent_name = group.parent_name
|
||||
if len(group):
|
||||
self.current_record = group[0]
|
||||
else:
|
||||
self.current_model = None
|
||||
self.models.signal_connect(self, 'record-cleared', self._record_cleared)
|
||||
self.models.signal_connect(self, 'record-changed', self._record_changed)
|
||||
self.models.signal_connect(self, 'record-modified', self._record_modified)
|
||||
self.models.signal_connect(self, 'model-changed', self._model_changed)
|
||||
models.add_fields(self.fields, models)
|
||||
self.fields.update(models.fields)
|
||||
self.current_record = None
|
||||
self.__group.signal_connect(self, 'group-cleared', self._group_cleared)
|
||||
self.__group.signal_connect(self, 'group-list-changed',
|
||||
self._group_list_changed)
|
||||
self.__group.signal_connect(self, 'record-modified', self._record_modified)
|
||||
self.__group.signal_connect(self, 'group-changed', self._group_changed)
|
||||
self.__group.add_fields(fields)
|
||||
|
||||
def _record_cleared(self, model_group, signal, *args):
|
||||
group = property(__get_group, __set_group)
|
||||
|
||||
def _group_cleared(self, group, signal):
|
||||
for view in self.views:
|
||||
view.reload = True
|
||||
if hasattr(view, 'reload'):
|
||||
view.reload = True
|
||||
|
||||
def _record_changed(self, model_group, signal, *args):
|
||||
def _group_list_changed(self, group, signal):
|
||||
for view in self.views:
|
||||
view.signal_record_changed(signal[0], model_group.models,
|
||||
signal[1], *args)
|
||||
if hasattr(view, 'group_list_changed'):
|
||||
view.group_list_changed(group, signal)
|
||||
|
||||
def _record_modified(self, model_group, signal, *args):
|
||||
def _record_modified(self, group, signal, *args):
|
||||
self.signal('record-modified')
|
||||
|
||||
def _model_changed(self, model_group, model):
|
||||
if self.parent:
|
||||
self.parent.signal('record-changed', self.parent)
|
||||
def _group_changed(self, group, record):
|
||||
self.display()
|
||||
|
||||
def _get_current_model(self):
|
||||
return self.__current_model
|
||||
def __get_current_record(self):
|
||||
return self.__current_record
|
||||
|
||||
#
|
||||
# Check more or less fields than in the screen !
|
||||
#
|
||||
def _set_current_model(self, value):
|
||||
self.__current_model = value
|
||||
def __set_current_record(self, record):
|
||||
self.__current_record = record
|
||||
try:
|
||||
offset = int(self.filter_widget.get_offset())
|
||||
except:
|
||||
offset = 0
|
||||
try:
|
||||
pos = self.models.models.index(value)
|
||||
pos = self.group.index(record)
|
||||
except:
|
||||
pos = -1
|
||||
self.signal('record-message', (pos + offset,
|
||||
len(self.models.models or []) + offset,
|
||||
self.search_count,
|
||||
value and value.id))
|
||||
self.signal('record-message', (pos + offset, len(self.group) + offset,
|
||||
self.search_count, record and record.id))
|
||||
attachment_count = 0
|
||||
if value and value.attachment_count > 0:
|
||||
attachment_count = value.attachment_count
|
||||
if record and record.attachment_count > 0:
|
||||
attachment_count = record.attachment_count
|
||||
self.signal('attachment-count', attachment_count)
|
||||
# update attachment-count after 1 second
|
||||
gobject.timeout_add(1000, self.update_attachment, value)
|
||||
gobject.timeout_add(1000, self.update_attachment, record)
|
||||
return True
|
||||
current_model = property(_get_current_model, _set_current_model)
|
||||
|
||||
def update_attachment(self, model):
|
||||
if model != self.__current_model:
|
||||
current_record = property(__get_current_record, __set_current_record)
|
||||
|
||||
def update_attachment(self, record):
|
||||
if record != self.current_record:
|
||||
return False
|
||||
if model and self.signal_connected('attachment-count'):
|
||||
attachment_count = model.get_attachment_count()
|
||||
if record and self.signal_connected('attachment-count'):
|
||||
attachment_count = record.get_attachment_count()
|
||||
self.signal('attachment-count', attachment_count)
|
||||
return False
|
||||
|
||||
@@ -237,30 +229,32 @@ class Screen(SignalEvent):
|
||||
for view in self.views:
|
||||
view.destroy()
|
||||
del view
|
||||
#del self.current_model
|
||||
self.models.signal_unconnect(self)
|
||||
del self.models
|
||||
self.group.signal_unconnect(self)
|
||||
del self.views
|
||||
|
||||
def switch_view(self):
|
||||
def switch_view(self, view_type=None):
|
||||
self.current_view.set_value()
|
||||
if self.current_model and self.current_model not in self.models.models:
|
||||
self.current_model = None
|
||||
if len(self.view_to_load):
|
||||
self.load_view_to_load()
|
||||
self.__current_view = len(self.views) - 1
|
||||
else:
|
||||
self.__current_view = (self.__current_view + 1) % len(self.views)
|
||||
if self.current_record and self.current_record not in self.group:
|
||||
self.current_record = None
|
||||
for i in xrange(len(self.views) + len(self.view_to_load)):
|
||||
if len(self.view_to_load):
|
||||
self.load_view_to_load()
|
||||
self.__current_view = len(self.views) - 1
|
||||
else:
|
||||
self.__current_view = (self.__current_view + 1) % len(self.views)
|
||||
if not view_type:
|
||||
break
|
||||
elif self.current_view.view_type == view_type:
|
||||
break
|
||||
self.screen_container.set(self.current_view.widget)
|
||||
if self.current_model:
|
||||
self.current_model.validate_set()
|
||||
if self.current_record:
|
||||
self.current_record.validate_set()
|
||||
else:
|
||||
if self.current_view.view_type == 'form':
|
||||
self.new()
|
||||
self.current_view.set_cursor()
|
||||
self.current_view.cancel()
|
||||
self.display()
|
||||
# TODO: set True or False accoring to the type
|
||||
|
||||
def load_view_to_load(self):
|
||||
if len(self.view_to_load):
|
||||
@@ -272,9 +266,6 @@ class Screen(SignalEvent):
|
||||
view_type = self.view_to_load.pop(0)
|
||||
self.add_view_id(view_id, view_type)
|
||||
|
||||
def add_view_custom(self, arch, fields, display=False, toolbar=None):
|
||||
return self.add_view(arch, fields, display, True, toolbar=toolbar)
|
||||
|
||||
def add_view_id(self, view_id, view_type, display=False, context=None):
|
||||
if view_type in self.views_preload:
|
||||
return self.add_view(self.views_preload[view_type]['arch'],
|
||||
@@ -285,13 +276,15 @@ class Screen(SignalEvent):
|
||||
ctx = {}
|
||||
ctx.update(rpc.CONTEXT)
|
||||
ctx.update(self.context)
|
||||
args = ('model', self.model_name, 'fields_view_get',
|
||||
view_id, view_type, ctx,
|
||||
self.parent and False or CONFIG['form.toolbar'])
|
||||
try:
|
||||
view = self.rpc.fields_view_get(view_id, view_type, ctx,
|
||||
self.hastoolbar)
|
||||
view = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
view = self.rpc.fields_view_get(view_id, view_type, ctx,
|
||||
self.hastoolbar)
|
||||
view = common.process_exception(exception, self.window, *args)
|
||||
if not view:
|
||||
return
|
||||
if self.exclude_field:
|
||||
if self.exclude_field in view['fields']:
|
||||
view['fields'][self.exclude_field]['states'] = {'invisible': True}
|
||||
@@ -302,8 +295,7 @@ class Screen(SignalEvent):
|
||||
return self.add_view(view['arch'], view['fields'], display,
|
||||
toolbar=view.get('toolbar', False), context=context)
|
||||
|
||||
def add_view(self, arch, fields, display=False, custom=False, toolbar=None,
|
||||
context=None):
|
||||
def add_view(self, arch, fields, display=False, toolbar=None, context=None):
|
||||
if toolbar is None:
|
||||
toolbar = {}
|
||||
def _parse_fields(node, fields):
|
||||
@@ -347,25 +339,26 @@ class Screen(SignalEvent):
|
||||
self.fields_view_tree = {'arch': arch, 'fields': fields}
|
||||
|
||||
from tryton.gui.window.view_form.view.widget_parse import WidgetParse
|
||||
models = self.models.models
|
||||
if self.current_model and (self.current_model not in models):
|
||||
models = models + [self.current_model]
|
||||
if custom:
|
||||
self.models.add_fields_custom(fields, self.models)
|
||||
else:
|
||||
self.models.add_fields(fields, self.models, context=context)
|
||||
|
||||
self.fields = self.models.fields
|
||||
if self.current_record and (self.current_record not in self.group):
|
||||
self.group.append(self.current_record)
|
||||
self.group.add_fields(fields, context=context)
|
||||
|
||||
parser = WidgetParse(parent=self.parent, window=self.window)
|
||||
view = parser.parse(self, xml_dom, self.fields, toolbar=toolbar)
|
||||
view = parser.parse(self, xml_dom, self.group.fields, toolbar=toolbar)
|
||||
|
||||
self.views.append(view)
|
||||
|
||||
if display:
|
||||
self.__current_view = len(self.views) - 1
|
||||
self.current_view.display()
|
||||
self.screen_container.set(view.widget)
|
||||
self.screen_container.set(self.current_view.widget)
|
||||
if self.current_record:
|
||||
self.current_record.validate_set()
|
||||
else:
|
||||
if self.current_view.view_type == 'form':
|
||||
self.new()
|
||||
self.current_view.set_cursor()
|
||||
self.current_view.cancel()
|
||||
self.display()
|
||||
return view
|
||||
|
||||
def editable_get(self):
|
||||
@@ -375,11 +368,12 @@ class Screen(SignalEvent):
|
||||
return False
|
||||
|
||||
def new(self, default=True, context=None):
|
||||
if self.models.readonly:
|
||||
if self.group.readonly:
|
||||
return
|
||||
if context is None:
|
||||
context = {}
|
||||
if self.current_view and ((self.current_view.view_type == 'tree' \
|
||||
if self.current_view and \
|
||||
((self.current_view.view_type == 'tree' \
|
||||
and not (hasattr(self.current_view.widget_tree, 'editable') \
|
||||
and self.current_view.widget_tree.editable)) \
|
||||
or self.current_view.view_type == 'graph'):
|
||||
@@ -393,18 +387,15 @@ class Screen(SignalEvent):
|
||||
ctx.update(rpc.CONTEXT)
|
||||
ctx.update(self.context)
|
||||
ctx.update(context)
|
||||
model = self.models.model_new(default, self.domain, ctx)
|
||||
if (not self.current_view) \
|
||||
or self.current_view.model_add_new \
|
||||
or self.create_new:
|
||||
self.models.model_add(model, self.new_model_position())
|
||||
self.current_model = model
|
||||
self.current_model.validate_set()
|
||||
record = self.group.new(default, self.domain, ctx)
|
||||
self.group.add(record, self.new_model_position())
|
||||
self.current_record = record
|
||||
self.current_record.validate_set()
|
||||
self.display()
|
||||
if self.current_view:
|
||||
self.current_view.set_cursor(new=True)
|
||||
self.request_set()
|
||||
return self.current_model
|
||||
return self.current_record
|
||||
|
||||
def new_model_position(self):
|
||||
position = -1
|
||||
@@ -416,78 +407,77 @@ class Screen(SignalEvent):
|
||||
|
||||
def set_on_write(self, func_name):
|
||||
if func_name:
|
||||
self.models.on_write.add(func_name)
|
||||
self.group.on_write.add(func_name)
|
||||
|
||||
def cancel_current(self):
|
||||
if self.current_model:
|
||||
self.current_model.cancel()
|
||||
if self.current_model.id < 0:
|
||||
if self.current_record:
|
||||
self.current_record.cancel()
|
||||
if self.current_record.id < 0:
|
||||
self.remove()
|
||||
if self.current_view:
|
||||
self.current_view.cancel()
|
||||
|
||||
def save_current(self):
|
||||
if not self.current_model:
|
||||
if not self.current_record:
|
||||
return False
|
||||
self.current_view.set_value()
|
||||
obj_id = False
|
||||
if self.current_model.validate():
|
||||
obj_id = self.current_model.save(force_reload=True)
|
||||
if self.current_record.validate():
|
||||
obj_id = self.current_record.save(force_reload=True)
|
||||
else:
|
||||
self.current_view.set_cursor()
|
||||
self.current_view.display()
|
||||
return False
|
||||
if self.current_view.view_type == 'tree':
|
||||
for model in self.models.models:
|
||||
if model.is_modified():
|
||||
if model.validate():
|
||||
obj_id = model.save(force_reload=True)
|
||||
for record in self.group:
|
||||
if record.is_modified():
|
||||
if record.validate():
|
||||
obj_id = record.save(force_reload=True)
|
||||
else:
|
||||
self.current_view.set_cursor()
|
||||
self.current_model = model
|
||||
self.current_record = record
|
||||
self.current_view.set_cursor()
|
||||
self.display()
|
||||
return False
|
||||
self.current_view.set_cursor()
|
||||
self.display()
|
||||
if self.current_model not in self.models:
|
||||
self.models.model_add(self.current_model, modified=False)
|
||||
self.display()
|
||||
if self.current_record not in self.group:
|
||||
self.group.add(self.current_record, modified=False)
|
||||
self.request_set()
|
||||
return obj_id
|
||||
|
||||
def _get_current_view(self):
|
||||
def __get_current_view(self):
|
||||
if not len(self.views):
|
||||
return None
|
||||
return self.views[self.__current_view]
|
||||
current_view = property(_get_current_view)
|
||||
|
||||
current_view = property(__get_current_view)
|
||||
|
||||
def get(self, get_readonly=True, includeid=False, check_load=True,
|
||||
get_modifiedonly=False):
|
||||
if not self.current_model:
|
||||
if not self.current_record:
|
||||
return None
|
||||
self.current_view.set_value()
|
||||
return self.current_model.get(get_readonly=get_readonly,
|
||||
return self.current_record.get(get_readonly=get_readonly,
|
||||
includeid=includeid, check_load=check_load,
|
||||
get_modifiedonly=get_modifiedonly)
|
||||
|
||||
def is_modified(self):
|
||||
if not self.current_model:
|
||||
return False
|
||||
self.current_view.set_value()
|
||||
res = False
|
||||
if self.current_view.view_type != 'tree':
|
||||
res = self.current_model.is_modified()
|
||||
res = self.current_record and self.current_record.is_modified()
|
||||
else:
|
||||
for model in self.models.models:
|
||||
if model.is_modified():
|
||||
for record in self.group:
|
||||
if record.is_modified():
|
||||
res = True
|
||||
return res
|
||||
|
||||
def reload(self, writen=False):
|
||||
ids = self.sel_ids_get()
|
||||
self.models.reload(ids)
|
||||
self.group.reload(ids)
|
||||
if writen:
|
||||
self.models.writen(ids)
|
||||
self.group.writen(ids)
|
||||
if self.parent:
|
||||
self.parent.reload()
|
||||
self.display()
|
||||
@@ -496,33 +486,36 @@ class Screen(SignalEvent):
|
||||
def remove(self, delete=False, remove=False):
|
||||
res = False
|
||||
reload_ids = []
|
||||
if self.current_view.view_type == 'form' and self.current_model:
|
||||
obj_id = self.current_model.id
|
||||
if delete and obj_id > 0:
|
||||
if self.current_view.view_type == 'form' and self.current_record:
|
||||
record_id = self.current_record.id
|
||||
if delete and record_id > 0:
|
||||
context = {}
|
||||
context.update(rpc.CONTEXT)
|
||||
context.update(self.context)
|
||||
context['_timestamp'] = self.current_model.get_timestamp()
|
||||
context['_timestamp'] = self.current_record.get_timestamp()
|
||||
reload_ids = self.group.on_write_ids(record_id)
|
||||
if reload_ids and record_id in reload_ids:
|
||||
reload_ids.remove(record_id)
|
||||
args = ('model', self.model_name, 'delete', [record_id],
|
||||
context)
|
||||
try:
|
||||
reload_ids = self.models.on_write_ids(obj_id)
|
||||
if reload_ids and obj_id in reload_ids:
|
||||
reload_ids.remove(obj_id)
|
||||
if not self.rpc.delete([obj_id], context):
|
||||
return False
|
||||
res = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
res = common.process_exception(exception, self.window,
|
||||
*args)
|
||||
if not res:
|
||||
return False
|
||||
self.current_view.set_cursor()
|
||||
if self.current_model in self.models.models:
|
||||
idx = self.models.models.index(self.current_model)
|
||||
self.models.remove(self.current_model, remove=remove)
|
||||
if self.models.models:
|
||||
idx = min(idx, len(self.models.models)-1)
|
||||
self.current_model = self.models.models[idx]
|
||||
if self.current_record in self.group:
|
||||
idx = self.group.index(self.current_record)
|
||||
self.group.remove(self.current_record, remove=remove)
|
||||
if self.group:
|
||||
idx = min(idx, len(self.group) - 1)
|
||||
self.current_record = self.group[idx]
|
||||
else:
|
||||
self.current_model = None
|
||||
self.current_record = None
|
||||
if reload_ids:
|
||||
self.models.reload(reload_ids)
|
||||
self.group.reload(reload_ids)
|
||||
self.display()
|
||||
res = True
|
||||
if self.current_view.view_type == 'tree':
|
||||
@@ -532,38 +525,41 @@ class Screen(SignalEvent):
|
||||
context.update(rpc.CONTEXT)
|
||||
context.update(self.context)
|
||||
context['_timestamp'] = {}
|
||||
for obj_id in ids:
|
||||
model = self.models.get_by_id(obj_id)
|
||||
context['_timestamp'].update(model.get_timestamp())
|
||||
for record_id in ids:
|
||||
record = self.group.get(record_id)
|
||||
context['_timestamp'].update(record.get_timestamp())
|
||||
reload_ids = self.group.on_write_ids(ids)
|
||||
if reload_ids:
|
||||
for record_id in ids:
|
||||
if record_id in reload_ids:
|
||||
reload_ids.remove(record_id)
|
||||
args = ('model', self.model_name, 'delete', ids,
|
||||
context)
|
||||
try:
|
||||
reload_ids = self.models.on_write_ids(ids)
|
||||
if reload_ids:
|
||||
for obj_id in ids:
|
||||
if obj_id in reload_ids:
|
||||
reload_ids.remove(obj_id)
|
||||
if not self.rpc.delete(ids, context):
|
||||
return False
|
||||
res = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
res = common.process_exception(exception, self.window,
|
||||
*args)
|
||||
if not res:
|
||||
return False
|
||||
sel_models = self.current_view.sel_models_get()
|
||||
if not sel_models:
|
||||
sel_records = self.current_view.selected_records()
|
||||
if not sel_records:
|
||||
return True
|
||||
idx = self.models.models.index(sel_models[0])
|
||||
for model in sel_models:
|
||||
idx = self.group.index(sel_records[0])
|
||||
for record in sel_records:
|
||||
# set current model to None to prevent __select_changed
|
||||
# to save the previous_model as it can be already deleted.
|
||||
self.current_model = None
|
||||
self.models.remove(model, remove=remove, signal=False)
|
||||
self.current_record = None
|
||||
self.group.remove(record, remove=remove, signal=False)
|
||||
# send record-changed only once
|
||||
model.signal('record-changed', model.parent)
|
||||
if self.models.models:
|
||||
idx = min(idx, len(self.models.models)-1)
|
||||
self.current_model = self.models.models[idx]
|
||||
record.signal('record-changed')
|
||||
if self.group:
|
||||
idx = min(idx, len(self.group) - 1)
|
||||
self.current_record = self.group[idx]
|
||||
else:
|
||||
self.current_model = None
|
||||
self.current_record = None
|
||||
if reload_ids:
|
||||
self.models.reload(reload_ids)
|
||||
self.group.reload(reload_ids)
|
||||
self.current_view.set_cursor()
|
||||
self.display()
|
||||
res = True
|
||||
@@ -571,12 +567,12 @@ class Screen(SignalEvent):
|
||||
return res
|
||||
|
||||
def load(self, ids, set_cursor=True, modified=False):
|
||||
self.models.load(ids, display=False, modified=modified)
|
||||
self.group.load(ids, display=False, modified=modified)
|
||||
self.current_view.reset()
|
||||
if ids:
|
||||
self.display(ids[0])
|
||||
else:
|
||||
self.current_model = None
|
||||
self.current_record = None
|
||||
self.display()
|
||||
if set_cursor:
|
||||
self.current_view.set_cursor()
|
||||
@@ -584,7 +580,7 @@ class Screen(SignalEvent):
|
||||
|
||||
def display(self, res_id=None, set_cursor=False):
|
||||
if res_id:
|
||||
self.current_model = self.models[res_id]
|
||||
self.current_record = self.group.get(res_id)
|
||||
if self.views:
|
||||
#XXX To remove when calendar will be implemented
|
||||
if self.current_view.view_type == 'calendar' and \
|
||||
@@ -592,9 +588,9 @@ class Screen(SignalEvent):
|
||||
self.switch_view()
|
||||
self.current_view.display()
|
||||
self.current_view.widget.set_sensitive(
|
||||
bool(self.models.models \
|
||||
bool(self.group \
|
||||
or (self.current_view.view_type != 'form') \
|
||||
or self.current_model))
|
||||
or self.current_record))
|
||||
self.search_active(self.current_view.view_type \
|
||||
in ('tree', 'graph', 'calendar'))
|
||||
if set_cursor:
|
||||
@@ -603,32 +599,32 @@ class Screen(SignalEvent):
|
||||
def display_next(self):
|
||||
self.current_view.set_value()
|
||||
self.current_view.set_cursor(reset_view=False)
|
||||
if self.current_model in self.models.models:
|
||||
idx = self.models.models.index(self.current_model)
|
||||
if self.current_record in self.group:
|
||||
idx = self.group.index(self.current_record)
|
||||
inc = 1
|
||||
if self.current_view.view_type == 'tree':
|
||||
start, end = self.current_view.widget_tree.get_visible_range()
|
||||
inc += end[0] - start[0]
|
||||
if inc >= 4 and (end[0] + 1) < len(self.models.models):
|
||||
if inc >= 4 and (end[0] + 1) < len(self.group):
|
||||
inc -= 3
|
||||
vadjustment = self.current_view.widget_tree.get_vadjustment()
|
||||
vadjustment.value = vadjustment.value + vadjustment.page_increment
|
||||
idx = idx + inc
|
||||
if idx >= len(self.models.models):
|
||||
idx = len(self.models.models) - 1
|
||||
self.current_model = self.models.models[idx]
|
||||
if idx >= len(self.group):
|
||||
idx = len(self.group) - 1
|
||||
self.current_record = self.group[idx]
|
||||
else:
|
||||
self.current_model = len(self.models.models) \
|
||||
and self.models.models[0]
|
||||
self.current_record = len(self.group) \
|
||||
and self.group[0]
|
||||
self.current_view.set_cursor(reset_view=False)
|
||||
if self.current_model:
|
||||
self.current_model.validate_set()
|
||||
if self.current_record:
|
||||
self.current_record.validate_set()
|
||||
self.display()
|
||||
|
||||
def display_prev(self):
|
||||
self.current_view.set_value()
|
||||
self.current_view.set_cursor(reset_view=False)
|
||||
if self.current_model in self.models.models:
|
||||
if self.current_record in self.group:
|
||||
inc = 1
|
||||
if self.current_view.view_type == 'tree':
|
||||
range = self.current_view.widget_tree.get_visible_range()
|
||||
@@ -642,38 +638,38 @@ class Screen(SignalEvent):
|
||||
if vadjustment.value:
|
||||
vadjustment.value = vadjustment.value - \
|
||||
vadjustment.page_increment
|
||||
idx = self.models.models.index(self.current_model) - inc
|
||||
idx = self.group.index(self.current_record) - inc
|
||||
if idx < 0:
|
||||
idx = 0
|
||||
self.current_model = self.models.models[idx]
|
||||
self.current_record = self.group[idx]
|
||||
else:
|
||||
self.current_model = len(self.models.models) \
|
||||
and self.models.models[-1]
|
||||
self.current_record = len(self.group) \
|
||||
and self.group[-1]
|
||||
self.current_view.set_cursor(reset_view=False)
|
||||
if self.current_model:
|
||||
self.current_model.validate_set()
|
||||
if self.current_record:
|
||||
self.current_record.validate_set()
|
||||
self.display()
|
||||
|
||||
def sel_ids_get(self):
|
||||
return self.current_view.sel_ids_get()
|
||||
|
||||
def id_get(self):
|
||||
if not self.current_model:
|
||||
if not self.current_record:
|
||||
return False
|
||||
return self.current_model.id
|
||||
return self.current_record.id
|
||||
|
||||
def ids_get(self):
|
||||
return [x.id for x in self.models if x.id]
|
||||
return [x.id for x in self.group if x.id]
|
||||
|
||||
def clear(self):
|
||||
self.models.clear()
|
||||
self.current_model = None
|
||||
self.group.clear()
|
||||
self.current_record = None
|
||||
|
||||
def on_change(self, fieldname, attr):
|
||||
self.current_model.on_change(fieldname, attr)
|
||||
self.current_record.on_change(fieldname, attr)
|
||||
self.display()
|
||||
|
||||
def request_set(self):
|
||||
if self.name == 'res.request':
|
||||
if self.model_name == 'res.request':
|
||||
from tryton.gui.main import Main
|
||||
Main.get_main().request_set()
|
||||
@@ -12,49 +12,6 @@ from tryton.pyson import PYSONEncoder
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
class ViewWidget(object):
|
||||
|
||||
def __init__(self, parent, widget, widget_name):
|
||||
self.view_form = parent
|
||||
self.widget = widget
|
||||
self.widget._view = self
|
||||
self.widget_name = widget_name
|
||||
|
||||
def display(self, model):
|
||||
if not model:
|
||||
self.widget.display(model, False)
|
||||
return False
|
||||
modelfield = model.mgroup.mfields.get(self.widget_name, None)
|
||||
if modelfield:
|
||||
modelfield.state_set(model)
|
||||
self.widget.display(model, modelfield)
|
||||
elif isinstance(self.widget, Action):
|
||||
self.widget.display(model, False)
|
||||
|
||||
def reset(self, model):
|
||||
modelfield = None
|
||||
if model:
|
||||
modelfield = model.mgroup.mfields.get(self.widget_name, None)
|
||||
if modelfield and 'valid' in modelfield.get_state_attrs(model):
|
||||
modelfield.get_state_attrs(model)['valid'] = True
|
||||
self.display(model)
|
||||
|
||||
def set_value(self, model):
|
||||
if self.widget_name in model.mgroup.mfields:
|
||||
self.widget.set_value(model, model.mgroup.mfields[self.widget_name])
|
||||
|
||||
def _get_model(self):
|
||||
return self.view_form.screen.current_model
|
||||
|
||||
model = property(_get_model)
|
||||
|
||||
def _get_modelfield(self):
|
||||
if self.model:
|
||||
return self.model.mgroup.mfields[self.widget_name]
|
||||
|
||||
modelfield = property(_get_modelfield)
|
||||
|
||||
|
||||
class ViewForm(ParserView):
|
||||
|
||||
def __init__(self, window, screen, widget, children=None,
|
||||
@@ -62,14 +19,14 @@ class ViewForm(ParserView):
|
||||
super(ViewForm, self).__init__(window, screen, widget, children,
|
||||
buttons, toolbar, notebooks, cursor_widget)
|
||||
self.view_type = 'form'
|
||||
self.model_add_new = False
|
||||
|
||||
for button in self.buttons:
|
||||
button.form = self
|
||||
|
||||
self.widgets = dict((name, [ViewWidget(self, widget, name)
|
||||
for widget in widgets])
|
||||
for name, widgets in children.iteritems())
|
||||
self.widgets = children
|
||||
for widgets in self.widgets.itervalues():
|
||||
for widget in widgets:
|
||||
widget.view = self
|
||||
|
||||
vbox = gtk.VBox()
|
||||
vp = gtk.Viewport()
|
||||
@@ -145,8 +102,8 @@ class ViewForm(ParserView):
|
||||
act = action.copy()
|
||||
if atype in ('print', 'action'):
|
||||
self.screen.save_current()
|
||||
obj_id = self.screen.current_model \
|
||||
and self.screen.current_model.id
|
||||
obj_id = self.screen.current_record \
|
||||
and self.screen.current_record.id
|
||||
if obj_id < 0:
|
||||
if atype in ('print'):
|
||||
message(_('You must save this record ' \
|
||||
@@ -157,15 +114,15 @@ class ViewForm(ParserView):
|
||||
return False
|
||||
email = {}
|
||||
if 'email' in action:
|
||||
email = self.screen.current_model.expr_eval(action['email'])
|
||||
email = self.screen.current_record.expr_eval(action['email'])
|
||||
if not email:
|
||||
email = {}
|
||||
email['subject'] = action['name'].replace('_', '')
|
||||
act['email'] = email
|
||||
self.screen.display()
|
||||
if atype == 'relate':
|
||||
obj_id = self.screen.current_model \
|
||||
and self.screen.current_model.id
|
||||
obj_id = self.screen.current_record \
|
||||
and self.screen.current_record.id
|
||||
if not obj_id:
|
||||
message(_('You must select a record ' \
|
||||
'to be able to use the relate button !'), self.window)
|
||||
@@ -173,14 +130,14 @@ class ViewForm(ParserView):
|
||||
encoder = PYSONEncoder()
|
||||
if 'pyson_domain' in act:
|
||||
act['pyson_domain'] = encoder.encode(
|
||||
self.screen.current_model.expr_eval(
|
||||
self.screen.current_record.expr_eval(
|
||||
act['pyson_domain'], check_load=False))
|
||||
if 'pyson_context' in act:
|
||||
act['pyson_context'] = encoder.encode(
|
||||
self.screen.current_model.expr_eval(
|
||||
self.screen.current_record.expr_eval(
|
||||
act['pyson_context'], check_load=False))
|
||||
data = {
|
||||
'model': self.screen.name,
|
||||
'model': self.screen.model_name,
|
||||
'id': obj_id,
|
||||
'ids': [obj_id],
|
||||
}
|
||||
@@ -206,49 +163,60 @@ class ViewForm(ParserView):
|
||||
def cancel(self):
|
||||
for widgets in self.widgets.itervalues():
|
||||
for widget in widgets:
|
||||
widget.widget.cancel()
|
||||
widget.cancel()
|
||||
|
||||
def set_value(self):
|
||||
model = self.screen.current_model
|
||||
if model:
|
||||
for widgets in self.widgets.itervalues():
|
||||
for widget in widgets:
|
||||
widget.set_value(model)
|
||||
record = self.screen.current_record
|
||||
if record:
|
||||
for name, widgets in self.widgets.iteritems():
|
||||
if name in record.group.fields:
|
||||
field = record.group.fields[name]
|
||||
for widget in widgets:
|
||||
widget.set_value(record, field)
|
||||
|
||||
def sel_ids_get(self):
|
||||
if self.screen.current_model:
|
||||
return [self.screen.current_model.id]
|
||||
if self.screen.current_record:
|
||||
return [self.screen.current_record.id]
|
||||
return []
|
||||
|
||||
def sel_models_get(self):
|
||||
if self.screen.current_model:
|
||||
return [self.screen.current_model]
|
||||
def selected_records(self):
|
||||
if self.screen.current_record:
|
||||
return [self.screen.current_record]
|
||||
return []
|
||||
|
||||
def reset(self):
|
||||
model = self.screen.current_model
|
||||
for name, widgets in self.widgets.iteritems():
|
||||
for widget in widgets:
|
||||
widget.reset(model)
|
||||
record = self.screen.current_record
|
||||
if record:
|
||||
for name, widgets in self.widgets.iteritems():
|
||||
field = record.group.fields.get(name)
|
||||
if field and 'valid' in field.get_state_attrs(record):
|
||||
for widget in widgets:
|
||||
field.get_state_attrs(record)['valid'] = True
|
||||
widget.display(record, field)
|
||||
|
||||
def signal_record_changed(self, *args):
|
||||
for widgets in self.widgets.itervalues():
|
||||
for widget in widgets:
|
||||
if hasattr(widget.widget, 'screen'):
|
||||
for view in widget.widget.screen.views:
|
||||
if hasattr(widget, 'screen'):
|
||||
for view in widget.screen.views:
|
||||
view.signal_record_changed(*args)
|
||||
|
||||
def display(self):
|
||||
model = self.screen.current_model
|
||||
if model:
|
||||
# Force to set mfields in model
|
||||
for field in model.mgroup.fields:
|
||||
model[field].get(model, check_load=False)
|
||||
for widgets in self.widgets.itervalues():
|
||||
record = self.screen.current_record
|
||||
if record:
|
||||
# Force to set fields in record
|
||||
for field in record.group.fields:
|
||||
record[field].get(record, check_load=False)
|
||||
for name, widgets in self.widgets.iteritems():
|
||||
field = None
|
||||
if record:
|
||||
field = record.group.fields.get(name)
|
||||
if field:
|
||||
field.state_set(record)
|
||||
for widget in widgets:
|
||||
widget.display(model)
|
||||
widget.display(record, field)
|
||||
for button in self.buttons:
|
||||
button.state_set(model)
|
||||
button.state_set(record)
|
||||
return True
|
||||
|
||||
def set_cursor(self, new=False, reset_view=True):
|
||||
@@ -256,25 +224,25 @@ class ViewForm(ParserView):
|
||||
for notebook in self.notebooks:
|
||||
notebook.set_current_page(0)
|
||||
if self.cursor_widget in self.widgets:
|
||||
self.widgets[self.cursor_widget][0].widget.grab_focus()
|
||||
model = self.screen.current_model
|
||||
self.widgets[self.cursor_widget][0].grab_focus()
|
||||
record = self.screen.current_record
|
||||
position = reduce(lambda x, y: x + len(y), self.widgets, 0)
|
||||
focus_widget = None
|
||||
if model:
|
||||
for widgets in self.widgets.itervalues():
|
||||
if record:
|
||||
for name, widgets in self.widgets.iteritems():
|
||||
for widget in widgets:
|
||||
modelfield = model.mgroup.mfields.get(widget.widget_name, None)
|
||||
if not modelfield:
|
||||
field = record.group.fields.get(name)
|
||||
if not field:
|
||||
continue
|
||||
if not modelfield.get_state_attrs(model).get('valid', True):
|
||||
if widget.widget.position > position:
|
||||
if not field.get_state_attrs(record).get('valid', True):
|
||||
if widget.position > position:
|
||||
continue
|
||||
position = widget.widget.position
|
||||
position = widget.position
|
||||
focus_widget = widget
|
||||
if focus_widget:
|
||||
for notebook in self.notebooks:
|
||||
for i in range(notebook.get_n_pages()):
|
||||
child = notebook.get_nth_page(i)
|
||||
if focus_widget.widget.widget.is_ancestor(child):
|
||||
if focus_widget.widget.is_ancestor(child):
|
||||
notebook.set_current_page(i)
|
||||
focus_widget.widget.grab_focus()
|
||||
focus_widget.grab_focus()
|
||||
@@ -13,8 +13,9 @@ _ = gettext.gettext
|
||||
class Binary(WidgetInterface):
|
||||
"Binary"
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
super(Binary, self).__init__(window, parent, model, attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(Binary, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
|
||||
self.tooltips = Tooltips()
|
||||
|
||||
@@ -52,8 +53,6 @@ class Binary(WidgetInterface):
|
||||
|
||||
self.tooltips.enable()
|
||||
|
||||
self.model_field = None
|
||||
|
||||
def _readonly_set(self, value):
|
||||
if value:
|
||||
self.but_new.hide()
|
||||
@@ -71,48 +70,47 @@ class Binary(WidgetInterface):
|
||||
def sig_new(self, widget=None):
|
||||
try:
|
||||
filename = file_selection(_('Open...'),
|
||||
parent=self._window)
|
||||
if filename and self.model_field:
|
||||
self.model_field.set_client(self._view.model,
|
||||
parent=self.window)
|
||||
if filename and self.field:
|
||||
self.field.set_client(self.record,
|
||||
base64.encodestring(file(filename, 'rb').read()))
|
||||
fname = self.attrs.get('fname_widget', False)
|
||||
if fname:
|
||||
self.parent.value = {fname:os.path.basename(filename)}
|
||||
self.display(self._view.model, self.model_field)
|
||||
self.display(self.record, self.field)
|
||||
except Exception, exception:
|
||||
warning(_('Error reading the file.\nError message:\n%s') \
|
||||
% str(exception), self._window, _('Error'))
|
||||
% str(exception), self.window, _('Error'))
|
||||
|
||||
def sig_save_as(self, widget=None):
|
||||
try:
|
||||
filename = file_selection(_('Save As...'),
|
||||
parent=self._window, action=gtk.FILE_CHOOSER_ACTION_SAVE)
|
||||
if filename and self.model_field:
|
||||
parent=self.window, action=gtk.FILE_CHOOSER_ACTION_SAVE)
|
||||
if filename and self.field:
|
||||
file_p = file(filename,'wb+')
|
||||
file_p.write(base64.decodestring(
|
||||
self.model_field.get(self._view.model)))
|
||||
self.field.get(self.record)))
|
||||
file_p.close()
|
||||
except Exception, exception:
|
||||
warning(_('Error writing the file.\nError message:\n%s') \
|
||||
% str(exception), self._window, _('Error'))
|
||||
% str(exception), self.window, _('Error'))
|
||||
|
||||
def sig_remove(self, widget=None):
|
||||
if self.model_field:
|
||||
self.model_field.set_client(self._view.model, False)
|
||||
if self.field:
|
||||
self.field.set_client(self.record, False)
|
||||
fname = self.attrs.get('fname_widget', False)
|
||||
if fname:
|
||||
self.parent.value = {fname:False}
|
||||
self.display(self._view.model, self.model_field)
|
||||
self.display(self.record, self.field)
|
||||
|
||||
def display(self, model, model_field):
|
||||
super(Binary, self).display(model, model_field)
|
||||
if not model_field:
|
||||
def display(self, record, field):
|
||||
super(Binary, self).display(record, field)
|
||||
if not field:
|
||||
self.wid_text.set_text('')
|
||||
self.but_save_as.set_sensitive(False)
|
||||
return False
|
||||
self.model_field = model_field
|
||||
self.wid_text.set_text(self._size_get(model_field.get(model)))
|
||||
self.but_save_as.set_sensitive(bool(model_field.get(model)))
|
||||
self.wid_text.set_text(self._size_get(field.get(record)))
|
||||
self.but_save_as.set_sensitive(bool(field.get(record)))
|
||||
return True
|
||||
|
||||
def display_value(self):
|
||||
@@ -121,7 +119,7 @@ class Binary(WidgetInterface):
|
||||
def _size_get(self, value):
|
||||
return value and ('%d ' + _('bytes')) % len(value) or ''
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
def set_value(self, record, field):
|
||||
return
|
||||
|
||||
def _color_widget(self):
|
||||
|
||||
@@ -18,8 +18,9 @@ _ = gettext.gettext
|
||||
class Calendar(WidgetInterface):
|
||||
"Calendar"
|
||||
|
||||
def __init__(self, window, parent=None, model=None, attrs=None):
|
||||
super(Calendar, self).__init__(window, parent, model=model, attrs=attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(Calendar, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
|
||||
self.format = date_format()
|
||||
self.widget = date_widget.ComplexEntry(self.format, spacing=0)
|
||||
@@ -66,7 +67,7 @@ class Calendar(WidgetInterface):
|
||||
def grab_focus(self):
|
||||
return self.entry.grab_focus()
|
||||
|
||||
def get_value(self, model):
|
||||
def get_value(self, record):
|
||||
value = self.entry.get_text()
|
||||
if value == '':
|
||||
return False
|
||||
@@ -76,16 +77,16 @@ class Calendar(WidgetInterface):
|
||||
return False
|
||||
return datetime_strftime(date, DT_FORMAT)
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
model_field.set_client(model, self.get_value(model))
|
||||
def set_value(self, record, field):
|
||||
field.set_client(record, self.get_value(record))
|
||||
return True
|
||||
|
||||
def display(self, model, model_field):
|
||||
if not model_field:
|
||||
def display(self, record, field):
|
||||
if not field:
|
||||
self.entry.clear()
|
||||
return False
|
||||
super(Calendar, self).display(model, model_field)
|
||||
value = model_field.get_client(model)
|
||||
super(Calendar, self).display(record, field)
|
||||
value = field.get_client(record)
|
||||
if not value:
|
||||
self.entry.clear()
|
||||
else:
|
||||
@@ -109,7 +110,7 @@ class Calendar(WidgetInterface):
|
||||
return self.entry.get_text()
|
||||
|
||||
def cal_open(self, widget):
|
||||
win = gtk.Dialog(_('Date Selection'), self._window,
|
||||
win = gtk.Dialog(_('Date Selection'), self.window,
|
||||
gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_OK, gtk.RESPONSE_OK))
|
||||
@@ -127,7 +128,7 @@ class Calendar(WidgetInterface):
|
||||
win.show_all()
|
||||
|
||||
try:
|
||||
val = self.get_value(self.model)
|
||||
val = self.get_value(self.record)
|
||||
if val:
|
||||
cal.select_month(int(val[5:7])-1, int(val[0:4]))
|
||||
cal.select_day(int(val[8:10]))
|
||||
@@ -147,15 +148,16 @@ class Calendar(WidgetInterface):
|
||||
format = format.replace('%Y', '0%Y')
|
||||
self.entry.set_text(datetime_strftime(date, format))
|
||||
self._focus_out()
|
||||
self._window.present()
|
||||
self.window.present()
|
||||
win.destroy()
|
||||
|
||||
|
||||
class DateTime(WidgetInterface):
|
||||
"DateTime"
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
super(DateTime, self).__init__(window, parent, model, attrs=attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(DateTime, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
|
||||
self.format = date_format() + ' ' + HM_FORMAT
|
||||
self.widget = date_widget.ComplexEntry(self.format, spacing=0)
|
||||
@@ -201,7 +203,7 @@ class DateTime(WidgetInterface):
|
||||
def grab_focus(self):
|
||||
return self.entry.grab_focus()
|
||||
|
||||
def get_value(self, model, timezone=True):
|
||||
def get_value(self, record, timezone=True):
|
||||
value = self.entry.get_text()
|
||||
if value == '':
|
||||
return False
|
||||
@@ -221,15 +223,15 @@ class DateTime(WidgetInterface):
|
||||
pass
|
||||
return datetime_strftime(date, DHM_FORMAT)
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
model_field.set_client(model, self.get_value(model))
|
||||
def set_value(self, record, field):
|
||||
field.set_client(record, self.get_value(record))
|
||||
return True
|
||||
|
||||
def display(self, model, model_field):
|
||||
super(DateTime, self).display(model, model_field)
|
||||
if not model_field:
|
||||
def display(self, record, field):
|
||||
super(DateTime, self).display(record, field)
|
||||
if not field:
|
||||
return self.show(False)
|
||||
self.show(model_field.get_client(model))
|
||||
self.show(field.get_client(record))
|
||||
|
||||
def show(self, dt_val, timezone=True):
|
||||
if not dt_val:
|
||||
@@ -263,7 +265,7 @@ class DateTime(WidgetInterface):
|
||||
return self.entry.get_text()
|
||||
|
||||
def cal_open(self, widget):
|
||||
win = gtk.Dialog(_('Date Time Selection'), self._window,
|
||||
win = gtk.Dialog(_('Date Time Selection'), self.window,
|
||||
gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_OK, gtk.RESPONSE_OK))
|
||||
@@ -292,7 +294,7 @@ class DateTime(WidgetInterface):
|
||||
win.show_all()
|
||||
|
||||
try:
|
||||
val = self.get_value(self.model, timezone=False)
|
||||
val = self.get_value(self.record, timezone=False)
|
||||
if val:
|
||||
widget_hour.set_value(int(val[11:13]))
|
||||
widget_minute.set_value(int(val[-5:-3]))
|
||||
@@ -314,5 +316,5 @@ class DateTime(WidgetInterface):
|
||||
value = datetime_strftime(date, DHM_FORMAT)
|
||||
self.show(value, timezone=False)
|
||||
self._focus_out()
|
||||
self._window.present()
|
||||
self.window.present()
|
||||
win.destroy()
|
||||
@@ -6,10 +6,8 @@ from interface import WidgetInterface
|
||||
class Char(WidgetInterface):
|
||||
"Char"
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
if attrs is None:
|
||||
attrs = {}
|
||||
super(Char, self).__init__(window, parent, model=model, attrs=attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(Char, self).__init__(field_name, model_name, window, attrs=attrs)
|
||||
|
||||
self.widget = gtk.HBox()
|
||||
self.entry = gtk.Entry()
|
||||
@@ -29,15 +27,15 @@ class Char(WidgetInterface):
|
||||
def grab_focus(self):
|
||||
return self.entry.grab_focus()
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
return model_field.set_client(model, self.entry.get_text() or False)
|
||||
def set_value(self, record, field):
|
||||
return field.set_client(record, self.entry.get_text() or False)
|
||||
|
||||
def display(self, model, model_field):
|
||||
super(Char, self).display(model, model_field)
|
||||
if not model_field:
|
||||
def display(self, record, field):
|
||||
super(Char, self).display(record, field)
|
||||
if not field:
|
||||
self.entry.set_text('')
|
||||
return False
|
||||
self.entry.set_text(model_field.get(model) or '')
|
||||
self.entry.set_text(field.get(record) or '')
|
||||
|
||||
def _readonly_set(self, value):
|
||||
super(Char, self)._readonly_set(value)
|
||||
@@ -50,6 +48,6 @@ class Char(WidgetInterface):
|
||||
|
||||
class Sha(Char):
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
super(Sha, self).__init__(window, parent, model=model, attrs=attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(Sha, self).__init__(field_name, model_name, window, attrs=attrs)
|
||||
self.entry.set_visibility(False)
|
||||
@@ -8,8 +8,9 @@ _ = gettext.gettext
|
||||
|
||||
class CheckBox(WidgetInterface):
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
super(CheckBox, self).__init__(window, parent, model, attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(CheckBox, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
self.widget = gtk.CheckButton()
|
||||
self.widget.connect('focus-in-event', lambda x, y: self._focus_in())
|
||||
self.widget.connect('focus-out-event', lambda x, y: self._focus_out())
|
||||
@@ -20,15 +21,15 @@ class CheckBox(WidgetInterface):
|
||||
super(CheckBox, self)._readonly_set(value)
|
||||
self.widget.set_sensitive(not value)
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
model_field.set_client(model, int(self.widget.get_active()))
|
||||
def set_value(self, record, field):
|
||||
field.set_client(record, self.widget.get_active())
|
||||
|
||||
def display(self, model, model_field):
|
||||
super(CheckBox, self).display(model, model_field)
|
||||
if not model_field:
|
||||
def display(self, record, field):
|
||||
super(CheckBox, self).display(record, field)
|
||||
if not field:
|
||||
self.widget.set_active(False)
|
||||
return False
|
||||
self.widget.set_active(bool(model_field.get(model)))
|
||||
self.widget.set_active(bool(field.get(record)))
|
||||
|
||||
def display_value(self):
|
||||
if self.widget.get_active():
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from char import Char
|
||||
from integer import Integer
|
||||
import locale
|
||||
|
||||
@@ -8,28 +7,29 @@ import locale
|
||||
class Float(Integer):
|
||||
"Float"
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
super(Float, self).__init__(window, parent, model=model, attrs=attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(Float, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
self.digits = attrs.get('digits', (16, 2))
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
def set_value(self, record, field):
|
||||
try:
|
||||
value = locale.atof(self.entry.get_text())
|
||||
except:
|
||||
value = 0.0
|
||||
return model_field.set_client(model, value)
|
||||
return field.set_client(record, value)
|
||||
|
||||
def display(self, model, model_field):
|
||||
super(Char, self).display(model, model_field)
|
||||
if not model_field:
|
||||
def display(self, record, field):
|
||||
super(Float, self).display(record, field)
|
||||
if not field:
|
||||
self.entry.set_text('')
|
||||
return False
|
||||
if isinstance(self.digits, str):
|
||||
digits = self._view.model.expr_eval(self.digits)
|
||||
digits = record.expr_eval(self.digits)
|
||||
else:
|
||||
digits = self.digits
|
||||
self.entry.set_text(locale.format('%.' + str(digits[1]) + 'f',
|
||||
model_field.get(model) or 0.0, True))
|
||||
field.get(record) or 0.0, True))
|
||||
|
||||
def sig_insert_text(self, entry, new_text, new_text_length, position):
|
||||
value = entry.get_text()
|
||||
@@ -42,7 +42,7 @@ class Float(Integer):
|
||||
return
|
||||
|
||||
if isinstance(self.digits, str):
|
||||
digits = self._view.model.expr_eval(self.digits)
|
||||
digits = self.record.expr_eval(self.digits)
|
||||
else:
|
||||
digits = self.digits
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import tryton.rpc as rpc
|
||||
|
||||
class FloatTime(WidgetInterface):
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
super(FloatTime, self).__init__(window, parent, model=model,
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(FloatTime, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
|
||||
self.widget = gtk.HBox()
|
||||
@@ -33,19 +33,19 @@ class FloatTime(WidgetInterface):
|
||||
def grab_focus(self):
|
||||
return self.entry.grab_focus()
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
def set_value(self, record, field):
|
||||
value = self.entry.get_text()
|
||||
if not value:
|
||||
return model_field.set_client(model, 0.0)
|
||||
return model_field.set_client(model,
|
||||
return field.set_client(record, 0.0)
|
||||
return field.set_client(record,
|
||||
common.text_to_float_time(value, self.conv))
|
||||
|
||||
def display(self, model, model_field):
|
||||
super(FloatTime, self).display(model, model_field)
|
||||
if not model_field:
|
||||
def display(self, record, field):
|
||||
super(FloatTime, self).display(record, field)
|
||||
if not field:
|
||||
self.entry.set_text('00:00')
|
||||
return False
|
||||
val = model_field.get(model)
|
||||
val = field.get(record)
|
||||
|
||||
self.entry.set_text(common.float_time_to_text(val, self.conv))
|
||||
|
||||
|
||||
@@ -16,8 +16,9 @@ NOIMAGE = file(os.path.join(PIXMAPS_DIR, 'tryton-noimage.png'), 'rb').read()
|
||||
|
||||
class Image(WidgetInterface):
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
super(Image, self).__init__(window, parent, model, attrs=attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(Image, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
|
||||
self.height = int(attrs.get('img_height', 100))
|
||||
self.width = int(attrs.get('img_width', 300))
|
||||
@@ -96,22 +97,22 @@ class Image(WidgetInterface):
|
||||
for pat in ("*.png", "*.jpg", "*.gif", "*.tif", "*.xpm"):
|
||||
filter_image.add_pattern(pat)
|
||||
|
||||
filename = file_selection(_('Open...'), parent=self._window,
|
||||
filename = file_selection(_('Open...'), parent=self.window,
|
||||
preview=True, filters=[filter_image, filter_all])
|
||||
if filename:
|
||||
self._view.modelfield.set_client(self._view.model,
|
||||
self.field.set_client(self.record,
|
||||
encodestring(file(filename, 'rb').read()))
|
||||
self.update_img()
|
||||
|
||||
def sig_save_as(self, widget):
|
||||
filename = file_selection(_('Save As...'), parent=self._window,
|
||||
filename = file_selection(_('Save As...'), parent=self.window,
|
||||
action=gtk.FILE_CHOOSER_ACTION_SAVE)
|
||||
if filename:
|
||||
file(filename, 'wb').write(decodestring(
|
||||
self._view.modelfield.get_client(self._view.model)))
|
||||
self.field.get_client(self.record)))
|
||||
|
||||
def sig_remove(self, widget):
|
||||
self._view.modelfield.set_client(self._view.model, False)
|
||||
self.field.set_client(self.record, False)
|
||||
self.update_img()
|
||||
|
||||
def drag_motion(self, widget, context, x, y, timestamp):
|
||||
@@ -127,26 +128,26 @@ class Image(WidgetInterface):
|
||||
if info == 0:
|
||||
uri = selection.get_text().split('\n')[0]
|
||||
if uri:
|
||||
self._view.modelfield.set_client(self._view.model,
|
||||
self.field.set_client(self.record,
|
||||
encodestring(urllib.urlopen(uri).read()))
|
||||
self.update_img()
|
||||
elif info == 1:
|
||||
uri = selection.data.split('\r\n')[0]
|
||||
if uri:
|
||||
self._view.modelfield.set_client(self._view.model,
|
||||
self.field.set_client(self.record,
|
||||
encodestring(urllib.urlopen(uri).read()))
|
||||
self.update_img()
|
||||
elif info == 2:
|
||||
data = selection.get_pixbuf()
|
||||
if data:
|
||||
self._view.modelfield.set_client(self._view.model,
|
||||
self.field.set_client(self.record,
|
||||
encodestring(data))
|
||||
self.update_img()
|
||||
|
||||
def update_img(self):
|
||||
value = None
|
||||
if self._view:
|
||||
value = self._view.modelfield.get_client(self._view.model)
|
||||
if self.field:
|
||||
value = self.field.get_client(self.record)
|
||||
if not value:
|
||||
data = NOIMAGE
|
||||
else:
|
||||
@@ -190,8 +191,8 @@ class Image(WidgetInterface):
|
||||
gtk.gdk.INTERP_BILINEAR)
|
||||
self.image.set_from_pixbuf(scaled)
|
||||
|
||||
def display(self, model, model_field):
|
||||
if not model_field:
|
||||
def display(self, record, field):
|
||||
if not field:
|
||||
return False
|
||||
super(Image, self).display(model, model_field)
|
||||
super(Image, self).display(record, field)
|
||||
self.update_img()
|
||||
@@ -7,26 +7,28 @@ import locale
|
||||
class Integer(Char):
|
||||
"Integer"
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
super(Integer, self).__init__(window, parent, model=model, attrs=attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(Integer, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
self.entry.set_max_length(0)
|
||||
self.entry.set_alignment(1.0)
|
||||
self.entry.connect('insert_text', self.sig_insert_text)
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
def set_value(self, record, field):
|
||||
try:
|
||||
value = locale.atoi(self.entry.get_text())
|
||||
except:
|
||||
value = 0
|
||||
return model_field.set_client(model, value)
|
||||
return field.set_client(record, value)
|
||||
|
||||
def display(self, model, model_field):
|
||||
super(Char, self).display(model, model_field)
|
||||
if not model_field:
|
||||
def display(self, record, field):
|
||||
# skip Char call because set_text doesn't work with int
|
||||
super(Char, self).display(record, field)
|
||||
if not field:
|
||||
self.entry.set_text('')
|
||||
return False
|
||||
self.entry.set_text(locale.format('%d',
|
||||
model_field.get(model) or 0, True))
|
||||
field.get(record) or 0, True))
|
||||
|
||||
def display_value(self):
|
||||
return self.entry.get_text()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
import gtk
|
||||
from tryton.rpc import RPCProxy
|
||||
import tryton.rpc as rpc
|
||||
from tryton.common import COLORS, process_exception, message
|
||||
from tryton.config import TRYTON_ICON
|
||||
@@ -16,7 +15,7 @@ _ATTRS_BOOLEAN = {
|
||||
'readonly': False
|
||||
}
|
||||
|
||||
def field_pref_set(field, name, model, value, client_value, dependance,
|
||||
def field_pref_set(field, name, model_name, value, client_value, dependance,
|
||||
window, reset=False):
|
||||
dialog = WidgetFieldPreference(window, reset=reset)
|
||||
if dependance is None:
|
||||
@@ -60,7 +59,7 @@ def field_pref_set(field, name, model, value, client_value, dependance,
|
||||
method = 'reset_default'
|
||||
else:
|
||||
method = 'set_default'
|
||||
args = ('model', 'ir.default', method, model, field, clause,
|
||||
args = ('model', 'ir.default', method, model_name, field, clause,
|
||||
value, user, rpc.CONTEXT)
|
||||
try:
|
||||
rpc.execute(*args)
|
||||
@@ -72,14 +71,12 @@ def field_pref_set(field, name, model, value, client_value, dependance,
|
||||
|
||||
class WidgetInterface(object):
|
||||
|
||||
def __init__(self, window, parent=None, model=None, attrs=None):
|
||||
if attrs is None:
|
||||
attrs = {}
|
||||
self.parent = parent
|
||||
self.model = model
|
||||
self._window = window
|
||||
self._view = None
|
||||
self.attrs = attrs
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
self.field_name = field_name
|
||||
self.model_name = model_name
|
||||
self.window = window
|
||||
self.view = None # Filled by ViewForm
|
||||
self.attrs = attrs or {}
|
||||
for key, val in _ATTRS_BOOLEAN.iteritems():
|
||||
self.attrs[key] = attrs.get(key, False) not in ('False', '0', False)
|
||||
self.default_readonly = self.attrs.get('readonly', False)
|
||||
@@ -96,41 +93,51 @@ class WidgetInterface(object):
|
||||
self.colors = {}
|
||||
self.visible = True
|
||||
|
||||
def __get_record(self):
|
||||
return self.view.screen.current_record
|
||||
|
||||
record = property(__get_record)
|
||||
|
||||
def __get_field(self):
|
||||
if self.record:
|
||||
return self.record.group.fields[self.field_name]
|
||||
|
||||
field = property(__get_field)
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
def _menu_sig_default_get(self):
|
||||
if self._view.modelfield.get_state_attrs(self._view.model)\
|
||||
.get('readonly', False):
|
||||
if self.field.get_state_attrs(self.record).get('readonly', False):
|
||||
return False
|
||||
model = self._view.modelfield.parent.resource
|
||||
args = ('model', model, 'default_get', [self.attrs['name']])
|
||||
model_name = self.field.parent.model_name
|
||||
args = ('model', model_name, 'default_get', [self.attrs['name']])
|
||||
try:
|
||||
res = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
process_exception(exception, self._window, *args)
|
||||
self._view.modelfield.set_default(self._view.model,
|
||||
process_exception(exception, self.window, *args)
|
||||
self.field.set_default(self.record,
|
||||
res.get(self.attrs['name'], False), modified=True)
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
self.display(self.record, self.field)
|
||||
|
||||
def _menu_sig_default_set(self, reset=False):
|
||||
deps = []
|
||||
for wname, wviews in self._view.view_form.widgets.iteritems():
|
||||
for wname, wviews in self.view.widgets.iteritems():
|
||||
for wview in wviews:
|
||||
if wview.modelfield.attrs.get('change_default', False):
|
||||
wvalue = wview.modelfield.get(self._view.model)
|
||||
wvalue = wview.modelfield.get(self.record)
|
||||
name = wview.modelfield.attrs.get('string', wname)
|
||||
value = wview.modelfield.get_client(self._view.model)
|
||||
value = wview.modelfield.get_client(self.record)
|
||||
deps.append((wname, name, wvalue, value))
|
||||
if not self._view.modelfield.validate(self._view.model):
|
||||
message(_('Invalid field!'), parent=self._window)
|
||||
if not self.field.validate(self.record):
|
||||
message(_('Invalid field!'), parent=self.window)
|
||||
return
|
||||
value = self._view.modelfield.get_default(self._view.model)
|
||||
value = self.field.get_default(self.record)
|
||||
client_value = self.display_value()
|
||||
model = self._view.modelfield.parent.resource
|
||||
field_pref_set(self._view.widget_name,
|
||||
self.attrs.get('string', self._view.widget_name), model,
|
||||
value, client_value, deps, self._window, reset=reset)
|
||||
model_name = self.field.parent.model_name
|
||||
field_pref_set(self.field_name,
|
||||
self.attrs.get('string', self.field_name), model_name,
|
||||
value, client_value, deps, self.window, reset=reset)
|
||||
|
||||
def sig_activate(self, widget=None):
|
||||
# emulate a focus_out so that the onchange is called if needed
|
||||
@@ -205,7 +212,7 @@ class WidgetInterface(object):
|
||||
widget.show()
|
||||
|
||||
def display_value(self):
|
||||
return self._view.modelfield.get_client(self._view.model)
|
||||
return self.field.get_client(self.record)
|
||||
|
||||
def _menu_open(self, obj, event):
|
||||
if event.button == 3:
|
||||
@@ -243,30 +250,30 @@ class WidgetInterface(object):
|
||||
pass
|
||||
|
||||
def _focus_out(self):
|
||||
if not self._view.modelfield:
|
||||
if not self.field:
|
||||
return False
|
||||
if not self.visible:
|
||||
return False
|
||||
self.set_value(self._view.model, self._view.modelfield)
|
||||
self.set_value(self.record, self.field)
|
||||
|
||||
def display(self, model, modelfield):
|
||||
if not modelfield:
|
||||
def display(self, record, field):
|
||||
if not field:
|
||||
self._readonly_set(self.attrs.get('readonly', False))
|
||||
return
|
||||
self._readonly_set(modelfield.get_state_attrs(model).\
|
||||
self._readonly_set(field.get_state_attrs(record).\
|
||||
get('readonly', False))
|
||||
if modelfield.get_state_attrs(model).get('readonly', False):
|
||||
if field.get_state_attrs(record).get('readonly', False):
|
||||
self.color_set('readonly')
|
||||
elif not modelfield.get_state_attrs(model).get('valid', True):
|
||||
elif not field.get_state_attrs(record).get('valid', True):
|
||||
self.color_set('invalid')
|
||||
elif modelfield.get_state_attrs(model).get('required', False):
|
||||
elif field.get_state_attrs(record).get('required', False):
|
||||
self.color_set('required')
|
||||
else:
|
||||
self.color_set('normal')
|
||||
self.invisible_set(modelfield.get_state_attrs(model).\
|
||||
self.invisible_set(field.get_state_attrs(record).\
|
||||
get('invisible', False))
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
def set_value(self, record, field):
|
||||
pass
|
||||
|
||||
def cancel(self):
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
import gtk
|
||||
from tryton.gui.window.view_form.screen import Screen
|
||||
from interface import WidgetInterface
|
||||
from one2many import Dialog
|
||||
import tryton.rpc as rpc
|
||||
from tryton.gui.window.win_search import WinSearch
|
||||
from tryton.gui.window.win_form import WinForm
|
||||
from tryton.gui.window.view_form.widget_search.form import _LIMIT
|
||||
import tryton.common as common
|
||||
import gettext
|
||||
@@ -15,8 +15,9 @@ _ = gettext.gettext
|
||||
|
||||
class Many2Many(WidgetInterface):
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
super(Many2Many, self).__init__(window, parent, model, attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(Many2Many, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
|
||||
self.widget = gtk.VBox(homogeneous=False, spacing=5)
|
||||
|
||||
@@ -59,7 +60,7 @@ class Many2Many(WidgetInterface):
|
||||
|
||||
hbox.set_focus_chain([self.wid_text])
|
||||
|
||||
self.screen = Screen(attrs['relation'], self._window,
|
||||
self.screen = Screen(attrs['relation'], self.window,
|
||||
view_type=['tree'], views_preload=attrs.get('views', {}),
|
||||
row_activate=self._on_activate)
|
||||
|
||||
@@ -89,8 +90,8 @@ class Many2Many(WidgetInterface):
|
||||
del self.widget
|
||||
|
||||
def _sig_add(self, *args):
|
||||
domain = self._view.modelfield.domain_get(self._view.model)
|
||||
context = self._view.modelfield.context_get(self._view.model)
|
||||
domain = self.field.domain_get(self.record)
|
||||
context = self.field.context_get(self.record)
|
||||
value = self.wid_text.get_text()
|
||||
|
||||
try:
|
||||
@@ -101,11 +102,11 @@ class Many2Many(WidgetInterface):
|
||||
ids = rpc.execute('model', self.attrs['relation'], 'search',
|
||||
dom , 0, _LIMIT, None, context)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self._window)
|
||||
common.process_exception(exception, self.window)
|
||||
return False
|
||||
if len(ids) != 1 or not value:
|
||||
win = WinSearch(self.attrs['relation'], sel_multi=True, ids=ids,
|
||||
context=context, domain=domain, parent=self._window,
|
||||
context=context, domain=domain, parent=self.window,
|
||||
views_preload=self.attrs.get('views', {}))
|
||||
ids = win.run()
|
||||
|
||||
@@ -129,22 +130,11 @@ class Many2Many(WidgetInterface):
|
||||
self._sig_edit()
|
||||
|
||||
def _sig_edit(self):
|
||||
if self.screen.current_model:
|
||||
readonly = False
|
||||
domain = []
|
||||
if self._view.modelfield and self._view.model:
|
||||
modelfield = self._view.modelfield
|
||||
model = self._view.model
|
||||
readonly = modelfield.get_state_attrs(model
|
||||
).get('readonly', False)
|
||||
domain = modelfield.domain_get(self._view.model)
|
||||
dia = Dialog(self.attrs['relation'], parent=self._view.model,
|
||||
model=self.screen.current_model, attrs=self.attrs,
|
||||
window=self._window, readonly=readonly, domain=domain)
|
||||
res, record = dia.run()
|
||||
if res:
|
||||
record.save()
|
||||
dia.destroy()
|
||||
if self.screen.current_record:
|
||||
win = WinForm(self.screen, self.window)
|
||||
if win.run():
|
||||
self.screen.current_record.save()
|
||||
win.destroy()
|
||||
|
||||
def _readonly_set(self, value):
|
||||
super(Many2Many, self)._readonly_set(value)
|
||||
@@ -153,20 +143,20 @@ class Many2Many(WidgetInterface):
|
||||
self.wid_but_remove.set_sensitive(not value)
|
||||
self.wid_but_add.set_sensitive(not value)
|
||||
|
||||
def display(self, model, model_field):
|
||||
if not model_field:
|
||||
self.screen.current_model = None
|
||||
def display(self, record, field):
|
||||
if field is None:
|
||||
self.screen.current_record = None
|
||||
self.screen.display()
|
||||
return False
|
||||
super(Many2Many, self).display(model, model_field)
|
||||
new_models = model_field.get_client(model)
|
||||
if self.screen.models != new_models:
|
||||
self.screen.models_set(new_models)
|
||||
super(Many2Many, self).display(record, field)
|
||||
new_group = field.get_client(record)
|
||||
if id(self.screen.group) != id(new_group):
|
||||
self.screen.group = new_group
|
||||
self.screen.display()
|
||||
return True
|
||||
|
||||
def display_value(self):
|
||||
ids = self._view.modelfield.get_default(self._view.model)
|
||||
ids = self.field.get_default(self.record)
|
||||
try:
|
||||
result = rpc.execute('model', self.attrs['relation'], 'read',
|
||||
ids, ['rec_name'], rpc.CONTEXT)
|
||||
@@ -174,6 +164,6 @@ class Many2Many(WidgetInterface):
|
||||
return str(ids)
|
||||
return ', '.join(x['rec_name'] for x in result)
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
def set_value(self, record, field):
|
||||
self.screen.current_view.set_value()
|
||||
return True
|
||||
@@ -8,7 +8,7 @@ from tryton.common import TRYTON_ICON, COLOR_SCHEMES
|
||||
import tryton.common as common
|
||||
from tryton.gui.window.view_form.screen import Screen
|
||||
from tryton.gui.window.win_search import WinSearch
|
||||
from tryton.rpc import RPCProxy
|
||||
from tryton.gui.window.win_form import WinForm
|
||||
import tryton.rpc as rpc
|
||||
from tryton.action import Action
|
||||
from tryton.gui.window.view_form.widget_search.form import _LIMIT
|
||||
@@ -18,151 +18,11 @@ import pango
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
class Dialog(object):
|
||||
|
||||
def __init__(self, model, obj_id=None, attrs=None, domain=None,
|
||||
context=None, window=None):
|
||||
if attrs is None:
|
||||
attrs = {}
|
||||
|
||||
self.dia = gtk.Dialog(_('Link'), window,
|
||||
gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT)
|
||||
self.window = window
|
||||
if ('string' in attrs) and attrs['string']:
|
||||
self.dia.set_title(attrs['string'])
|
||||
self.dia.set_property('default-width', 760)
|
||||
self.dia.set_property('default-height', 500)
|
||||
self.dia.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
self.dia.set_icon(TRYTON_ICON)
|
||||
self.dia.set_has_separator(False)
|
||||
|
||||
self.accel_group = gtk.AccelGroup()
|
||||
self.dia.add_accel_group(self.accel_group)
|
||||
|
||||
icon_cancel = gtk.STOCK_CLOSE
|
||||
if not obj_id:
|
||||
icon_cancel = gtk.STOCK_CANCEL
|
||||
self.but_cancel = self.dia.add_button(icon_cancel,
|
||||
gtk.RESPONSE_CANCEL)
|
||||
|
||||
self.but_ok = self.dia.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
self.but_ok.add_accelerator('clicked', self.accel_group,
|
||||
gtk.keysyms.Return, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE)
|
||||
|
||||
self.dia.set_default_response(gtk.RESPONSE_OK)
|
||||
self.dia.show()
|
||||
|
||||
self.screen = Screen(model, self.dia, domain=domain, context=context,
|
||||
view_type=['form'], views_preload=attrs.get('views', {}))
|
||||
if obj_id:
|
||||
self.screen.load([obj_id])
|
||||
else:
|
||||
self.screen.new()
|
||||
name = attrs.get('string', '')
|
||||
if name:
|
||||
name += ' - '
|
||||
name += self.screen.current_view.title
|
||||
self.dia.set_title(name)
|
||||
|
||||
title = gtk.Label()
|
||||
title.set_use_markup(True)
|
||||
title.modify_font(pango.FontDescription("12"))
|
||||
title.set_label('<b>' + name + '</b>')
|
||||
title.set_padding(20, 3)
|
||||
title.set_alignment(0.0, 0.5)
|
||||
title.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000"))
|
||||
title.show()
|
||||
|
||||
self.info_label = gtk.Label()
|
||||
self.info_label.set_padding(3, 3)
|
||||
self.info_label.set_alignment(1.0, 0.5)
|
||||
|
||||
self.eb_info = gtk.EventBox()
|
||||
self.eb_info.add(self.info_label)
|
||||
self.eb_info.connect('button-release-event',
|
||||
lambda *a: self.message_info(''))
|
||||
|
||||
vbox = gtk.VBox()
|
||||
vbox.pack_start(self.eb_info, expand=True, fill=True, padding=5)
|
||||
vbox.show()
|
||||
|
||||
hbox = gtk.HBox()
|
||||
hbox.pack_start(title, expand=True, fill=True)
|
||||
hbox.pack_start(vbox, expand=False, fill=True, padding=20)
|
||||
hbox.show()
|
||||
|
||||
frame = gtk.Frame()
|
||||
frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
|
||||
frame.add(hbox)
|
||||
frame.show()
|
||||
|
||||
eb = gtk.EventBox()
|
||||
eb.add(frame)
|
||||
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#ffffff"))
|
||||
eb.show()
|
||||
|
||||
self.dia.vbox.pack_start(eb, expand=False, fill=True, padding=3)
|
||||
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
scroll.set_placement(gtk.CORNER_TOP_LEFT)
|
||||
scroll.set_shadow_type(gtk.SHADOW_NONE)
|
||||
scroll.show()
|
||||
self.dia.vbox.pack_start(scroll, expand=True, fill=True)
|
||||
|
||||
viewport = gtk.Viewport()
|
||||
viewport.set_shadow_type(gtk.SHADOW_NONE)
|
||||
viewport.show()
|
||||
scroll.add(viewport)
|
||||
|
||||
self.screen.widget.show()
|
||||
viewport.add(self.screen.widget)
|
||||
|
||||
i, j = self.screen.screen_container.size_get()
|
||||
viewport.set_size_request(i, j + 30)
|
||||
self.dia.show()
|
||||
self.screen.current_view.set_cursor()
|
||||
self.screen.display()
|
||||
|
||||
def message_info(self, message, color='red'):
|
||||
if message:
|
||||
self.info_label.set_label(message)
|
||||
self.eb_info.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(
|
||||
COLOR_SCHEMES.get(color, 'white')))
|
||||
self.eb_info.show_all()
|
||||
else:
|
||||
self.info_label.set_label('')
|
||||
self.eb_info.hide()
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
res = self.dia.run()
|
||||
if res == gtk.RESPONSE_OK:
|
||||
obj_id = None
|
||||
try:
|
||||
obj_id = self.screen.save_current()
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.dia)
|
||||
if obj_id:
|
||||
return (True, (self.screen.current_model.id,
|
||||
self.screen.current_model.rec_name()))
|
||||
else:
|
||||
self.screen.display()
|
||||
else:
|
||||
break
|
||||
return (False, False)
|
||||
|
||||
def destroy(self):
|
||||
self.window.present()
|
||||
self.screen.destroy()
|
||||
self.dia.destroy()
|
||||
|
||||
class Many2One(WidgetInterface):
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
if attrs is None:
|
||||
attrs = {}
|
||||
WidgetInterface.__init__(self, window, parent, model, attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(Many2One, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
|
||||
self.widget = gtk.HBox(spacing=0)
|
||||
self.widget.set_property('sensitive', True)
|
||||
@@ -208,7 +68,6 @@ class Many2One(WidgetInterface):
|
||||
self.tooltips.enable()
|
||||
|
||||
self._readonly = False
|
||||
self.model_type = attrs['relation']
|
||||
|
||||
self.completion = gtk.EntryCompletion()
|
||||
self.liststore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
|
||||
@@ -219,7 +78,7 @@ class Many2One(WidgetInterface):
|
||||
['rec_name'])
|
||||
names = [(x['id'], x['rec_name']) for x in result]
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self._window)
|
||||
common.process_exception(exception, self.window)
|
||||
names = []
|
||||
if names:
|
||||
self.load_completion(names)
|
||||
@@ -227,12 +86,6 @@ class Many2One(WidgetInterface):
|
||||
def grab_focus(self):
|
||||
return self.wid_text.grab_focus()
|
||||
|
||||
def _focus_out(self):
|
||||
return WidgetInterface._focus_out(self)
|
||||
|
||||
def _focus_in(self):
|
||||
return WidgetInterface._focus_in(self)
|
||||
|
||||
def load_completion(self, names):
|
||||
self.completion.set_match_func(self.match_func, None)
|
||||
self.completion.connect("match-selected", self.on_completion_match)
|
||||
@@ -248,8 +101,8 @@ class Many2One(WidgetInterface):
|
||||
return modelstr.startswith(key_string)
|
||||
|
||||
def on_completion_match(self, completion, model, iter):
|
||||
self._view.modelfield.set_client(self._view.model, int(model[iter][0]))
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
self.field.set_client(self.record, int(model[iter][0]))
|
||||
self.display(self.record, self.field)
|
||||
return True
|
||||
|
||||
def _readonly_set(self, value):
|
||||
@@ -267,19 +120,19 @@ class Many2One(WidgetInterface):
|
||||
def sig_activate(self, widget, event=None, key_press=False):
|
||||
if not self.focus_out:
|
||||
return
|
||||
if not self._view.modelfield:
|
||||
if not self.field:
|
||||
return
|
||||
self.changed = False
|
||||
value = self._view.modelfield.get(self._view.model)
|
||||
value = self.field.get(self.record)
|
||||
|
||||
self.focus_out = False
|
||||
if not value:
|
||||
if not self._readonly and (self.wid_text.get_text() or \
|
||||
(self._view.modelfield.get_state_attrs(
|
||||
self._view.model)['required']) and key_press):
|
||||
domain = self._view.modelfield.domain_get(self._view.model)
|
||||
(self.field.get_state_attrs(
|
||||
self.record)['required']) and key_press):
|
||||
domain = self.field.domain_get(self.record)
|
||||
context = rpc.CONTEXT.copy()
|
||||
context.update(self._view.modelfield.context_get(self._view.model))
|
||||
context.update(self.field.context_get(self.record))
|
||||
self.wid_text.grab_focus()
|
||||
|
||||
try:
|
||||
@@ -293,70 +146,80 @@ class Many2One(WidgetInterface):
|
||||
'search', dom, 0, _LIMIT, None, context)
|
||||
except Exception, exception:
|
||||
self.focus_out = True
|
||||
common.process_exception(exception, self._window)
|
||||
common.process_exception(exception, self.window)
|
||||
self.changed = True
|
||||
return False
|
||||
if len(ids)==1:
|
||||
self._view.modelfield.set_client(self._view.model, ids[0],
|
||||
self.field.set_client(self.record, ids[0],
|
||||
force_change=True)
|
||||
self.focus_out = True
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
self.display(self.record, self.field)
|
||||
return True
|
||||
|
||||
win = WinSearch(self.attrs['relation'], sel_multi=False,
|
||||
ids=ids, context=context, domain=domain,
|
||||
parent=self._window,
|
||||
parent=self.window,
|
||||
views_preload=self.attrs.get('views', {}))
|
||||
ids = win.run()
|
||||
if ids:
|
||||
self._view.modelfield.set_client(self._view.model, ids[0],
|
||||
self.field.set_client(self.record, ids[0],
|
||||
force_change=True)
|
||||
self.focus_out = True
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
self.display(self.record, self.field)
|
||||
return True
|
||||
else:
|
||||
self.focus_out = True
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
self.display(self.record, self.field)
|
||||
return False
|
||||
self.focus_out = True
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
self.display(self.record, self.field)
|
||||
self.changed = True
|
||||
return True
|
||||
|
||||
def get_screen(self):
|
||||
domain = self.field.domain_get(self.record)
|
||||
context = self.field.context_get(self.record)
|
||||
return Screen(self.attrs['relation'], self.window, domain=domain,
|
||||
context=context, view_type=['form'],
|
||||
views_preload=self.attrs.get('views', {}))
|
||||
|
||||
def sig_new(self, *args):
|
||||
self.focus_out = False
|
||||
domain = self._view.modelfield.domain_get(self._view.model)
|
||||
context = self._view.modelfield.context_get(self._view.model)
|
||||
dia = Dialog(self.attrs['relation'], attrs=self.attrs,
|
||||
window=self._window, domain=domain, context=context)
|
||||
res, value = dia.run()
|
||||
if res:
|
||||
self._view.modelfield.set_client(self._view.model, value)
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
dia.destroy()
|
||||
screen = self.get_screen()
|
||||
win = WinForm(screen, self.window, new=True)
|
||||
while win.run():
|
||||
if screen.save_current():
|
||||
value = (screen.current_record.id,
|
||||
screen.current_record.rec_name())
|
||||
self.field.set_client(self.record, value)
|
||||
break
|
||||
else:
|
||||
screen.display()
|
||||
win.destroy()
|
||||
self.focus_out = True
|
||||
|
||||
def sig_edit(self, widget):
|
||||
self.changed = False
|
||||
value = self._view.modelfield.get(self._view.model)
|
||||
value = self.field.get(self.record)
|
||||
self.focus_out = False
|
||||
if value:
|
||||
domain = self._view.modelfield.domain_get(self._view.model)
|
||||
context = self._view.modelfield.context_get(self._view.model)
|
||||
dia = Dialog(self.attrs['relation'],
|
||||
self._view.modelfield.get(self._view.model),
|
||||
attrs=self.attrs, window=self._window, domain=domain,
|
||||
context=context)
|
||||
res, value = dia.run()
|
||||
if res:
|
||||
self._view.modelfield.set_client(self._view.model, value,
|
||||
force_change=True)
|
||||
dia.destroy()
|
||||
screen = self.get_screen()
|
||||
screen.load([self.field.get(self.record)])
|
||||
win = WinForm(screen, self.window)
|
||||
while win.run():
|
||||
if screen.save_current():
|
||||
value = (screen.current_record.id,
|
||||
screen.current_record.rec_name())
|
||||
self.field.set_client(self.record, value, force_change=True)
|
||||
break
|
||||
else:
|
||||
screen.display()
|
||||
win.destroy()
|
||||
else:
|
||||
if not self._readonly:
|
||||
domain = self._view.modelfield.domain_get(self._view.model)
|
||||
domain = self.field.domain_get(self.record)
|
||||
context = rpc.CONTEXT.copy()
|
||||
context.update(self._view.modelfield.context_get(self._view.model))
|
||||
context.update(self.field.context_get(self.record))
|
||||
self.wid_text.grab_focus()
|
||||
|
||||
try:
|
||||
@@ -370,26 +233,26 @@ class Many2One(WidgetInterface):
|
||||
'search', dom, 0, _LIMIT, None, context)
|
||||
except Exception, exception:
|
||||
self.focus_out = True
|
||||
common.process_exception(exception, self._window)
|
||||
common.process_exception(exception, self.window)
|
||||
self.changed = True
|
||||
return False
|
||||
if ids and len(ids)==1:
|
||||
self._view.modelfield.set_client(self._view.model, ids[0],
|
||||
self.field.set_client(self.record, ids[0],
|
||||
force_change=True)
|
||||
self.focus_out = True
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
self.display(self.record, self.field)
|
||||
return True
|
||||
|
||||
win = WinSearch(self.attrs['relation'], sel_multi=False,
|
||||
ids=ids, context=context,
|
||||
domain=domain, parent=self._window,
|
||||
domain=domain, parent=self.window,
|
||||
views_preload=self.attrs.get('views', {}))
|
||||
ids = win.run()
|
||||
if ids:
|
||||
self._view.modelfield.set_client(self._view.model, ids[0],
|
||||
self.field.set_client(self.record, ids[0],
|
||||
force_change=True)
|
||||
self.focus_out = True
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
self.display(self.record, self.field)
|
||||
self.changed = True
|
||||
|
||||
def sig_key_press(self, widget, event, *args):
|
||||
@@ -407,22 +270,22 @@ class Many2One(WidgetInterface):
|
||||
def sig_changed(self, *args):
|
||||
if not self.changed:
|
||||
return False
|
||||
if self._view.modelfield.get(self._view.model):
|
||||
self._view.modelfield.set_client(self._view.model, False)
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
if self.field.get(self.record):
|
||||
self.field.set_client(self.record, False)
|
||||
self.display(self.record, self.field)
|
||||
return False
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
def set_value(self, record, field):
|
||||
pass # No update of the model, the model is updated in real time !
|
||||
|
||||
def display(self, model, model_field):
|
||||
def display(self, record, field):
|
||||
self.changed = False
|
||||
if not model_field:
|
||||
if not field:
|
||||
self.wid_text.set_text('')
|
||||
self.changed = True
|
||||
return False
|
||||
WidgetInterface.display(self, model, model_field)
|
||||
res = model_field.get_client(model)
|
||||
super(Many2One, self).display(record, field)
|
||||
res = field.get_client(record)
|
||||
self.wid_text.set_text((res and str(res)) or '')
|
||||
img = gtk.Image()
|
||||
if res:
|
||||
@@ -436,10 +299,15 @@ class Many2One(WidgetInterface):
|
||||
self.changed = True
|
||||
|
||||
def _populate_popup(self, widget, menu):
|
||||
value = self._view.modelfield.get(self._view.model)
|
||||
ir_action_keyword = RPCProxy('ir.action.keyword')
|
||||
relates = ir_action_keyword.get_keyword('form_relate',
|
||||
(self.model_type, 0), rpc.CONTEXT)
|
||||
value = self.field.get(self.record)
|
||||
args = ('model', 'ir.action.keyword', 'get_keyword',
|
||||
'form_relate', (self.attrs['relation'], 0), rpc.CONTEXT)
|
||||
try:
|
||||
relates = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
relates = common.process_exception(exception, self.window)
|
||||
if not relates:
|
||||
return False
|
||||
menu_entries = []
|
||||
menu_entries.append((None, None, None))
|
||||
menu_entries += self._menu_entries
|
||||
@@ -471,27 +339,27 @@ class Many2One(WidgetInterface):
|
||||
data = {}
|
||||
context = {}
|
||||
act = action.copy()
|
||||
obj_id = self._view.modelfield.get(self._view.model)
|
||||
obj_id = self.field.get(self.record)
|
||||
if not obj_id:
|
||||
common.message(_('You must select a record to use the relation!'),
|
||||
self._window)
|
||||
self.window)
|
||||
return False
|
||||
screen = Screen(self.attrs['relation'], self._window)
|
||||
screen = Screen(self.attrs['relation'], self.window)
|
||||
screen.load([obj_id])
|
||||
encoder = PYSONEncoder()
|
||||
act['domain'] = encoder.encode(screen.current_model.expr_eval(
|
||||
act['domain'] = encoder.encode(screen.current_record.expr_eval(
|
||||
act.get('domain', []), check_load=False))
|
||||
act['context'] = encoder.encode(screen.current_model.expr_eval(
|
||||
act['context'] = encoder.encode(screen.current_record.expr_eval(
|
||||
act.get('context', {}), check_load=False))
|
||||
data['model'] = self.model_type
|
||||
data['model'] = self.attrs['relation']
|
||||
data['id'] = obj_id
|
||||
data['ids'] = [obj_id]
|
||||
return Action._exec_action(act, self._window, data, context)
|
||||
return Action._exec_action(act, self.window, data, context)
|
||||
|
||||
def click_and_action(self, atype):
|
||||
obj_id = self._view.modelfield.get(self._view.model)
|
||||
return Action.exec_keyword(atype, self._window, {
|
||||
'model': self.model_type,
|
||||
obj_id = self.field.get(self.record)
|
||||
return Action.exec_keyword(atype, self.window, {
|
||||
'model': self.attrs['relation'],
|
||||
'id': obj_id or False,
|
||||
'ids': [obj_id],
|
||||
}, alwaysask=True)
|
||||
@@ -5,8 +5,9 @@ import gettext
|
||||
from tryton.common import TRYTON_ICON, COLOR_SCHEMES
|
||||
from interface import WidgetInterface
|
||||
from tryton.gui.window.view_form.screen import Screen
|
||||
from tryton.gui.window.view_form.model.group import ModelRecordGroup
|
||||
from tryton.gui.window.view_form.model.group import Group
|
||||
from tryton.gui.window.win_search import WinSearch
|
||||
from tryton.gui.window.win_form import WinForm
|
||||
from tryton.gui.window.view_form.widget_search.form import _LIMIT
|
||||
import tryton.common as common
|
||||
import tryton.rpc as rpc
|
||||
@@ -14,462 +15,153 @@ import pango
|
||||
|
||||
_ = gettext.gettext
|
||||
|
||||
def _create_menu(self, attrs):
|
||||
hbox = gtk.HBox(homogeneous=False, spacing=0)
|
||||
menubar = gtk.MenuBar()
|
||||
if hasattr(menubar, 'set_pack_direction') and \
|
||||
hasattr(menubar, 'set_child_pack_direction'):
|
||||
menubar.set_pack_direction(gtk.PACK_DIRECTION_LTR)
|
||||
menubar.set_child_pack_direction(gtk.PACK_DIRECTION_LTR)
|
||||
|
||||
menuitem_title = gtk.ImageMenuItem(stock_id='tryton-preferences')
|
||||
|
||||
menu_title = gtk.Menu()
|
||||
menuitem_set_to_default = gtk.MenuItem(_('Set to default value'), True)
|
||||
menuitem_set_to_default.connect('activate',
|
||||
lambda *x: self._menu_sig_default_get())
|
||||
menu_title.add(menuitem_set_to_default)
|
||||
menuitem_set_default = gtk.MenuItem(_('Set as default'), True)
|
||||
menuitem_set_default.connect('activate',
|
||||
lambda *x: self._menu_sig_default_set())
|
||||
menu_title.add(menuitem_set_default)
|
||||
menuitem_reset_default = gtk.MenuItem(_('Reset default'), True)
|
||||
menuitem_reset_default.connect('activate',
|
||||
lambda *x: self._menu_sig_default_set(reset=True))
|
||||
menu_title.add(menuitem_reset_default)
|
||||
menuitem_title.set_submenu(menu_title)
|
||||
|
||||
menubar.add(menuitem_title)
|
||||
hbox.pack_start(menubar, expand=True, fill=True)
|
||||
|
||||
tooltips = common.Tooltips()
|
||||
|
||||
if attrs.get('add_remove'):
|
||||
|
||||
self.wid_text = gtk.Entry()
|
||||
self.wid_text.set_property('width_chars', 13)
|
||||
self.wid_text.connect('activate', self._sig_activate)
|
||||
hbox.pack_start(self.wid_text, expand=True, fill=True)
|
||||
|
||||
self.but_add = gtk.Button()
|
||||
tooltips.set_tip(self.but_add, _('Add'))
|
||||
self.but_add.connect('clicked', self._sig_add)
|
||||
img_add = gtk.Image()
|
||||
img_add.set_from_stock('tryton-list-add', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_add.set_alignment(0.5, 0.5)
|
||||
self.but_add.add(img_add)
|
||||
self.but_add.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(self.but_add, expand=False, fill=False)
|
||||
|
||||
self.but_remove = gtk.Button()
|
||||
tooltips.set_tip(self.but_remove, _('Remove'))
|
||||
self.but_remove.connect('clicked', self._sig_remove, True)
|
||||
img_remove = gtk.Image()
|
||||
img_remove.set_from_stock('tryton-list-remove', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_remove.set_alignment(0.5, 0.5)
|
||||
self.but_remove.add(img_remove)
|
||||
self.but_remove.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(self.but_remove, expand=False, fill=False)
|
||||
|
||||
hbox.pack_start(gtk.VSeparator(), expand=False, fill=True)
|
||||
|
||||
self.but_new = gtk.Button()
|
||||
tooltips.set_tip(self.but_new, _('Create a new record'))
|
||||
self.but_new.connect('clicked', self._sig_new)
|
||||
img_new = gtk.Image()
|
||||
img_new.set_from_stock('tryton-new', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_new.set_alignment(0.5, 0.5)
|
||||
self.but_new.add(img_new)
|
||||
self.but_new.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(self.but_new, expand=False, fill=False)
|
||||
|
||||
self.but_open = gtk.Button()
|
||||
tooltips.set_tip(self.but_open, _('Edit selected record'))
|
||||
self.but_open.connect('clicked', self._sig_edit)
|
||||
img_open = gtk.Image()
|
||||
img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_open.set_alignment(0.5, 0.5)
|
||||
self.but_open.add(img_open)
|
||||
self.but_open.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(self.but_open, expand=False, fill=False)
|
||||
|
||||
self.but_del = gtk.Button()
|
||||
tooltips.set_tip(self.but_del, _('Delete selected record'))
|
||||
self.but_del.connect('clicked', self._sig_remove)
|
||||
img_del = gtk.Image()
|
||||
img_del.set_from_stock('tryton-delete', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_del.set_alignment(0.5, 0.5)
|
||||
self.but_del.add(img_del)
|
||||
self.but_del.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(self.but_del, expand=False, fill=False)
|
||||
|
||||
hbox.pack_start(gtk.VSeparator(), expand=False, fill=True)
|
||||
|
||||
but_pre = gtk.Button()
|
||||
tooltips.set_tip(but_pre, _('Previous'))
|
||||
but_pre.connect('clicked', self._sig_previous)
|
||||
img_pre = gtk.Image()
|
||||
img_pre.set_from_stock('tryton-go-previous', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_pre.set_alignment(0.5, 0.5)
|
||||
but_pre.add(img_pre)
|
||||
but_pre.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(but_pre, expand=False, fill=False)
|
||||
|
||||
self.label = gtk.Label('(0,0)')
|
||||
hbox.pack_start(self.label, expand=False, fill=False)
|
||||
|
||||
but_next = gtk.Button()
|
||||
tooltips.set_tip(but_next, _('Next'))
|
||||
but_next.connect('clicked', self._sig_next)
|
||||
img_next = gtk.Image()
|
||||
img_next.set_from_stock('tryton-go-next', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_next.set_alignment(0.5, 0.5)
|
||||
but_next.add(img_next)
|
||||
but_next.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(but_next, expand=False, fill=False)
|
||||
|
||||
hbox.pack_start(gtk.VSeparator(), expand=False, fill=True)
|
||||
|
||||
but_switch = gtk.Button()
|
||||
tooltips.set_tip(but_switch, _('Switch'))
|
||||
but_switch.connect('clicked', self.switch_view)
|
||||
img_switch = gtk.Image()
|
||||
img_switch.set_from_stock('tryton-fullscreen', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_switch.set_alignment(0.5, 0.5)
|
||||
but_switch.add(img_switch)
|
||||
but_switch.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(but_switch, expand=False, fill=False)
|
||||
|
||||
if attrs.get('add_remove'):
|
||||
hbox.set_focus_chain([self.wid_text])
|
||||
else:
|
||||
hbox.set_focus_chain([])
|
||||
|
||||
tooltips.enable()
|
||||
|
||||
return hbox, menuitem_title
|
||||
|
||||
|
||||
class Dialog(object):
|
||||
|
||||
def __init__(self, model_name, parent, model=None, attrs=None,
|
||||
model_ctx=None, window=None, default_get_ctx=None, readonly=False,
|
||||
domain=None):
|
||||
|
||||
if attrs is None:
|
||||
attrs = {}
|
||||
if model_ctx is None:
|
||||
model_ctx = {}
|
||||
if default_get_ctx is None:
|
||||
default_get_ctx = {}
|
||||
|
||||
self.attrs = attrs
|
||||
self.model_name = model_name
|
||||
self.parent=parent
|
||||
self.model_ctx = model_ctx
|
||||
self.default_get_ctx = default_get_ctx
|
||||
|
||||
self.dia = gtk.Dialog(_('Link'), window,
|
||||
gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT)
|
||||
self.dia.connect('close', self._sig_close)
|
||||
self.window = window
|
||||
self.dia.set_property('default-width', 760)
|
||||
self.dia.set_property('default-height', 500)
|
||||
self.dia.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
self.dia.set_icon(TRYTON_ICON)
|
||||
self.dia.set_has_separator(False)
|
||||
|
||||
self.accel_group = gtk.AccelGroup()
|
||||
self.dia.add_accel_group(self.accel_group)
|
||||
|
||||
self.but_cancel = None
|
||||
if not model:
|
||||
icon_cancel = gtk.STOCK_CANCEL
|
||||
self.but_cancel = self.dia.add_button(icon_cancel,
|
||||
gtk.RESPONSE_CANCEL)
|
||||
|
||||
self.but_ok = self.dia.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
self.but_ok.add_accelerator('clicked', self.accel_group,
|
||||
gtk.keysyms.Return, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE)
|
||||
|
||||
self.dia.set_default_response(gtk.RESPONSE_OK)
|
||||
|
||||
self.default_get_ctx = default_get_ctx
|
||||
|
||||
menuitem_title = None
|
||||
if isinstance(model, ModelRecordGroup):
|
||||
hbox, menuitem_title = _create_menu(self, attrs)
|
||||
self.dia.vbox.pack_start(hbox, expand=False, fill=True)
|
||||
self.dia.show()
|
||||
|
||||
self.screen = Screen(model_name, self.dia, view_type=[], parent=parent,
|
||||
parent_name=attrs.get('relation_field', ''),
|
||||
exclude_field=attrs.get('relation_field', None), readonly=readonly,
|
||||
domain=domain)
|
||||
self.screen.models._context.update(model_ctx)
|
||||
modified = False
|
||||
if not model:
|
||||
model = self.screen.new(context=default_get_ctx)
|
||||
modified = True
|
||||
if isinstance(model, ModelRecordGroup):
|
||||
self.screen.tree_saves = False
|
||||
self.screen.add_view_id(False, 'tree', display=True,
|
||||
context=default_get_ctx)
|
||||
self.screen.add_view_id(False, 'form', display=False,
|
||||
context=default_get_ctx)
|
||||
self.screen.signal_connect(self, 'record-message', self._sig_label)
|
||||
self.screen.widget.connect('key_press_event', self.on_keypress)
|
||||
self.screen.models_set(model)
|
||||
else:
|
||||
self.screen.models.model_add(model, modified=modified)
|
||||
self.screen.current_model = model
|
||||
if ('views' in attrs) and ('form' in attrs['views']):
|
||||
arch = attrs['views']['form']['arch']
|
||||
fields = attrs['views']['form']['fields']
|
||||
if attrs.get('relation_field', False) \
|
||||
and attrs['relation_field'] in fields:
|
||||
del fields[attrs['relation_field']]
|
||||
self.screen.add_view(arch, fields, display=True,
|
||||
context=default_get_ctx)
|
||||
else:
|
||||
self.screen.add_view_id(False, 'form', display=True,
|
||||
context=default_get_ctx)
|
||||
|
||||
name = self.screen.current_view.title
|
||||
self.dia.set_title(name)
|
||||
if menuitem_title:
|
||||
menuitem_title.get_child().set_text(name)
|
||||
|
||||
title = gtk.Label()
|
||||
title.set_use_markup(True)
|
||||
title.modify_font(pango.FontDescription("12"))
|
||||
title.set_label('<b>' + name + '</b>')
|
||||
title.set_padding(20, 3)
|
||||
title.set_alignment(0.0, 0.5)
|
||||
title.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000"))
|
||||
title.show()
|
||||
|
||||
self.info_label = gtk.Label()
|
||||
self.info_label.set_padding(3, 3)
|
||||
self.info_label.set_alignment(1.0, 0.5)
|
||||
|
||||
self.eb_info = gtk.EventBox()
|
||||
self.eb_info.add(self.info_label)
|
||||
self.eb_info.connect('button-release-event',
|
||||
lambda *a: self.message_info(''))
|
||||
|
||||
vbox = gtk.VBox()
|
||||
vbox.pack_start(self.eb_info, expand=True, fill=True, padding=5)
|
||||
vbox.show()
|
||||
|
||||
hbox = gtk.HBox()
|
||||
hbox.pack_start(title, expand=True, fill=True)
|
||||
hbox.pack_start(vbox, expand=False, fill=True, padding=20)
|
||||
hbox.show()
|
||||
|
||||
frame = gtk.Frame()
|
||||
frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
|
||||
frame.add(hbox)
|
||||
frame.show()
|
||||
|
||||
eb = gtk.EventBox()
|
||||
eb.add(frame)
|
||||
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#ffffff"))
|
||||
eb.show()
|
||||
|
||||
self.dia.vbox.pack_start(eb, expand=False, fill=True, padding=3)
|
||||
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
scroll.set_placement(gtk.CORNER_TOP_LEFT)
|
||||
scroll.set_shadow_type(gtk.SHADOW_NONE)
|
||||
scroll.show()
|
||||
self.dia.vbox.pack_start(scroll, expand=True, fill=True)
|
||||
|
||||
viewport = gtk.Viewport()
|
||||
viewport.set_shadow_type(gtk.SHADOW_NONE)
|
||||
viewport.show()
|
||||
scroll.add(viewport)
|
||||
|
||||
self.screen.widget.show()
|
||||
viewport.add(self.screen.widget)
|
||||
|
||||
width, height = self.screen.screen_container.size_get()
|
||||
viewport.set_size_request(width, height + 30)
|
||||
self.screen.display()
|
||||
self.screen.current_view.set_cursor()
|
||||
|
||||
def message_info(self, message, color='red'):
|
||||
if message:
|
||||
self.info_label.set_label(message)
|
||||
self.eb_info.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(
|
||||
COLOR_SCHEMES.get(color, 'white')))
|
||||
self.eb_info.show_all()
|
||||
else:
|
||||
self.info_label.set_label('')
|
||||
self.eb_info.hide()
|
||||
|
||||
def on_keypress(self, widget, event):
|
||||
if (event.keyval == gtk.keysyms.F3) \
|
||||
and self.but_new.get_property('sensitive'):
|
||||
self._sig_new(widget)
|
||||
return False
|
||||
if event.keyval == gtk.keysyms.F2 \
|
||||
and widget == self.screen.widget:
|
||||
self._sig_edit(widget)
|
||||
return False
|
||||
if event.keyval in (gtk.keysyms.Delete, gtk.keysyms.KP_Delete) \
|
||||
and widget == self.screen.widget:
|
||||
self._sig_remove(widget)
|
||||
return False
|
||||
|
||||
def switch_view(self, widget):
|
||||
self.screen.switch_view()
|
||||
|
||||
def _sig_new(self, widget):
|
||||
if (self.screen.current_view.view_type == 'form') \
|
||||
or self.screen.editable_get():
|
||||
self.screen.new(context=self.default_get_ctx)
|
||||
self.screen.current_view.widget.set_sensitive(True)
|
||||
else:
|
||||
dia = Dialog(self.model_name, parent=self.parent,
|
||||
attrs=self.attrs, model_ctx=self.model_ctx,
|
||||
default_get_ctx=self.default_get_ctx,
|
||||
window=self.window)
|
||||
res = True
|
||||
while res:
|
||||
res, value = dia.run()
|
||||
if res:
|
||||
self.screen.models.model_add(value)
|
||||
value.signal('record-changed', value.parent)
|
||||
self.screen.display()
|
||||
dia.new()
|
||||
dia.destroy()
|
||||
|
||||
def _sig_edit(self, widget=None):
|
||||
if self.screen.current_model:
|
||||
dia = Dialog(self.model_name, parent=self.parent,
|
||||
model=self.screen.current_model, attrs=self.attrs,
|
||||
window=self.window)
|
||||
res, value = dia.run()
|
||||
dia.destroy()
|
||||
|
||||
def _sig_next(self, widget):
|
||||
self.screen.display_next()
|
||||
|
||||
def _sig_previous(self, widget):
|
||||
self.screen.display_prev()
|
||||
|
||||
def _sig_remove(self, widget, remove=False):
|
||||
self.screen.remove(remove=remove)
|
||||
|
||||
def _sig_activate(self, *args):
|
||||
self._sig_add()
|
||||
self.wid_text.grab_focus()
|
||||
|
||||
def _sig_add(self, *args):
|
||||
domain = []
|
||||
context = rpc.CONTEXT.copy()
|
||||
|
||||
try:
|
||||
if self.wid_text.get_text():
|
||||
dom = [('rec_name', 'ilike',
|
||||
'%' + self.wid_text.get_text() + '%'), domain]
|
||||
else:
|
||||
dom = domain
|
||||
ids = rpc.execute('model', self.attrs['relation'],
|
||||
'search', dom, 0, _LIMIT, None, context)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self._window)
|
||||
return False
|
||||
if len(ids) != 1:
|
||||
win = WinSearch(self.attrs['relation'], sel_multi=True, ids=ids,
|
||||
context=context, domain=domain, parent=self._window,
|
||||
views_preload=self.attrs.get('views', {}))
|
||||
ids = win.run()
|
||||
|
||||
res_id = None
|
||||
if ids:
|
||||
res_id = ids[0]
|
||||
self.screen.load(ids, modified=True)
|
||||
self.screen.display(res_id=res_id)
|
||||
if self.screen.current_view:
|
||||
self.screen.current_view.set_cursor()
|
||||
self.wid_text.set_text('')
|
||||
|
||||
def _sig_label(self, screen, signal_data):
|
||||
name = '_'
|
||||
if signal_data[0] >= 0:
|
||||
name = str(signal_data[0] + 1)
|
||||
line = '(%s/%s)' % (name, signal_data[1])
|
||||
self.label.set_text(line)
|
||||
|
||||
def _menu_sig_default_get(self):
|
||||
pass
|
||||
|
||||
def _menu_sig_default_set(self, reset=False):
|
||||
pass
|
||||
|
||||
def new(self):
|
||||
model = self.screen.new(context=self.default_get_ctx)
|
||||
self.screen.models.model_add(model)
|
||||
return True
|
||||
|
||||
def run(self):
|
||||
end = False
|
||||
while not end:
|
||||
res = self.dia.run()
|
||||
self.screen.current_view.set_value()
|
||||
end = (res != gtk.RESPONSE_OK) \
|
||||
or (not self.screen.current_model \
|
||||
or self.screen.current_model.validate())
|
||||
if not end:
|
||||
self.screen.current_view.set_cursor()
|
||||
self.screen.display()
|
||||
if self.but_cancel:
|
||||
self.but_cancel.set_label(gtk.STOCK_CLOSE)
|
||||
|
||||
if res == gtk.RESPONSE_OK:
|
||||
model = self.screen.current_model
|
||||
return (True, model)
|
||||
return (False, None)
|
||||
|
||||
def _sig_close(self, widget):
|
||||
if self.screen.current_view:
|
||||
self.screen.current_view.set_value()
|
||||
if not self.but_cancel \
|
||||
and self.screen.current_model \
|
||||
and not self.screen.current_model.validate():
|
||||
if self.screen.current_view:
|
||||
self.screen.current_view.set_cursor()
|
||||
self.screen.display()
|
||||
widget.emit_stop_by_name('close')
|
||||
|
||||
def destroy(self):
|
||||
self.screen.signal_unconnect(self)
|
||||
self.window.present()
|
||||
self.dia.destroy()
|
||||
self.screen.destroy()
|
||||
|
||||
|
||||
class One2Many(WidgetInterface):
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
super(One2Many, self).__init__(window, parent, model, attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(One2Many, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
|
||||
self.widget = gtk.VBox(homogeneous=False, spacing=5)
|
||||
|
||||
hbox, menuitem_title = _create_menu(self, attrs)
|
||||
hbox = gtk.HBox(homogeneous=False, spacing=0)
|
||||
menubar = gtk.MenuBar()
|
||||
if hasattr(menubar, 'set_pack_direction') and \
|
||||
hasattr(menubar, 'set_child_pack_direction'):
|
||||
menubar.set_pack_direction(gtk.PACK_DIRECTION_LTR)
|
||||
menubar.set_child_pack_direction(gtk.PACK_DIRECTION_LTR)
|
||||
|
||||
menuitem_title = gtk.ImageMenuItem(stock_id='tryton-preferences')
|
||||
|
||||
menu_title = gtk.Menu()
|
||||
menuitem_set_to_default = gtk.MenuItem(_('Set to default value'), True)
|
||||
menuitem_set_to_default.connect('activate',
|
||||
lambda *x: self._menu_sig_default_get())
|
||||
menu_title.add(menuitem_set_to_default)
|
||||
menuitem_set_default = gtk.MenuItem(_('Set as default'), True)
|
||||
menuitem_set_default.connect('activate',
|
||||
lambda *x: self._menu_sig_default_set())
|
||||
menu_title.add(menuitem_set_default)
|
||||
menuitem_reset_default = gtk.MenuItem(_('Reset default'), True)
|
||||
menuitem_reset_default.connect('activate',
|
||||
lambda *x: self._menu_sig_default_set(reset=True))
|
||||
menu_title.add(menuitem_reset_default)
|
||||
menuitem_title.set_submenu(menu_title)
|
||||
|
||||
menubar.add(menuitem_title)
|
||||
hbox.pack_start(menubar, expand=True, fill=True)
|
||||
|
||||
tooltips = common.Tooltips()
|
||||
|
||||
if attrs.get('add_remove'):
|
||||
|
||||
self.wid_text = gtk.Entry()
|
||||
self.wid_text.set_property('width_chars', 13)
|
||||
self.wid_text.connect('activate', self._sig_activate)
|
||||
hbox.pack_start(self.wid_text, expand=True, fill=True)
|
||||
|
||||
self.but_add = gtk.Button()
|
||||
tooltips.set_tip(self.but_add, _('Add'))
|
||||
self.but_add.connect('clicked', self._sig_add)
|
||||
img_add = gtk.Image()
|
||||
img_add.set_from_stock('tryton-list-add', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_add.set_alignment(0.5, 0.5)
|
||||
self.but_add.add(img_add)
|
||||
self.but_add.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(self.but_add, expand=False, fill=False)
|
||||
|
||||
self.but_remove = gtk.Button()
|
||||
tooltips.set_tip(self.but_remove, _('Remove'))
|
||||
self.but_remove.connect('clicked', self._sig_remove, True)
|
||||
img_remove = gtk.Image()
|
||||
img_remove.set_from_stock('tryton-list-remove', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_remove.set_alignment(0.5, 0.5)
|
||||
self.but_remove.add(img_remove)
|
||||
self.but_remove.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(self.but_remove, expand=False, fill=False)
|
||||
|
||||
hbox.pack_start(gtk.VSeparator(), expand=False, fill=True)
|
||||
|
||||
self.but_new = gtk.Button()
|
||||
tooltips.set_tip(self.but_new, _('Create a new record'))
|
||||
self.but_new.connect('clicked', self._sig_new)
|
||||
img_new = gtk.Image()
|
||||
img_new.set_from_stock('tryton-new', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_new.set_alignment(0.5, 0.5)
|
||||
self.but_new.add(img_new)
|
||||
self.but_new.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(self.but_new, expand=False, fill=False)
|
||||
|
||||
self.but_open = gtk.Button()
|
||||
tooltips.set_tip(self.but_open, _('Edit selected record'))
|
||||
self.but_open.connect('clicked', self._sig_edit)
|
||||
img_open = gtk.Image()
|
||||
img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_open.set_alignment(0.5, 0.5)
|
||||
self.but_open.add(img_open)
|
||||
self.but_open.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(self.but_open, expand=False, fill=False)
|
||||
|
||||
self.but_del = gtk.Button()
|
||||
tooltips.set_tip(self.but_del, _('Delete selected record'))
|
||||
self.but_del.connect('clicked', self._sig_remove)
|
||||
img_del = gtk.Image()
|
||||
img_del.set_from_stock('tryton-delete', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_del.set_alignment(0.5, 0.5)
|
||||
self.but_del.add(img_del)
|
||||
self.but_del.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(self.but_del, expand=False, fill=False)
|
||||
|
||||
hbox.pack_start(gtk.VSeparator(), expand=False, fill=True)
|
||||
|
||||
but_pre = gtk.Button()
|
||||
tooltips.set_tip(but_pre, _('Previous'))
|
||||
but_pre.connect('clicked', self._sig_previous)
|
||||
img_pre = gtk.Image()
|
||||
img_pre.set_from_stock('tryton-go-previous', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_pre.set_alignment(0.5, 0.5)
|
||||
but_pre.add(img_pre)
|
||||
but_pre.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(but_pre, expand=False, fill=False)
|
||||
|
||||
self.label = gtk.Label('(0,0)')
|
||||
hbox.pack_start(self.label, expand=False, fill=False)
|
||||
|
||||
but_next = gtk.Button()
|
||||
tooltips.set_tip(but_next, _('Next'))
|
||||
but_next.connect('clicked', self._sig_next)
|
||||
img_next = gtk.Image()
|
||||
img_next.set_from_stock('tryton-go-next', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_next.set_alignment(0.5, 0.5)
|
||||
but_next.add(img_next)
|
||||
but_next.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(but_next, expand=False, fill=False)
|
||||
|
||||
hbox.pack_start(gtk.VSeparator(), expand=False, fill=True)
|
||||
|
||||
but_switch = gtk.Button()
|
||||
tooltips.set_tip(but_switch, _('Switch'))
|
||||
but_switch.connect('clicked', self.switch_view)
|
||||
img_switch = gtk.Image()
|
||||
img_switch.set_from_stock('tryton-fullscreen', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_switch.set_alignment(0.5, 0.5)
|
||||
but_switch.add(img_switch)
|
||||
but_switch.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(but_switch, expand=False, fill=False)
|
||||
|
||||
if attrs.get('add_remove'):
|
||||
hbox.set_focus_chain([self.wid_text])
|
||||
else:
|
||||
hbox.set_focus_chain([])
|
||||
|
||||
tooltips.enable()
|
||||
|
||||
self.widget.pack_start(hbox, expand=False, fill=True)
|
||||
|
||||
self.screen = Screen(attrs['relation'], self._window,
|
||||
view_type=attrs.get('mode','tree,form').split(','),
|
||||
parent=self.parent, parent_name=attrs.get('relation_field', ''),
|
||||
self.screen = Screen(attrs['relation'], self.window,
|
||||
view_type=attrs.get('mode', 'tree,form').split(','),
|
||||
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', {}),
|
||||
exclude_field=attrs.get('relation_field', None))
|
||||
self.screen.signal_connect(self, 'record-message', self._sig_label)
|
||||
menuitem_title.get_child().set_text(attrs.get('string', ''))
|
||||
@@ -515,17 +207,12 @@ class One2Many(WidgetInterface):
|
||||
self.but_remove.set_sensitive(not value)
|
||||
|
||||
def _sig_new(self, widget):
|
||||
self._view.view_form.set_value()
|
||||
ctx = self._view.model.expr_eval(self.screen.default_get)
|
||||
ctx.update(self._view.model.expr_eval(self.attrs.get('context', {})))
|
||||
self.view.set_value()
|
||||
ctx = {}
|
||||
ctx.update(self.record.expr_eval(self.attrs.get('context', {})))
|
||||
sequence = None
|
||||
idx = -1
|
||||
if self.screen.current_view.view_type == 'tree':
|
||||
sequence = self.screen.current_view.widget_tree.sequence
|
||||
select_ids = self.screen.sel_ids_get()
|
||||
if select_ids:
|
||||
model = self.screen.models.get_by_id(select_ids[0])
|
||||
idx = self.screen.models.models.index(model)
|
||||
if (self.screen.current_view.view_type == 'form') \
|
||||
or self.screen.editable_get():
|
||||
self.screen.new(context=ctx)
|
||||
@@ -533,48 +220,27 @@ class One2Many(WidgetInterface):
|
||||
else:
|
||||
readonly = False
|
||||
domain = []
|
||||
if self._view.modelfield and self._view.model:
|
||||
modelfield = self._view.modelfield
|
||||
model = self._view.model
|
||||
readonly = modelfield.get_state_attrs(model
|
||||
if self.field and self.record:
|
||||
readonly = self.field.get_state_attrs(self.record
|
||||
).get('readonly', False)
|
||||
domain = modelfield.domain_get(self._view.model)
|
||||
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=readonly, domain=domain)
|
||||
res = True
|
||||
while res:
|
||||
res, value = dia.run()
|
||||
if res:
|
||||
if idx >= 0:
|
||||
idx += 1
|
||||
self.screen.models.model_add(value, position=idx)
|
||||
value.signal('record-changed', value.parent)
|
||||
self.screen.display_next()
|
||||
dia.new()
|
||||
dia.destroy()
|
||||
domain = self.field.domain_get(self.record)
|
||||
win = WinForm(self.screen, self.window, new=True,
|
||||
context=ctx)
|
||||
while True:
|
||||
if win.run():
|
||||
win.new()
|
||||
else:
|
||||
break
|
||||
win.destroy()
|
||||
if sequence:
|
||||
self.screen.models.set_sequence(field=sequence)
|
||||
self.screen.group.set_sequence(field=sequence)
|
||||
|
||||
def _sig_edit(self, widget=None):
|
||||
self._view.view_form.set_value()
|
||||
if self.screen.current_model:
|
||||
readonly = False
|
||||
domain = []
|
||||
if self._view.modelfield and self._view.model:
|
||||
modelfield = self._view.modelfield
|
||||
model = self._view.model
|
||||
readonly = modelfield.get_state_attrs(model
|
||||
).get('readonly', False)
|
||||
domain = modelfield.domain_get(self._view.model)
|
||||
dia = Dialog(self.attrs['relation'], parent=self._view.model,
|
||||
model=self.screen.current_model, attrs=self.attrs,
|
||||
window=self._window, readonly=readonly, domain=domain,
|
||||
model_ctx=self.screen.models.context)
|
||||
res, value = dia.run()
|
||||
dia.destroy()
|
||||
self.view.set_value()
|
||||
if self.screen.current_record:
|
||||
win = WinForm(self.screen, self.window)
|
||||
win.run()
|
||||
win.destroy()
|
||||
|
||||
def _sig_next(self, widget):
|
||||
self.screen.display_next()
|
||||
@@ -590,14 +256,14 @@ class One2Many(WidgetInterface):
|
||||
self.wid_text.grab_focus()
|
||||
|
||||
def _sig_add(self, *args):
|
||||
self._view.view_form.set_value()
|
||||
domain = self._view.modelfield.domain_get(self._view.model)
|
||||
self.view.set_value()
|
||||
domain = self.field.domain_get(self.record)
|
||||
context = rpc.CONTEXT.copy()
|
||||
context.update(self._view.modelfield.context_get(self._view.model))
|
||||
context.update(self.field.context_get(self.record))
|
||||
domain = domain[:]
|
||||
domain.extend(self._view.model.expr_eval(self.attrs.get('add_remove'),
|
||||
domain.extend(self.record.expr_eval(self.attrs.get('add_remove'),
|
||||
context))
|
||||
removed_ids = self._view.modelfield.get_removed_ids(self._view.model)
|
||||
removed_ids = self.field.get_removed_ids(self.record)
|
||||
|
||||
try:
|
||||
if self.wid_text.get_text():
|
||||
@@ -608,11 +274,11 @@ class One2Many(WidgetInterface):
|
||||
ids = rpc.execute('model', self.attrs['relation'],
|
||||
'search', dom, 0, _LIMIT, None, context)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self._window)
|
||||
common.process_exception(exception, self.window)
|
||||
return False
|
||||
if len(ids) != 1:
|
||||
win = WinSearch(self.attrs['relation'], sel_multi=True, ids=ids,
|
||||
context=context, domain=domain, parent=self._window,
|
||||
context=context, domain=domain, parent=self.window,
|
||||
views_preload=self.attrs.get('views', {}))
|
||||
ids = win.run()
|
||||
|
||||
@@ -632,38 +298,35 @@ class One2Many(WidgetInterface):
|
||||
line = '(%s/%s)' % (name, signal_data[1])
|
||||
self.label.set_text(line)
|
||||
|
||||
def display(self, model, model_field):
|
||||
if not model_field:
|
||||
self.screen.current_model = None
|
||||
def display(self, record, field):
|
||||
if field is None:
|
||||
self.screen.current_record = None
|
||||
self.screen.display()
|
||||
return False
|
||||
super(One2Many, self).display(model, model_field)
|
||||
new_models = model_field.get_client(model)
|
||||
if self.screen.models != new_models:
|
||||
self.screen.models_set(new_models)
|
||||
super(One2Many, self).display(record, field)
|
||||
new_group = field.get_client(record)
|
||||
if id(self.screen.group) != id(new_group):
|
||||
self.screen.group = new_group
|
||||
if (self.screen.current_view.view_type == 'tree') \
|
||||
and self.screen.editable_get():
|
||||
self.screen.current_model = None
|
||||
self.screen.current_record = None
|
||||
readonly = False
|
||||
domain = []
|
||||
if self._view.modelfield and self._view.model:
|
||||
modelfield = self._view.modelfield
|
||||
model = self._view.model
|
||||
readonly = modelfield.get_state_attrs(model
|
||||
).get('readonly', False)
|
||||
domain = modelfield.domain_get(self._view.model)
|
||||
if record:
|
||||
readonly = field.get_state_attrs(record).get('readonly', False)
|
||||
domain = field.domain_get(record)
|
||||
if self.screen.domain != domain:
|
||||
self.screen.domain = domain
|
||||
self.screen.models.readonly = readonly
|
||||
self.screen.group.readonly = readonly
|
||||
self.screen.display()
|
||||
return True
|
||||
|
||||
def display_value(self):
|
||||
return '<' + self.attrs.get('string', '') + '>'
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
def set_value(self, record, field):
|
||||
self.screen.current_view.set_value()
|
||||
if self.screen.is_modified():
|
||||
model.modified = True
|
||||
model.modified_fields.setdefault(model_field.name)
|
||||
record.modified = True
|
||||
record.modified_fields.setdefault(field.name)
|
||||
return True
|
||||
@@ -40,16 +40,16 @@ class Button(object):
|
||||
def button_clicked(self, widget):
|
||||
if not self.form:
|
||||
return
|
||||
model = self.form.screen.current_model
|
||||
record = self.form.screen.current_record
|
||||
obj_id = self.form.screen.save_current()
|
||||
if obj_id:
|
||||
if not self.attrs.get('confirm', False) or \
|
||||
common.sur(self.attrs['confirm'], self.form.window):
|
||||
button_type = self.attrs.get('type', 'workflow')
|
||||
ctx = rpc.CONTEXT.copy()
|
||||
ctx.update(model.context_get())
|
||||
ctx.update(record.context_get())
|
||||
if button_type == 'workflow':
|
||||
args = ('model', self.form.screen.name,
|
||||
args = ('model', self.form.screen.model_name,
|
||||
'workflow_trigger_validate', obj_id,
|
||||
self.attrs['name'], ctx)
|
||||
try:
|
||||
@@ -58,7 +58,7 @@ class Button(object):
|
||||
common.process_exception(exception, self.form.window,
|
||||
*args)
|
||||
elif button_type == 'object':
|
||||
args = ('model', self.form.screen.name, self.attrs['name'],
|
||||
args = ('model', self.form.screen.model_name, self.attrs['name'],
|
||||
[obj_id], ctx)
|
||||
try:
|
||||
rpc.execute(*args)
|
||||
@@ -76,7 +76,7 @@ class Button(object):
|
||||
*args)
|
||||
if action_id:
|
||||
Action.execute(action_id, {
|
||||
'model': self.form.screen.name,
|
||||
'model': self.form.screen.model_name,
|
||||
'id': obj_id,
|
||||
'ids': [obj_id],
|
||||
}, self.form.window, context=ctx)
|
||||
@@ -84,14 +84,11 @@ class Button(object):
|
||||
raise Exception('Unallowed button type')
|
||||
self.form.screen.reload(writen=True)
|
||||
else:
|
||||
if self.form.screen.form:
|
||||
self.form.screen.form.message_info(
|
||||
_('Invalid Form, correct red fields!'))
|
||||
self.form.screen.display()
|
||||
|
||||
def state_set(self, model):
|
||||
if model:
|
||||
state_changes = model.expr_eval(self.attrs.get('states', {}),
|
||||
def state_set(self, record):
|
||||
if record:
|
||||
state_changes = record.expr_eval(self.attrs.get('states', {}),
|
||||
check_load=False)
|
||||
else:
|
||||
state_changes = {}
|
||||
@@ -120,9 +117,9 @@ class Label(gtk.Label):
|
||||
super(Label, self).__init__(str=str)
|
||||
self.attrs = attrs or {}
|
||||
|
||||
def state_set(self, model):
|
||||
if model:
|
||||
state_changes = model.expr_eval(self.attrs.get('states', {}),
|
||||
def state_set(self, record):
|
||||
if record:
|
||||
state_changes = record.expr_eval(self.attrs.get('states', {}),
|
||||
check_load=False)
|
||||
else:
|
||||
state_changes = {}
|
||||
@@ -138,9 +135,9 @@ class VBox(gtk.VBox):
|
||||
super(VBox, self).__init__(homogeneous, spacing)
|
||||
self.attrs = attrs or {}
|
||||
|
||||
def state_set(self, model):
|
||||
if model:
|
||||
state_changes = model.expr_eval(self.attrs.get('states', {}),
|
||||
def state_set(self, record):
|
||||
if record:
|
||||
state_changes = record.expr_eval(self.attrs.get('states', {}),
|
||||
check_load=False)
|
||||
else:
|
||||
state_changes = {}
|
||||
@@ -156,9 +153,9 @@ class Image(gtk.Image):
|
||||
super(Image, self).__init__()
|
||||
self.attrs = attrs or {}
|
||||
|
||||
def state_set(self, model):
|
||||
if model:
|
||||
state_changes = model.expr_eval(self.attrs.get('states', {}),
|
||||
def state_set(self, record):
|
||||
if record:
|
||||
state_changes = record.expr_eval(self.attrs.get('states', {}),
|
||||
check_load=False)
|
||||
else:
|
||||
state_changes = {}
|
||||
@@ -180,9 +177,9 @@ class Frame(gtk.Frame):
|
||||
self.set_shadow_type(gtk.SHADOW_NONE)
|
||||
self.set_border_width(0)
|
||||
|
||||
def state_set(self, model):
|
||||
if model:
|
||||
state_changes = model.expr_eval(self.attrs.get('states', {}),
|
||||
def state_set(self, record):
|
||||
if record:
|
||||
state_changes = record.expr_eval(self.attrs.get('states', {}),
|
||||
check_load=False)
|
||||
else:
|
||||
state_changes = {}
|
||||
@@ -199,9 +196,9 @@ class ScrolledWindow(gtk.ScrolledWindow):
|
||||
vadjustment=vadjustment)
|
||||
self.attrs = attrs or {}
|
||||
|
||||
def state_set(self, model):
|
||||
if model:
|
||||
state_changes = model.expr_eval(self.attrs.get('states', {}),
|
||||
def state_set(self, record):
|
||||
if record:
|
||||
state_changes = record.expr_eval(self.attrs.get('states', {}),
|
||||
check_load=False)
|
||||
else:
|
||||
state_changes = {}
|
||||
@@ -298,7 +295,7 @@ class ParserForm(ParserInterface):
|
||||
screen=screen)
|
||||
self.widget_id = 0
|
||||
|
||||
def parse(self, model, root_node, fields, notebook=None, paned=None,
|
||||
def parse(self, model_name, root_node, fields, notebook=None, paned=None,
|
||||
tooltips=None):
|
||||
dict_widget = {}
|
||||
button_list = []
|
||||
@@ -323,7 +320,7 @@ class ParserForm(ParserInterface):
|
||||
attrs = common.node_attributes(node)
|
||||
if not cursor_widget:
|
||||
if attrs.get('name') and fields.get(attrs['name']) \
|
||||
and not fields[attrs['name']].get('exclude_field',
|
||||
and not fields[attrs['name']].attrs.get('exclude_field',
|
||||
False):
|
||||
cursor_widget = attrs.get('name')
|
||||
if node.localName == 'image':
|
||||
@@ -339,10 +336,10 @@ class ParserForm(ParserInterface):
|
||||
if 'string' in attrs or 'name' in attrs:
|
||||
if not text:
|
||||
if 'name' in attrs and attrs['name'] in fields:
|
||||
if 'states' in fields[attrs['name']]:
|
||||
if 'states' in fields[attrs['name']].attrs:
|
||||
attrs['states'] = \
|
||||
fields[attrs['name']]['states']
|
||||
text = fields[attrs['name']]['string']
|
||||
fields[attrs['name']].attrs['states']
|
||||
text = fields[attrs['name']].attrs['string']
|
||||
vbox = VBox(attrs=attrs)
|
||||
button_list.append(vbox)
|
||||
if text:
|
||||
@@ -359,13 +356,16 @@ class ParserForm(ParserInterface):
|
||||
text = attrs.get('string', '')
|
||||
if 'name' in attrs and attrs['name'] in fields:
|
||||
if 'states' not in attrs \
|
||||
and 'states' in fields[attrs['name']]:
|
||||
attrs['states'] = fields[attrs['name']]['states']
|
||||
and 'states' in fields[attrs['name']].attrs:
|
||||
attrs['states'] = fields[attrs['name']].attrs['states']
|
||||
if not text:
|
||||
if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
|
||||
text = _(':') + fields[attrs['name']]['string']
|
||||
if gtk.widget_get_default_direction() == \
|
||||
gtk.TEXT_DIR_RTL:
|
||||
text = _(':') + \
|
||||
fields[attrs['name']].attrs['string']
|
||||
else:
|
||||
text = fields[attrs['name']]['string'] + _(':')
|
||||
text = fields[attrs['name']].attrs['string'] + \
|
||||
_(':')
|
||||
if 'align' not in attrs:
|
||||
attrs['align'] = 1.0
|
||||
elif not text:
|
||||
@@ -436,7 +436,7 @@ class ParserForm(ParserInterface):
|
||||
container.wid_add(notebook, colspan=attrs.get('colspan', 4),
|
||||
expand=True, fill=True)
|
||||
widget, widgets, buttons, spam, notebook_list2, cursor_widget2 = \
|
||||
self.parse(model, node, fields, notebook,
|
||||
self.parse(model_name, node, fields, notebook,
|
||||
tooltips=tooltips)
|
||||
max_width, max_height = -1, -1
|
||||
window_width, window_height = Main.get_main().window.get_size()
|
||||
@@ -465,11 +465,11 @@ class ParserForm(ParserInterface):
|
||||
angle = 0
|
||||
text = attrs.get('string', '')
|
||||
if 'name' in attrs and attrs['name'] in fields:
|
||||
if 'states' in fields[attrs['name']]:
|
||||
if 'states' in fields[attrs['name']].attrs:
|
||||
attrs['states'] = \
|
||||
fields[attrs['name']]['states']
|
||||
fields[attrs['name']].attrs['states']
|
||||
if not text:
|
||||
text = fields[attrs['name']]['string']
|
||||
text = fields[attrs['name']].attrs['string']
|
||||
if not text:
|
||||
text = _('No String Attr.')
|
||||
if '_' not in text:
|
||||
@@ -478,7 +478,7 @@ class ParserForm(ParserInterface):
|
||||
label.set_angle(angle)
|
||||
label.set_use_underline(True)
|
||||
widget, widgets, buttons, spam, notebook_list2, cursor_widget2 = \
|
||||
self.parse(model, node, fields, notebook,
|
||||
self.parse(model_name, node, fields, notebook,
|
||||
tooltips=tooltips)
|
||||
if not cursor_widget:
|
||||
cursor_widget = cursor_widget2
|
||||
@@ -509,18 +509,18 @@ class ParserForm(ParserInterface):
|
||||
log = logging.getLogger('view')
|
||||
log.error('Unknown field "%s"' % str(name))
|
||||
continue
|
||||
ftype = attrs.get('widget', fields[name]['type'])
|
||||
fields[name].update(attrs)
|
||||
fields[name]['model'] = model
|
||||
ftype = attrs.get('widget', fields[name].attrs['type'])
|
||||
fields[name].attrs.update(attrs)
|
||||
fields[name].attrs['model'] = model_name
|
||||
if not ftype in WIDGETS_TYPE:
|
||||
container.empty_add(int(attrs.get('colspan', 1)))
|
||||
continue
|
||||
|
||||
fields[name]['name'] = name
|
||||
fields[name].attrs['name'] = name
|
||||
if 'saves' in attrs:
|
||||
fields[name]['saves'] = attrs['saves']
|
||||
widget_act = WIDGETS_TYPE[ftype][0](self.window, self.parent,
|
||||
model, fields[name])
|
||||
fields[name].attrs['saves'] = attrs['saves']
|
||||
widget_act = WIDGETS_TYPE[ftype][0](name, model_name,
|
||||
self.window, fields[name].attrs)
|
||||
self.widget_id += 1
|
||||
widget_act.position = self.widget_id
|
||||
dict_widget.setdefault(name, [])
|
||||
@@ -538,21 +538,22 @@ class ParserForm(ParserInterface):
|
||||
xfill = True
|
||||
if 'xfill' in attrs:
|
||||
xfill = bool(common.safe_eval(attrs['xfill']))
|
||||
hlp = fields[name].get('help', attrs.get('help', False))
|
||||
hlp = fields[name].attrs.get('help', attrs.get('help', False))
|
||||
if attrs.get('height', False) or attrs.get('width', False):
|
||||
widget_act.widget.set_size_request(
|
||||
int(attrs.get('width', -1)),
|
||||
int(attrs.get('height', -1)))
|
||||
translate = False
|
||||
if ftype in ('char', 'text'):
|
||||
translate = fields[name].get('translate', False)
|
||||
container.wid_add(widget_act.widget, fields[name]['string'],
|
||||
expand, translate=translate, colspan=size, fname=name,
|
||||
translate = fields[name].attrs.get('translate', False)
|
||||
container.wid_add(widget_act.widget,
|
||||
fields[name].attrs['string'], expand,
|
||||
translate=translate, colspan=size, fname=name,
|
||||
help_tip=hlp, fill=fill, xexpand=xexpand, xfill=xfill)
|
||||
|
||||
elif node.localName == 'group':
|
||||
widget, widgets, buttons, spam, notebook_list2, cursor_widget2 = \
|
||||
self.parse(model, node, fields, tooltips=tooltips)
|
||||
self.parse(model_name, node, fields, tooltips=tooltips)
|
||||
if not cursor_widget:
|
||||
cursor_widget = cursor_widget2
|
||||
notebook_list.extend(notebook_list2)
|
||||
@@ -562,9 +563,9 @@ class ParserForm(ParserInterface):
|
||||
button_list += buttons
|
||||
text = ''
|
||||
if 'name' in attrs and attrs['name'] in fields:
|
||||
if 'states' in fields[attrs['name']]:
|
||||
attrs['states'] = fields[attrs['name']]['states']
|
||||
text = fields[attrs['name']]['string']
|
||||
if 'states' in fields[attrs['name']].attrs:
|
||||
attrs['states'] = fields[attrs['name']].attrs['states']
|
||||
text = fields[attrs['name']].attrs['string']
|
||||
if attrs.get('string'):
|
||||
text = attrs['string']
|
||||
|
||||
@@ -580,7 +581,7 @@ class ParserForm(ParserInterface):
|
||||
container.wid_add(hpaned, colspan=int(attrs.get('colspan', 4)),
|
||||
expand=True, fill=True)
|
||||
widget, widgets, buttons, spam, notebook_list2, cursor_widget2 = \
|
||||
self.parse(model, node, fields, paned=hpaned,
|
||||
self.parse(model_name, node, fields, paned=hpaned,
|
||||
tooltips=tooltips)
|
||||
if not cursor_widget:
|
||||
cursor_widget = cursor_widget2
|
||||
@@ -596,7 +597,7 @@ class ParserForm(ParserInterface):
|
||||
container.wid_add(vpaned, colspan=int(attrs.get('colspan', 4)),
|
||||
expand=True, fill=True)
|
||||
widget, widgets, buttons, spam, notebook_list, cursor_widget2 = \
|
||||
self.parse(model, node, fields, paned=vpaned,
|
||||
self.parse(model_name, node, fields, paned=vpaned,
|
||||
tooltips=tooltips)
|
||||
if not cursor_widget:
|
||||
cursor_widget = cursor_widget2
|
||||
@@ -609,7 +610,7 @@ class ParserForm(ParserInterface):
|
||||
vpaned.set_position(int(attrs['position']))
|
||||
elif node.localName == 'child1':
|
||||
widget, widgets, buttons, spam, notebook_list2, cursor_widget2 = \
|
||||
self.parse(model, node, fields, paned=paned,
|
||||
self.parse(model_name, node, fields, paned=paned,
|
||||
tooltips=tooltips)
|
||||
if not cursor_widget:
|
||||
cursor_widget = cursor_widget2
|
||||
@@ -621,7 +622,7 @@ class ParserForm(ParserInterface):
|
||||
paned.pack1(widget, resize=True, shrink=True)
|
||||
elif node.localName == 'child2':
|
||||
widget, widgets, buttons, spam, notebook_list, cursor_widget2 = \
|
||||
self.parse(model, node, fields, paned=paned,
|
||||
self.parse(model_name, node, fields, paned=paned,
|
||||
tooltips=tooltips)
|
||||
if not cursor_widget:
|
||||
cursor_widget = cursor_widget2
|
||||
@@ -632,20 +633,20 @@ class ParserForm(ParserInterface):
|
||||
dict_widget[widget_name].extend(widgets)
|
||||
paned.pack2(widget, resize=True, shrink=True)
|
||||
for (button, src, name, widget) in container.trans_box:
|
||||
button.connect('clicked', self.translate, model, name,
|
||||
button.connect('clicked', self.translate, model_name, name,
|
||||
src, widget)
|
||||
return container.pop(), dict_widget, button_list, on_write, \
|
||||
notebook_list, cursor_widget
|
||||
|
||||
def translate(self, widget, model, name, src, widget_entry):
|
||||
obj_id = self.screen.current_model.id
|
||||
def translate(self, widget, model_name, name, src, widget_entry):
|
||||
obj_id = self.screen.current_record.id
|
||||
if obj_id < 0:
|
||||
common.message(
|
||||
_('You need to save the record before adding translations!'),
|
||||
parent=self.window)
|
||||
return False
|
||||
|
||||
obj_id = self.screen.current_model.save(force_reload=False)
|
||||
obj_id = self.screen.current_record.save(force_reload=False)
|
||||
try:
|
||||
lang_ids = rpc.execute('model', 'ir.lang',
|
||||
'search', [('translatable', '=', '1')])
|
||||
@@ -744,7 +745,7 @@ class ParserForm(ParserInterface):
|
||||
context = copy.copy(rpc.CONTEXT)
|
||||
context['language'] = lang['code']
|
||||
try:
|
||||
val = rpc.execute('model', model,
|
||||
val = rpc.execute('model', model_name,
|
||||
'read', [obj_id], [name], context)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
@@ -795,7 +796,7 @@ class ParserForm(ParserInterface):
|
||||
value_set(widget_entry, new_val['value'])
|
||||
context = copy.copy(rpc.CONTEXT)
|
||||
context['language'] = new_val['code']
|
||||
args = ('model', model, 'write', [obj_id],
|
||||
args = ('model', model_name, 'write', [obj_id],
|
||||
{str(name): new_val['value']}, context)
|
||||
try:
|
||||
rpc.execute(*args)
|
||||
@@ -805,7 +806,7 @@ class ParserForm(ParserInterface):
|
||||
self.window.present()
|
||||
win.destroy()
|
||||
return
|
||||
self.screen.current_model.reload()
|
||||
self.screen.current_record.reload()
|
||||
self.window.present()
|
||||
win.destroy()
|
||||
return True
|
||||
|
||||
@@ -14,8 +14,9 @@ class ProgressBar(WidgetInterface):
|
||||
'top_to_bottom': gtk.PROGRESS_TOP_TO_BOTTOM,
|
||||
}
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
super(ProgressBar, self).__init__(window, parent, model=model, attrs=attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(ProgressBar, self).__init__(field_name, model_name, window,
|
||||
parent, attrs=attrs)
|
||||
self.digits = attrs.get('digits', (16, 2))
|
||||
self.widget = gtk.ProgressBar()
|
||||
orientation = self.orientations.get(attrs.get('orientation',
|
||||
@@ -30,7 +31,7 @@ class ProgressBar(WidgetInterface):
|
||||
return False
|
||||
value = float(model_field.get(model) or 0.0)
|
||||
if isinstance(self.digits, str):
|
||||
digits = self._view.model.expr_eval(self.digits)
|
||||
digits = self.record.expr_eval(self.digits)
|
||||
else:
|
||||
digits = self.digits
|
||||
self.widget.set_text(locale.format('%.' + str(digits[1]) + 'f',
|
||||
|
||||
@@ -4,10 +4,10 @@ import gtk
|
||||
import gobject
|
||||
import gettext
|
||||
from interface import WidgetInterface
|
||||
from many2one import Dialog
|
||||
from tryton.gui.window.win_search import WinSearch
|
||||
from tryton.gui.window.win_form import WinForm
|
||||
from tryton.gui.window.view_form.screen import Screen
|
||||
import tryton.rpc as rpc
|
||||
from tryton.rpc import RPCProxy
|
||||
import tryton.common as common
|
||||
from tryton.gui.window.view_form.widget_search.form import _LIMIT
|
||||
|
||||
@@ -16,10 +16,9 @@ _ = gettext.gettext
|
||||
|
||||
class Reference(WidgetInterface):
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
if attrs is None:
|
||||
attrs = {}
|
||||
super(Reference, self).__init__(window, parent, model, attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(Reference, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
|
||||
self.widget = gtk.HBox(spacing=0)
|
||||
|
||||
@@ -81,9 +80,9 @@ class Reference(WidgetInterface):
|
||||
if not isinstance(selection, (list, tuple)):
|
||||
try:
|
||||
selection = rpc.execute('model',
|
||||
self.model, selection, rpc.CONTEXT)
|
||||
self.model_name, selection, rpc.CONTEXT)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self._window)
|
||||
common.process_exception(exception, self.window)
|
||||
selection = []
|
||||
selection.sort(lambda x, y: cmp(x[1], y[1]))
|
||||
self.set_popdown(selection)
|
||||
@@ -131,7 +130,7 @@ class Reference(WidgetInterface):
|
||||
def _color_widget(self):
|
||||
return self.wid_text
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
def set_value(self, record, field):
|
||||
return
|
||||
|
||||
def sig_activate(self, widget=None):
|
||||
@@ -142,7 +141,7 @@ class Reference(WidgetInterface):
|
||||
return
|
||||
child = self.widget_combo.get_child()
|
||||
self.changed = False
|
||||
value = self._view.modelfield.get_client(self._view.model)
|
||||
value = self.field.get_client(self.record)
|
||||
|
||||
self.focus_out = False
|
||||
if not value:
|
||||
@@ -155,17 +154,23 @@ class Reference(WidgetInterface):
|
||||
return False
|
||||
if model and obj_id:
|
||||
if not leave:
|
||||
dia = Dialog(model, obj_id, attrs=self.attrs,
|
||||
window=self._window)
|
||||
res, value = dia.run()
|
||||
if res:
|
||||
self._view.modelfield.set_client(self._view.model,
|
||||
(model, value), force_change=True)
|
||||
dia.destroy()
|
||||
screen = Screen(model, self.window, view_type=['form'])
|
||||
screen.load([obj_id])
|
||||
win = WinForm(screen, self.window)
|
||||
while win.run():
|
||||
if screen.save_current():
|
||||
value = (screen.current_record.id,
|
||||
screen.current_record.rec_name())
|
||||
self.field(self.record, (model, value),
|
||||
force_change=True)
|
||||
break
|
||||
else:
|
||||
screen.display()
|
||||
win.destroy()
|
||||
elif model:
|
||||
if not self._readonly and ( self.wid_text.get_text() or not leave):
|
||||
domain = self._view.modelfield.domain_get(self._view.model)
|
||||
context = self._view.modelfield.context_get(self._view.model)
|
||||
domain = self.field.domain_get(self.record)
|
||||
context = self.field.context_get(self.record)
|
||||
|
||||
try:
|
||||
if self.wid_text.get_text():
|
||||
@@ -179,40 +184,41 @@ class Reference(WidgetInterface):
|
||||
except Exception, exception:
|
||||
self.focus_out = True
|
||||
self.changed = True
|
||||
common.process_exception(exception, self._window)
|
||||
common.process_exception(exception, self.window)
|
||||
return False
|
||||
if ids and len(ids) == 1:
|
||||
self._view.modelfield.set_client(self._view.model,
|
||||
(model, (ids[0], '')))
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
self.field.set_client(self.record, (model, (ids[0], '')))
|
||||
self.display(self.record, self.field)
|
||||
self.focus_out = True
|
||||
self.changed = True
|
||||
return True
|
||||
|
||||
win = WinSearch(model, sel_multi=False, ids=ids, context=context,
|
||||
domain=domain, parent=self._window)
|
||||
domain=domain, parent=self.window)
|
||||
ids = win.run()
|
||||
if ids:
|
||||
self._view.modelfield.set_client(self._view.model,
|
||||
(model, (ids[0], '')))
|
||||
self.field.set_client(self.record, (model, (ids[0], '')))
|
||||
else:
|
||||
self._view.modelfield.set_client(self._view.model,
|
||||
('', (name, name)))
|
||||
self.field.set_client(self.record, ('', (name, name)))
|
||||
self.focus_out = True
|
||||
self.changed = True
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
self.display(self.record, self.field)
|
||||
|
||||
def sig_new(self, *args):
|
||||
model = self.get_model()
|
||||
if not model:
|
||||
return
|
||||
dia = Dialog(model, window=self._window)
|
||||
res, value = dia.run()
|
||||
if res:
|
||||
self._view.modelfield.set_client(self._view.model,
|
||||
(model, value))
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
dia.destroy()
|
||||
screen = Screen(model, self.window, view_type=['form'])
|
||||
win = WinForm(screen, self.window, new=True)
|
||||
while win.run():
|
||||
if screen.save_current():
|
||||
value = (screen.current_record.id,
|
||||
screen.current_record.rec_name())
|
||||
self.field.set_client(self.record, (model, value))
|
||||
break
|
||||
else:
|
||||
screen.display()
|
||||
win.destroy()
|
||||
|
||||
def sig_key_press(self, widget, event):
|
||||
editable = self.wid_text.get_editable()
|
||||
@@ -223,7 +229,7 @@ class Reference(WidgetInterface):
|
||||
self.sig_focus_out(widget, event)
|
||||
return True
|
||||
elif event.keyval in (gtk.keysyms.Tab, gtk.keysyms.Return) and editable:
|
||||
if self._view.modelfield.get(self._view.model) or \
|
||||
if self.field.get(self.record) or \
|
||||
not self.wid_text.get_text():
|
||||
return False
|
||||
self.sig_focus_out(widget, event, leave=True)
|
||||
@@ -234,32 +240,30 @@ class Reference(WidgetInterface):
|
||||
if not self.changed:
|
||||
return
|
||||
self.wid_text.set_text('')
|
||||
self._view.modelfield.set_client(self._view.model,
|
||||
(self.get_model(), (0, '')))
|
||||
self.field.set_client(self.record, (self.get_model(), (0, '')))
|
||||
|
||||
def sig_changed(self, *args):
|
||||
if not self.changed:
|
||||
return False
|
||||
val = self._view.modelfield.get_client(self._view.model)
|
||||
val = self.field.get_client(self.record)
|
||||
if not val:
|
||||
model, (obj_id, name) = '', (0, '')
|
||||
else:
|
||||
model, (obj_id, name) = val
|
||||
if self.get_model() and obj_id:
|
||||
self._view.modelfield.set_client(self._view.model,
|
||||
(self.get_model(), (0, '')))
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
self.field.set_client(self.record, (self.get_model(), (0, '')))
|
||||
self.display(self.record, self.field)
|
||||
return False
|
||||
|
||||
def display(self, model, model_field):
|
||||
def display(self, record, field):
|
||||
child = self.widget_combo.get_child()
|
||||
self.changed = False
|
||||
if not model_field:
|
||||
if not field:
|
||||
child.set_text('')
|
||||
self.changed =True
|
||||
return False
|
||||
super(Reference, self).display(model, model_field)
|
||||
value = model_field.get_client(model)
|
||||
super(Reference, self).display(record, field)
|
||||
value = field.get_client(record)
|
||||
img = gtk.Image()
|
||||
if not value:
|
||||
model, (obj_id, name) = '', (0, '')
|
||||
@@ -268,12 +272,15 @@ class Reference(WidgetInterface):
|
||||
if model:
|
||||
child.set_text(self._selection2[model])
|
||||
if not name and obj_id:
|
||||
args = ('model', model, 'read', obj_id, ['rec_name'],
|
||||
rpc.CONTEXT)
|
||||
try:
|
||||
name = RPCProxy(model).read(obj_id, ['rec_name'],
|
||||
rpc.CONTEXT)['rec_name']
|
||||
name = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self._window)
|
||||
name = '???'
|
||||
name = common.process_exception(exception, self.window,
|
||||
*args)
|
||||
if not name:
|
||||
name = '???'
|
||||
self.wid_text.set_text(name)
|
||||
if obj_id:
|
||||
img.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
|
||||
@@ -9,8 +9,9 @@ import tryton.common as common
|
||||
|
||||
class Selection(WidgetInterface):
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
super(Selection, self).__init__(window, parent, model, attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(Selection, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
|
||||
self.widget = gtk.HBox(spacing=3)
|
||||
self.entry = gtk.ComboBoxEntry()
|
||||
@@ -40,16 +41,16 @@ class Selection(WidgetInterface):
|
||||
['rec_name'])
|
||||
selection = [(x['id'], x['rec_name']) for x in result]
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self._window)
|
||||
common.process_exception(exception, self.window)
|
||||
selection = []
|
||||
self.selection = selection[:]
|
||||
else:
|
||||
if not isinstance(selection, (list, tuple)):
|
||||
try:
|
||||
selection = rpc.execute('model',
|
||||
self.model, selection, rpc.CONTEXT)
|
||||
self.model_name, selection, rpc.CONTEXT)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self._window)
|
||||
common.process_exception(exception, self.window)
|
||||
selection = []
|
||||
self.selection = selection[:]
|
||||
|
||||
@@ -123,24 +124,24 @@ class Selection(WidgetInterface):
|
||||
value = val
|
||||
if len(txt) == len(text):
|
||||
break
|
||||
self._view.modelfield.set_client(self._view.model, value, force_change=True)
|
||||
self.display(self._view.model, self._view.modelfield)
|
||||
self.field.set_client(self.record, value, force_change=True)
|
||||
self.display(self.record, self.field)
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
model_field.set_client(model, self.value_get())
|
||||
def set_value(self, record, field):
|
||||
field.set_client(record, self.value_get())
|
||||
|
||||
def _menu_sig_default_set(self, reset=False):
|
||||
self.set_value(self._view.model, self._view.modelfield)
|
||||
self.set_value(self.record, self.field)
|
||||
super(Selection, self)._menu_sig_default_set(reset=reset)
|
||||
|
||||
def display(self, model, model_field):
|
||||
def display(self, record, field):
|
||||
child = self.entry.get_child()
|
||||
self.changed = False
|
||||
if not model_field:
|
||||
if not field:
|
||||
child.set_text('')
|
||||
return False
|
||||
super(Selection, self).display(model, model_field)
|
||||
value = model_field.get(model)
|
||||
super(Selection, self).display(record, field)
|
||||
value = field.get(record)
|
||||
if isinstance(value, (list, tuple)):
|
||||
value = value[0]
|
||||
if not value:
|
||||
|
||||
@@ -13,8 +13,9 @@ except:
|
||||
|
||||
class TextBox(WidgetInterface):
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
super(TextBox, self).__init__(window, parent, model, attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(TextBox, self).__init__(field_name, model_name, window,
|
||||
attrs=attrs)
|
||||
|
||||
self.widget = gtk.HBox()
|
||||
self.scrolledwindow = gtk.ScrolledWindow()
|
||||
@@ -55,8 +56,8 @@ class TextBox(WidgetInterface):
|
||||
|
||||
if not value and self.attrs.get('spell') \
|
||||
and CONFIG['client.spellcheck'] \
|
||||
and self._view and self._view.model:
|
||||
language = self._view.model.expr_eval(self.attrs['spell'])
|
||||
and self.record:
|
||||
language = self.record.expr_eval(self.attrs['spell'])
|
||||
try:
|
||||
if not spell:
|
||||
spell = gtkspell.Spell(self.textview)
|
||||
@@ -76,16 +77,16 @@ class TextBox(WidgetInterface):
|
||||
def _color_widget(self):
|
||||
return self.textview
|
||||
|
||||
def set_value(self, model, model_field):
|
||||
def set_value(self, record, field):
|
||||
buf = self.textview.get_buffer()
|
||||
iter_start = buf.get_start_iter()
|
||||
iter_end = buf.get_end_iter()
|
||||
current_text = buf.get_text(iter_start, iter_end, False)
|
||||
model_field.set_client(model, current_text or False)
|
||||
field.set_client(record, current_text or False)
|
||||
|
||||
def display(self, model, model_field):
|
||||
super(TextBox, self).display(model, model_field)
|
||||
value = model_field and model_field.get(model)
|
||||
def display(self, record, field):
|
||||
super(TextBox, self).display(record, field)
|
||||
value = field and field.get(record)
|
||||
if not value:
|
||||
value = ''
|
||||
buf = self.textview.get_buffer()
|
||||
@@ -101,8 +102,8 @@ class TextBox(WidgetInterface):
|
||||
pass
|
||||
|
||||
if self.attrs.get('spell') and CONFIG['client.spellcheck'] \
|
||||
and self._view and self._view.model:
|
||||
language = self._view.model.expr_eval(self.attrs['spell'])
|
||||
and self.record:
|
||||
language = self.record.expr_eval(self.attrs['spell'])
|
||||
try:
|
||||
if not spell:
|
||||
spell = gtkspell.Spell(self.textview)
|
||||
@@ -120,7 +121,7 @@ class TextBox(WidgetInterface):
|
||||
del spell
|
||||
|
||||
def display_value(self):
|
||||
lines = (self._view.modelfield.get_client(self._view.model) or '').split('\n')
|
||||
lines = (self.field.get_client(self.record) or '').split('\n')
|
||||
if len(lines) > 1:
|
||||
return lines[0] + '...'
|
||||
else:
|
||||
|
||||
@@ -10,10 +10,8 @@ import tryton.common as common
|
||||
class URL(Char):
|
||||
"url"
|
||||
|
||||
def __init__(self, window, parent, model, attrs=None):
|
||||
if attrs is None:
|
||||
attrs = {}
|
||||
super(URL, self).__init__(window, parent, model, attrs=attrs)
|
||||
def __init__(self, field_name, model_name, window, attrs=None):
|
||||
super(URL, self).__init__(field_name, model_name, window, attrs=attrs)
|
||||
|
||||
self.tooltips = common.Tooltips()
|
||||
self.button = gtk.Button()
|
||||
@@ -26,8 +24,8 @@ class URL(Char):
|
||||
self.widget.pack_start(self.button, expand=False, fill=False)
|
||||
self.widget.set_focus_chain([self.entry])
|
||||
|
||||
def display(self, model, model_field):
|
||||
super(URL, self).display(model, model_field)
|
||||
def display(self, record, field):
|
||||
super(URL, self).display(record, field)
|
||||
self.set_tooltips()
|
||||
|
||||
def set_tooltips(self):
|
||||
|
||||
@@ -10,7 +10,6 @@ class ViewGraph(ParserView):
|
||||
super(ViewGraph, self).__init__(window, screen, widget, children,
|
||||
buttons, toolbar, notebooks, cursor_widget)
|
||||
self.view_type = 'graph'
|
||||
self.model_add_new = False
|
||||
self.widgets = children
|
||||
|
||||
def __getitem__(self, name):
|
||||
@@ -37,9 +36,6 @@ class ViewGraph(ParserView):
|
||||
def reset(self):
|
||||
pass
|
||||
|
||||
def signal_record_changed(self, *args):
|
||||
self.display()
|
||||
|
||||
def display(self):
|
||||
for widget in self.widgets.itervalues():
|
||||
widget.display(self.screen.models)
|
||||
|
||||
@@ -354,7 +354,7 @@ class Graph(gtk.DrawingArea):
|
||||
if yfield.get('domain'):
|
||||
values = rpc.CONTEXT.copy()
|
||||
values['state'] = 'draft'
|
||||
for field in model.mgroup.fields:
|
||||
for field in model.group.fields:
|
||||
values[field] = model[field].get(model, check_load=False)
|
||||
if not PYSONDecoder(values).decode(yfield['domain']):
|
||||
continue
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
import gobject
|
||||
import gtk
|
||||
from tryton.rpc import RPCProxy
|
||||
import tryton.rpc as rpc
|
||||
import locale
|
||||
from interface import ParserView
|
||||
@@ -13,6 +12,7 @@ import tryton.common as common
|
||||
from tryton.config import CONFIG
|
||||
from tryton.common.cellrendererbutton import CellRendererButton
|
||||
from tryton.common.cellrenderertoggle import CellRendererToggle
|
||||
from tryton.pyson import PYSONEncoder
|
||||
import os
|
||||
|
||||
_ = gettext.gettext
|
||||
@@ -20,17 +20,16 @@ _ = gettext.gettext
|
||||
|
||||
class AdaptModelGroup(gtk.GenericTreeModel):
|
||||
|
||||
def __init__(self, model_group):
|
||||
def __init__(self, group):
|
||||
super(AdaptModelGroup, self).__init__()
|
||||
self.model_group = model_group
|
||||
self.models = model_group.models
|
||||
self.group = group
|
||||
self.last_sort = None
|
||||
self.sort_asc = True
|
||||
self.set_property('leak_references', False)
|
||||
|
||||
def added(self, modellist, position):
|
||||
if modellist is self.models:
|
||||
model = self.models[position]
|
||||
if modellist is self.group:
|
||||
model = self.group[position]
|
||||
self.row_inserted(self.on_get_path(model),
|
||||
self.get_iter(self.on_get_path(model)))
|
||||
|
||||
@@ -42,26 +41,26 @@ class AdaptModelGroup(gtk.GenericTreeModel):
|
||||
self.invalidate_iters()
|
||||
|
||||
def append(self, model):
|
||||
self.model_group.model_add(model)
|
||||
self.group.add(model)
|
||||
|
||||
def prepend(self, model):
|
||||
self.model_group.model_add(model, 0)
|
||||
self.group.add(model, 0)
|
||||
|
||||
def remove(self, iter):
|
||||
idx = self.get_path(iter)[0]
|
||||
self.model_group.model_remove(self.models[idx])
|
||||
self.group.remove(self.group[idx])
|
||||
self.invalidate_iters()
|
||||
|
||||
def move(self, path, position):
|
||||
idx = path[0]
|
||||
self.model_group.model_move(self.models[idx], position)
|
||||
self.group.move(self.group[idx], position)
|
||||
|
||||
def sort(self, ids):
|
||||
ids2pos = {}
|
||||
pos = 0
|
||||
new_order = []
|
||||
for model in self.models:
|
||||
ids2pos[model.id] = pos
|
||||
for record in self.group:
|
||||
ids2pos[record.id] = pos
|
||||
new_order.append(pos)
|
||||
pos += 1
|
||||
pos = 0
|
||||
@@ -73,19 +72,19 @@ class AdaptModelGroup(gtk.GenericTreeModel):
|
||||
pos += 1
|
||||
except:
|
||||
continue
|
||||
self.models.sort(lambda x, y: \
|
||||
self.group.sort(lambda x, y: \
|
||||
cmp(new_order[ids2pos[x.id]], new_order[ids2pos[y.id]]))
|
||||
prev = None
|
||||
for model in self.models:
|
||||
for record in self.group:
|
||||
if prev:
|
||||
prev.next[id(self.models)] = model
|
||||
prev = model
|
||||
prev.next[id(self.group)] = record
|
||||
prev = record
|
||||
if prev:
|
||||
prev.next[id(self.models)] = None
|
||||
prev.next[id(self.group)] = None
|
||||
self.rows_reordered(None, None, new_order)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.models)
|
||||
return len(self.group)
|
||||
|
||||
def on_get_flags(self):
|
||||
return gtk.TREE_MODEL_LIST_ONLY
|
||||
@@ -97,17 +96,17 @@ class AdaptModelGroup(gtk.GenericTreeModel):
|
||||
return gobject.TYPE_PYOBJECT
|
||||
|
||||
def on_get_path(self, iter):
|
||||
if iter in self.models:
|
||||
return self.models.index(iter)
|
||||
if iter in self.group:
|
||||
return self.group.index(iter)
|
||||
else:
|
||||
return 0
|
||||
|
||||
def on_get_iter(self, path):
|
||||
if isinstance(path, tuple):
|
||||
path = path[0]
|
||||
if self.models:
|
||||
if path < len(self.models):
|
||||
return self.models[path]
|
||||
if self.group is not None:
|
||||
if path < len(self.group):
|
||||
return self.group[path]
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
@@ -119,7 +118,7 @@ class AdaptModelGroup(gtk.GenericTreeModel):
|
||||
|
||||
def on_iter_next(self, node):
|
||||
try:
|
||||
return node.next[id(self.models)]
|
||||
return node.next[id(self.group)]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
@@ -131,11 +130,11 @@ class AdaptModelGroup(gtk.GenericTreeModel):
|
||||
|
||||
def on_iter_n_children(self, node):
|
||||
if node is None:
|
||||
return len(self.models)
|
||||
return len(self.group)
|
||||
return 0
|
||||
|
||||
def on_iter_nth_child(self, node, nth):
|
||||
if node is None and self.models:
|
||||
if node is None and self.group is not None:
|
||||
return self.on_get_iter(0)
|
||||
return None
|
||||
|
||||
@@ -151,7 +150,6 @@ class ViewList(ParserView):
|
||||
buttons, toolbar, notebooks, cursor_widget)
|
||||
self.store = None
|
||||
self.view_type = 'tree'
|
||||
self.model_add_new = True
|
||||
self.widget = gtk.VBox()
|
||||
self.widget_tree = widget
|
||||
scroll = gtk.ScrolledWindow()
|
||||
@@ -272,13 +270,13 @@ class ViewList(ParserView):
|
||||
return False
|
||||
email = {}
|
||||
if action.get('email'):
|
||||
email = self.screen.current_model.expr_eval(action['email'])
|
||||
email = self.screen.current_record.expr_eval(action['email'])
|
||||
if not email:
|
||||
email = {}
|
||||
email['subject'] = action['name'].replace('_', '')
|
||||
act['email'] = email
|
||||
data = {
|
||||
'model': self.screen.name,
|
||||
'model': self.screen.model_name,
|
||||
'id': obj_id,
|
||||
'ids': obj_ids,
|
||||
}
|
||||
@@ -327,13 +325,13 @@ class ViewList(ParserView):
|
||||
self.copy_clear_func, selection)
|
||||
|
||||
def copy_foreach(self, treemodel, path,iter, data):
|
||||
model = treemodel.get_value(iter, 0)
|
||||
record = treemodel.get_value(iter, 0)
|
||||
values = []
|
||||
for col in self.widget_tree.get_columns():
|
||||
if not col.get_visible() or not col.name:
|
||||
continue
|
||||
cell = self.widget_tree.cells[col.name]
|
||||
values.append('"' + str(cell.get_textual_value(model)) + '"')
|
||||
values.append('"' + str(cell.get_textual_value(record)) + '"')
|
||||
data.append('\t'.join(values))
|
||||
return
|
||||
|
||||
@@ -370,9 +368,9 @@ class ViewList(ParserView):
|
||||
info, etime):
|
||||
treeview.emit_stop_by_name('drag-data-received')
|
||||
if treeview.sequence:
|
||||
for model in self.screen.models.models:
|
||||
if model[treeview.sequence].get_state_attrs(
|
||||
model).get('readonly', False):
|
||||
for record in self.screen.group:
|
||||
if record[treeview.sequence].get_state_attrs(
|
||||
record).get('readonly', False):
|
||||
return
|
||||
if not selection.data:
|
||||
return
|
||||
@@ -389,7 +387,7 @@ class ViewList(ParserView):
|
||||
model.move(data, idx + 1)
|
||||
context.drop_finish(False, etime)
|
||||
if treeview.sequence:
|
||||
self.screen.models.set_sequence(field=treeview.sequence)
|
||||
self.screen.group.set_sequence(field=treeview.sequence)
|
||||
|
||||
def drag_data_delete(self, treeview, context):
|
||||
treeview.emit_stop_by_name('drag-data-delete')
|
||||
@@ -404,18 +402,21 @@ class ViewList(ParserView):
|
||||
model = selection.get_selected_rows()[0]
|
||||
if (not path) or not path[0]:
|
||||
return False
|
||||
model = model.models[path[0][0]]
|
||||
record = model.group[path[0][0]]
|
||||
|
||||
if hasattr(path[1], '_type') and path[1]._type == 'many2one':
|
||||
value = model[path[1].name].get(model)
|
||||
ir_action_keyword = RPCProxy('ir.action.keyword')
|
||||
value = record[path[1].name].get(record)
|
||||
args = ('model', 'ir.action.keyword', 'get_keyword',
|
||||
'form_relate',
|
||||
(self.screen.fields[path[1].name]['relation'], 0),
|
||||
rpc.CONTEXT)
|
||||
try:
|
||||
relates = ir_action_keyword.get_keyword('form_relate',
|
||||
(self.screen.fields[path[1].name]['relation'], 0),
|
||||
rpc.CONTEXT)
|
||||
relates = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
return False
|
||||
relates = common.process_exception(exception, self.window,
|
||||
*args)
|
||||
if not relates:
|
||||
return False
|
||||
menu_entries = []
|
||||
menu_entries.append((None, None, None))
|
||||
menu_entries.append((_('Actions'),
|
||||
@@ -457,11 +458,12 @@ class ViewList(ParserView):
|
||||
screen = Screen(self.screen.fields[path[1].name]['relation'],
|
||||
self.window)
|
||||
screen.load([value])
|
||||
act['domain'] = str(screen.current_model.expr_eval(act.get('domain', []),
|
||||
check_load=False))
|
||||
act['context'] = str(screen.current_model.expr_eval(act.get('context', {}),
|
||||
check_load=False))
|
||||
data['model'] = self.screen.name
|
||||
encoder = PYSONEncoder()
|
||||
act['domain'] = encoder.encode(screen.current_record.expr_eval(
|
||||
act.get('domain', []), check_load=False))
|
||||
act['context'] = encoder.encode(screen.current_record.expr_eval(
|
||||
act.get('context', {}), check_load=False))
|
||||
data['model'] = self.screen.model_name
|
||||
data['id'] = value
|
||||
data['ids'] = [value]
|
||||
return Action._exec_action(act, self.window, data, context)
|
||||
@@ -473,19 +475,19 @@ class ViewList(ParserView):
|
||||
'ids': [value],
|
||||
}, alwaysask=True)
|
||||
|
||||
def signal_record_changed(self, signal, *args):
|
||||
if self.store:
|
||||
if signal == 'record-added':
|
||||
self.store.added(*args)
|
||||
elif signal == 'record-removed':
|
||||
self.store.removed(*args)
|
||||
def group_list_changed(self, group, signal):
|
||||
if self.store is not None:
|
||||
if signal[0] == 'record-added':
|
||||
self.store.added(group, signal[1])
|
||||
elif signal[0] == 'record-removed':
|
||||
self.store.removed(group, signal[1])
|
||||
self.update_children()
|
||||
|
||||
def cancel(self):
|
||||
pass
|
||||
|
||||
def __str__(self):
|
||||
return 'ViewList (%s)' % self.screen.resource
|
||||
return 'ViewList (%s)' % self.screen.model_name
|
||||
|
||||
def __getitem__(self, name):
|
||||
return None
|
||||
@@ -523,26 +525,26 @@ class ViewList(ParserView):
|
||||
self.screen.row_activate()
|
||||
|
||||
def __select_changed(self, tree_sel):
|
||||
previous_model = self.screen.current_model
|
||||
previous_record = self.screen.current_record
|
||||
|
||||
if tree_sel.get_mode() == gtk.SELECTION_SINGLE:
|
||||
model, iter = tree_sel.get_selected()
|
||||
if iter:
|
||||
path = model.get_path(iter)[0]
|
||||
self.screen.current_model = model.models[path]
|
||||
self.screen.current_record = model.group[path]
|
||||
|
||||
elif tree_sel.get_mode() == gtk.SELECTION_MULTIPLE:
|
||||
model, paths = tree_sel.get_selected_rows()
|
||||
if paths:
|
||||
self.screen.current_model = model.models[paths[0][0]]
|
||||
self.screen.current_record = model.group[paths[0][0]]
|
||||
|
||||
if hasattr(self.widget_tree, 'editable') \
|
||||
and self.widget_tree.editable \
|
||||
and self.screen.tree_saves \
|
||||
and previous_model != self.screen.current_model:
|
||||
if previous_model and \
|
||||
not (previous_model.validate() and previous_model.save()):
|
||||
self.screen.current_model = previous_model
|
||||
and not self.screen.parent \
|
||||
and previous_record != self.screen.current_record:
|
||||
if previous_record and \
|
||||
not (previous_record.validate() and previous_record.save()):
|
||||
self.screen.current_record = previous_record
|
||||
self.set_cursor()
|
||||
return True
|
||||
self.update_children()
|
||||
@@ -561,12 +563,12 @@ class ViewList(ParserView):
|
||||
def display(self):
|
||||
if self.reload \
|
||||
or (not self.widget_tree.get_model()) \
|
||||
or self.screen.models != \
|
||||
self.widget_tree.get_model().model_group:
|
||||
self.store = AdaptModelGroup(self.screen.models)
|
||||
or self.screen.group != \
|
||||
self.widget_tree.get_model().group:
|
||||
self.store = AdaptModelGroup(self.screen.group)
|
||||
self.widget_tree.set_model(self.store)
|
||||
self.reload = False
|
||||
if not self.screen.current_model:
|
||||
if not self.screen.current_record:
|
||||
# Should find a simpler solution to do something like
|
||||
#self.widget.set_cursor(None,None,False)
|
||||
if self.store:
|
||||
@@ -578,12 +580,12 @@ class ViewList(ParserView):
|
||||
self.update_children()
|
||||
|
||||
def set_state(self):
|
||||
model = self.screen.current_model
|
||||
if model:
|
||||
for field in model.mgroup.fields:
|
||||
modelfield = model.mgroup.mfields.get(field, None)
|
||||
if modelfield:
|
||||
modelfield.state_set(model)
|
||||
record = self.screen.current_record
|
||||
if record:
|
||||
for field in record.group.fields:
|
||||
field = record.group.fields.get(field, None)
|
||||
if field:
|
||||
field.state_set(record)
|
||||
|
||||
def update_children(self):
|
||||
ids = self.sel_ids_get()
|
||||
@@ -591,23 +593,23 @@ class ViewList(ParserView):
|
||||
value = 0.0
|
||||
value_selected = 0.0
|
||||
loaded = True
|
||||
for model in self.screen.models.models:
|
||||
if not model.loaded:
|
||||
for record in self.screen.group:
|
||||
if not record.loaded:
|
||||
loaded = False
|
||||
break
|
||||
if model.id in ids or not ids:
|
||||
if record.id in ids or not ids:
|
||||
if not value_selected:
|
||||
value_selected = model.fields_get()[self.children[child][0]]\
|
||||
.get(model, check_load=False)
|
||||
value_selected = record.fields_get()[self.children[child][0]]\
|
||||
.get(record, check_load=False)
|
||||
else:
|
||||
value_selected += model.fields_get()[self.children[child][0]]\
|
||||
.get(model, check_load=False)
|
||||
value_selected += record.fields_get()[self.children[child][0]]\
|
||||
.get(record, check_load=False)
|
||||
if not value:
|
||||
value = model.fields_get()[self.children[child][0]]\
|
||||
.get(model, check_load=False)
|
||||
value = record.fields_get()[self.children[child][0]]\
|
||||
.get(record, check_load=False)
|
||||
else:
|
||||
value += model.fields_get()[self.children[child][0]]\
|
||||
.get(model, check_load=False)
|
||||
value += record.fields_get()[self.children[child][0]]\
|
||||
.get(record, check_load=False)
|
||||
|
||||
if loaded:
|
||||
label_str = locale.format('%.' + str(self.children[child][3]) + 'f',
|
||||
@@ -624,8 +626,8 @@ class ViewList(ParserView):
|
||||
|
||||
def set_cursor(self, new=False, reset_view=True):
|
||||
self.widget_tree.grab_focus()
|
||||
if self.screen.current_model:
|
||||
path = self.store.on_get_path(self.screen.current_model)
|
||||
if self.screen.current_record:
|
||||
path = self.store.on_get_path(self.screen.current_record)
|
||||
focus_column = None
|
||||
for column in self.widget_tree.get_columns():
|
||||
renderers = column.get_cell_renderers()
|
||||
@@ -647,21 +649,21 @@ class ViewList(ParserView):
|
||||
|
||||
def sel_ids_get(self):
|
||||
def _func_sel_get(store, path, iter, ids):
|
||||
model = store.on_get_iter(path)
|
||||
if model and model.id > 0:
|
||||
ids.append(model.id)
|
||||
record = store.on_get_iter(path)
|
||||
if record and record.id > 0:
|
||||
ids.append(record.id)
|
||||
ids = []
|
||||
sel = self.widget_tree.get_selection()
|
||||
sel.selected_foreach(_func_sel_get, ids)
|
||||
return ids
|
||||
|
||||
def sel_models_get(self):
|
||||
def _func_sel_get(store, path, iter, models):
|
||||
models.append(store.on_get_iter(path))
|
||||
models = []
|
||||
def selected_records(self):
|
||||
def _func_sel_get(store, path, iter, records):
|
||||
records.append(store.on_get_iter(path))
|
||||
records = []
|
||||
sel = self.widget_tree.get_selection()
|
||||
sel.selected_foreach(_func_sel_get, models)
|
||||
return models
|
||||
sel.selected_foreach(_func_sel_get, records)
|
||||
return records
|
||||
|
||||
def unset_editable(self):
|
||||
self.widget_tree.editable = False
|
||||
|
||||
@@ -10,9 +10,9 @@ _ = gettext.gettext
|
||||
|
||||
|
||||
class EditableTreeView(gtk.TreeView):
|
||||
leaving_model_events = (gtk.keysyms.Up, gtk.keysyms.Down,
|
||||
leaving_record_events = (gtk.keysyms.Up, gtk.keysyms.Down,
|
||||
gtk.keysyms.Return)
|
||||
leaving_events = leaving_model_events + (gtk.keysyms.Tab,
|
||||
leaving_events = leaving_record_events + (gtk.keysyms.Tab,
|
||||
gtk.keysyms.ISO_Left_Tab, gtk.keysyms.KP_Enter)
|
||||
|
||||
def __init__(self, position):
|
||||
@@ -20,38 +20,38 @@ class EditableTreeView(gtk.TreeView):
|
||||
self.editable = position
|
||||
self.cells = {}
|
||||
|
||||
def on_quit_cell(self, current_model, fieldname, value):
|
||||
modelfield = current_model[fieldname]
|
||||
if hasattr(modelfield, 'editabletree_entry'):
|
||||
del modelfield.editabletree_entry
|
||||
def on_quit_cell(self, current_record, fieldname, value):
|
||||
field = current_record[fieldname]
|
||||
if hasattr(field, 'editabletree_entry'):
|
||||
del field.editabletree_entry
|
||||
cell = self.cells[fieldname]
|
||||
|
||||
# The value has not changed and is valid ... do nothing.
|
||||
if value == cell.get_textual_value(current_model) \
|
||||
and modelfield.validate(current_model):
|
||||
if value == cell.get_textual_value(current_record) \
|
||||
and field.validate(current_record):
|
||||
return
|
||||
|
||||
try:
|
||||
real_value = cell.value_from_text(current_model, value)
|
||||
modelfield.set_client(current_model, real_value)
|
||||
real_value = cell.value_from_text(current_record, value)
|
||||
field.set_client(current_record, real_value)
|
||||
except parser.UnsettableColumn:
|
||||
return
|
||||
|
||||
def on_open_remote(self, current_model, fieldname, create, value):
|
||||
modelfield = current_model[fieldname]
|
||||
def on_open_remote(self, current_record, fieldname, create, value):
|
||||
field = current_record[fieldname]
|
||||
cell = self.cells[fieldname]
|
||||
if value != cell.get_textual_value(current_model) or not value:
|
||||
if value != cell.get_textual_value(current_record) or not value:
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
try:
|
||||
valid, value = cell.open_remote(current_model, create,
|
||||
valid, value = cell.open_remote(current_record, create,
|
||||
changed, value)
|
||||
if valid:
|
||||
modelfield.set_client(current_model, value)
|
||||
field.set_client(current_record, value)
|
||||
except NotImplementedError:
|
||||
pass
|
||||
return cell.get_textual_value(current_model)
|
||||
return cell.get_textual_value(current_record)
|
||||
|
||||
def on_create_line(self):
|
||||
model = self.get_model()
|
||||
@@ -60,12 +60,9 @@ class EditableTreeView(gtk.TreeView):
|
||||
else:
|
||||
method = model.append
|
||||
ctx = self.screen.context.copy()
|
||||
if self.screen.current_model and self.screen.current_model.parent:
|
||||
ctx.update(self.screen.current_model.parent.expr_eval(
|
||||
self.screen.default_get))
|
||||
new_model = model.model_group.model_new(domain=self.screen.domain,
|
||||
new_record = model.group.new(domain=self.screen.domain,
|
||||
context=ctx)
|
||||
res = method(new_model)
|
||||
res = method(new_record)
|
||||
return res
|
||||
|
||||
def __next_column(self, col):
|
||||
@@ -115,24 +112,24 @@ class EditableTreeView(gtk.TreeView):
|
||||
|
||||
def set_value(self):
|
||||
path, column = self.get_cursor()
|
||||
store = self.get_model()
|
||||
model = self.get_model()
|
||||
if not path or not column:
|
||||
return True
|
||||
model = store.get_value(store.get_iter(path), 0)
|
||||
modelfield = model[column.name]
|
||||
if hasattr(modelfield, 'editabletree_entry'):
|
||||
entry = modelfield.editabletree_entry
|
||||
record = model.get_value(model.get_iter(path), 0)
|
||||
field = record[column.name]
|
||||
if hasattr(field, 'editabletree_entry'):
|
||||
entry = field.editabletree_entry
|
||||
if isinstance(entry, gtk.Entry):
|
||||
txt = entry.get_text()
|
||||
else:
|
||||
txt = entry.get_active_text()
|
||||
self.on_quit_cell(model, column.name, txt)
|
||||
self.on_quit_cell(record, column.name, txt)
|
||||
return True
|
||||
|
||||
def on_keypressed(self, entry, event):
|
||||
path, column = self.get_cursor()
|
||||
store = self.get_model()
|
||||
model = store.get_value(store.get_iter(path), 0)
|
||||
model = self.get_model()
|
||||
record = model.get_value(model.get_iter(path), 0)
|
||||
|
||||
leaving = False
|
||||
if event.keyval == gtk.keysyms.Right:
|
||||
@@ -157,24 +154,20 @@ class EditableTreeView(gtk.TreeView):
|
||||
else:
|
||||
txt = entry.get_active_text()
|
||||
entry.disconnect(entry.editing_done_id)
|
||||
self.on_quit_cell(model, column.name, txt)
|
||||
self.on_quit_cell(record, column.name, txt)
|
||||
entry.editing_done_id = entry.connect('editing_done',
|
||||
self.on_editing_done)
|
||||
if event.keyval in self.leaving_model_events:
|
||||
if not model.validate():
|
||||
invalid_fields = model.invalid_fields
|
||||
if event.keyval in self.leaving_record_events:
|
||||
if not record.validate():
|
||||
invalid_fields = record.invalid_fields
|
||||
col = None
|
||||
for col in self.get_columns():
|
||||
if col.name in invalid_fields:
|
||||
break
|
||||
self.set_cursor(path, col, True)
|
||||
if self.screen.form:
|
||||
self.screen.form.message_info(
|
||||
_('Warning; field "%s" is required!') % \
|
||||
invalid_fields[col.name])
|
||||
return True
|
||||
if self.screen.tree_saves:
|
||||
obj_id = model.save()
|
||||
if not self.screen.parent:
|
||||
obj_id = record.save()
|
||||
if not obj_id:
|
||||
return True
|
||||
if event.keyval in (gtk.keysyms.Tab, gtk.keysyms.KP_Enter) \
|
||||
@@ -187,12 +180,12 @@ class EditableTreeView(gtk.TreeView):
|
||||
self.set_cursor(path, new_col, True)
|
||||
elif event.keyval == gtk.keysyms.Up:
|
||||
entry.disconnect(entry.editing_done_id)
|
||||
self._key_up(path, store, column)
|
||||
self._key_up(path, model, column)
|
||||
entry.editing_done_id = entry.connect('editing_done',
|
||||
self.on_editing_done)
|
||||
elif event.keyval == gtk.keysyms.Down:
|
||||
entry.disconnect(entry.editing_done_id)
|
||||
self._key_down(path, store, column)
|
||||
self._key_down(path, model, column)
|
||||
entry.editing_done_id = entry.connect('editing_done',
|
||||
self.on_editing_done)
|
||||
elif event.keyval in (gtk.keysyms.Return,):
|
||||
@@ -211,22 +204,22 @@ class EditableTreeView(gtk.TreeView):
|
||||
break
|
||||
entry.disconnect(entry.editing_done_id)
|
||||
if self.editable == 'top':
|
||||
new_path = self._key_up(path, store, col)
|
||||
new_path = self._key_up(path, model, col)
|
||||
else:
|
||||
new_path = self._key_down(path, store, column)
|
||||
new_path = self._key_down(path, model, column)
|
||||
entry.editing_done_id = entry.connect('editing_done',
|
||||
self.on_editing_done)
|
||||
elif event.keyval == gtk.keysyms.Escape:
|
||||
if model.id < 0:
|
||||
store.remove(store.get_iter(path))
|
||||
self.screen.current_model = False
|
||||
if record.id < 0:
|
||||
model.remove(model.get_iter(path))
|
||||
self.screen.current_record = False
|
||||
if not path[0]:
|
||||
self.screen.current_model = False
|
||||
if path[0] == len(self.screen.models.models) \
|
||||
self.screen.current_record = False
|
||||
if path[0] == len(self.screen.group) \
|
||||
and path[0]:
|
||||
path = (path[0] - 1,)
|
||||
self.screen.display()
|
||||
if len(self.screen.models.models):
|
||||
if len(self.screen.group):
|
||||
self.set_cursor(path, column, False)
|
||||
elif event.keyval in (gtk.keysyms.F3, gtk.keysyms.F2):
|
||||
if isinstance(entry, gtk.Entry):
|
||||
@@ -234,9 +227,8 @@ class EditableTreeView(gtk.TreeView):
|
||||
else:
|
||||
value = entry.get_active_text()
|
||||
entry.disconnect(entry.editing_done_id)
|
||||
newval = self.on_open_remote(model, column.name,
|
||||
create=(event.keyval==gtk.keysyms.F3),
|
||||
value=value)
|
||||
newval = self.on_open_remote(record, column.name,
|
||||
create=(event.keyval==gtk.keysyms.F3), value=value)
|
||||
if isinstance(entry, gtk.Entry):
|
||||
entry.set_text(newval)
|
||||
else:
|
||||
@@ -245,31 +237,31 @@ class EditableTreeView(gtk.TreeView):
|
||||
self.on_editing_done)
|
||||
self.set_cursor(path, column, True)
|
||||
else:
|
||||
modelfield = model[column.name]
|
||||
field = record[column.name]
|
||||
if isinstance(entry, gtk.Entry):
|
||||
entry.set_max_length(int(modelfield.attrs.get('size', 0)))
|
||||
# store in the model the entry widget to get the value in set_value
|
||||
modelfield.editabletree_entry = entry
|
||||
model.modified = True
|
||||
model.modified_fields.setdefault(column.name)
|
||||
entry.set_max_length(int(field.attrs.get('size', 0)))
|
||||
# store in the record the entry widget to get the value in set_value
|
||||
field.editabletree_entry = entry
|
||||
record.modified = True
|
||||
record.modified_fields.setdefault(column.name)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _key_down(self, path, store, column):
|
||||
if path[0] == len(store) - 1 and self.editable == 'bottom':
|
||||
def _key_down(self, path, model, column):
|
||||
if path[0] == len(model) - 1 and self.editable == 'bottom':
|
||||
self.on_create_line()
|
||||
new_path = (path[0] + 1) % len(store)
|
||||
new_path = (path[0] + 1) % len(model)
|
||||
self.set_cursor(new_path, column, True)
|
||||
self.scroll_to_cell(new_path)
|
||||
return new_path
|
||||
|
||||
def _key_up(self, path, store, column):
|
||||
def _key_up(self, path, model, column):
|
||||
if path[0] == 0 and self.editable == 'top':
|
||||
self.on_create_line()
|
||||
new_path = 0
|
||||
else:
|
||||
new_path = (path[0] - 1) % len(store)
|
||||
new_path = (path[0] - 1) % len(model)
|
||||
self.set_cursor(new_path, column, True)
|
||||
self.scroll_to_cell(new_path)
|
||||
return new_path
|
||||
@@ -278,9 +270,9 @@ class EditableTreeView(gtk.TreeView):
|
||||
path, column = self.get_cursor()
|
||||
if not path:
|
||||
return True
|
||||
store = self.get_model()
|
||||
model = store.get_value(store.get_iter(path), 0)
|
||||
model = self.get_model()
|
||||
record = model.get_value(model.get_iter(path), 0)
|
||||
if isinstance(entry, gtk.Entry):
|
||||
self.on_quit_cell(model, column.name, entry.get_text())
|
||||
self.on_quit_cell(record, column.name, entry.get_text())
|
||||
elif isinstance(entry, gtk.ComboBoxEntry):
|
||||
self.on_quit_cell(model, column.name, entry.get_active_text())
|
||||
self.on_quit_cell(record, column.name, entry.get_active_text())
|
||||
@@ -1,23 +1,13 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
import locale
|
||||
import gtk
|
||||
|
||||
from tryton.rpc import RPCProxy
|
||||
from editabletree import EditableTreeView
|
||||
from tryton.gui.window.view_form.view.interface import ParserInterface
|
||||
|
||||
import time
|
||||
|
||||
from tryton.gui.window.view_form.view.form_gtk.many2one import Dialog \
|
||||
as M2ODialog
|
||||
from tryton.gui.window.view_form.view.form_gtk.one2many import Dialog \
|
||||
as O2MDialog
|
||||
from tryton.gui.window.win_search import WinSearch
|
||||
from tryton.gui.window.win_form import WinForm
|
||||
from tryton.gui.window.view_form.screen import Screen
|
||||
from tryton.gui.window.view_form.widget_search.form import _LIMIT
|
||||
|
||||
import tryton.rpc as rpc
|
||||
import datetime
|
||||
from tryton.common import DT_FORMAT, DHM_FORMAT, COLORS, node_attributes, \
|
||||
TRYTON_ICON, HM_FORMAT
|
||||
import tryton.common as common
|
||||
@@ -31,6 +21,10 @@ from tryton.common.cellrendererfloat import CellRendererFloat
|
||||
from tryton.action import Action
|
||||
from tryton.translate import date_format
|
||||
from tryton.pyson import PYSONDecoder
|
||||
import gtk
|
||||
import locale
|
||||
import datetime
|
||||
import time
|
||||
import gettext
|
||||
|
||||
_ = gettext.gettext
|
||||
@@ -60,10 +54,10 @@ def sort_model(column, treeview, screen):
|
||||
else:
|
||||
column.arrow_show = False
|
||||
column.arrow.hide()
|
||||
model = treeview.get_model()
|
||||
if screen.search_count == len(model):
|
||||
store = treeview.get_model()
|
||||
if screen.search_count == len(store):
|
||||
ids = screen.search_filter(only_ids=True)
|
||||
model.sort(ids)
|
||||
store.sort(ids)
|
||||
else:
|
||||
screen.search_filter()
|
||||
|
||||
@@ -73,7 +67,7 @@ class ParserTree(ParserInterface):
|
||||
super(ParserTree, self).__init__(window, parent, attrs, screen)
|
||||
self.treeview = None
|
||||
|
||||
def parse(self, model, root_node, fields):
|
||||
def parse(self, model_name, root_node, fields):
|
||||
dict_widget = {}
|
||||
button_list = []
|
||||
attrs = node_attributes(root_node)
|
||||
@@ -102,11 +96,11 @@ class ParserTree(ParserInterface):
|
||||
bool(int(node_attrs[boolean_fields]))
|
||||
if fname not in fields:
|
||||
continue
|
||||
fields[fname].update(node_attrs)
|
||||
node_attrs.update(fields[fname])
|
||||
fields[fname].attrs.update(node_attrs)
|
||||
node_attrs.update(fields[fname].attrs)
|
||||
cell = CELLTYPES.get(node_attrs.get('widget',
|
||||
fields[fname]['type']))(fname, model,
|
||||
treeview, node_attrs, self.window)
|
||||
fields[fname].attrs['type']))(fname, model_name,
|
||||
treeview, self.window, node_attrs)
|
||||
treeview.cells[fname] = cell
|
||||
renderer = cell.renderer
|
||||
|
||||
@@ -122,15 +116,15 @@ class ParserTree(ParserInterface):
|
||||
renderer.connect_after('editing-started', send_keys,
|
||||
treeview)
|
||||
|
||||
col = gtk.TreeViewColumn(fields[fname]['string'], renderer)
|
||||
col = gtk.TreeViewColumn(fields[fname].attrs['string'], renderer)
|
||||
col.name = fname
|
||||
|
||||
hbox = gtk.HBox(False, 2)
|
||||
label = gtk.Label(fields[fname]['string'])
|
||||
label = gtk.Label(fields[fname].attrs['string'])
|
||||
label.show()
|
||||
help = fields[fname]['string']
|
||||
if fields[fname].get('help'):
|
||||
help += '\n' + fields[fname]['help']
|
||||
help = fields[fname].attrs['string']
|
||||
if fields[fname].attrs.get('help'):
|
||||
help += '\n' + fields[fname].attrs['help']
|
||||
tooltips.set_tip(label, help)
|
||||
tooltips.enable()
|
||||
arrow = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_IN)
|
||||
@@ -141,7 +135,7 @@ class ParserTree(ParserInterface):
|
||||
hbox.show()
|
||||
col.set_widget(hbox)
|
||||
|
||||
col._type = fields[fname]['type']
|
||||
col._type = fields[fname].attrs['type']
|
||||
col.set_cell_data_func(renderer, cell.setter)
|
||||
col.set_clickable(True)
|
||||
twidth = {
|
||||
@@ -158,10 +152,10 @@ class ParserTree(ParserInterface):
|
||||
'many2many': 50,
|
||||
'boolean': 20,
|
||||
}
|
||||
if 'width' in fields[fname]:
|
||||
width = int(fields[fname]['width'])
|
||||
if 'width' in fields[fname].attrs:
|
||||
width = int(fields[fname].attrs['width'])
|
||||
else:
|
||||
width = twidth.get(fields[fname]['type'], 100)
|
||||
width = twidth.get(fields[fname].attrs['type'], 100)
|
||||
col.width = width
|
||||
if width > 0:
|
||||
col.set_fixed_width(width)
|
||||
@@ -171,30 +165,30 @@ class ParserTree(ParserInterface):
|
||||
col.connect('clicked', sort_model, treeview, self.screen)
|
||||
col.set_resizable(True)
|
||||
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
||||
col.set_visible(not fields[fname].get('tree_invisible', False))
|
||||
col.set_visible(not fields[fname].attrs.get('tree_invisible', False))
|
||||
i = treeview.append_column(col)
|
||||
if 'sum' in fields[fname] and fields[fname]['type'] \
|
||||
if 'sum' in fields[fname].attrs and fields[fname].attrs['type'] \
|
||||
in ('integer', 'biginteger', 'float', 'numeric',
|
||||
'float_time'):
|
||||
label = gtk.Label()
|
||||
label.set_use_markup(True)
|
||||
label_str = fields[fname]['sum'] + ': '
|
||||
label_bold = bool(int(fields[fname].get('sum_bold', 0)))
|
||||
label_str = fields[fname].attrs['sum'] + ': '
|
||||
label_bold = bool(int(fields[fname].attrs.get('sum_bold', 0)))
|
||||
if label_bold:
|
||||
label.set_markup('<b>%s</b>' % label_str)
|
||||
else:
|
||||
label.set_markup(label_str)
|
||||
label_sum = gtk.Label()
|
||||
label_sum.set_use_markup(True)
|
||||
if isinstance(fields[fname].get('digits'), str):
|
||||
if isinstance(fields[fname].attrs.get('digits'), str):
|
||||
digits = 2
|
||||
else:
|
||||
digits = fields[fname].get('digits', (16, 2))[1]
|
||||
digits = fields[fname].attrs.get('digits', (16, 2))[1]
|
||||
dict_widget[i] = (fname, label, label_sum, digits,
|
||||
label_bold)
|
||||
elif node.localName == 'button':
|
||||
#TODO add shortcut
|
||||
cell = Button(treeview, node_attrs, self.window, self.screen)
|
||||
cell = Button(treeview, self.window, self.screen, node_attrs)
|
||||
button_list.append(cell)
|
||||
renderer = cell.renderer
|
||||
string = node_attrs.get('string', _('Unknown'))
|
||||
@@ -239,24 +233,24 @@ class ParserTree(ParserInterface):
|
||||
|
||||
class Char(object):
|
||||
|
||||
def __init__(self, field_name, model, treeview=None, attrs=None,
|
||||
window=None):
|
||||
def __init__(self, field_name, model_name, treeview, window, attrs=None):
|
||||
super(Char, self).__init__()
|
||||
self.field_name = field_name
|
||||
self.model = model
|
||||
self.model_name = model_name
|
||||
self.attrs = attrs or {}
|
||||
self.renderer = CellRendererText()
|
||||
self.treeview = treeview
|
||||
self.window = window
|
||||
|
||||
def setter(self, column, cell, store, iter):
|
||||
model = store.get_value(iter, 0)
|
||||
text = self.get_textual_value(model)
|
||||
record = store.get_value(iter, 0)
|
||||
text = self.get_textual_value(record)
|
||||
|
||||
if isinstance(cell, CellRendererToggle):
|
||||
cell.set_active(bool(text))
|
||||
else:
|
||||
cell.set_property('text', text)
|
||||
fg_color = self.get_color(model)
|
||||
fg_color = self.get_color(record)
|
||||
cell.set_property('foreground', fg_color)
|
||||
if fg_color == 'black':
|
||||
cell.set_property('foreground-set', False)
|
||||
@@ -274,22 +268,22 @@ class Char(object):
|
||||
and self.treeview.editable:
|
||||
states = ('readonly', 'required', 'invisible')
|
||||
|
||||
field = model[self.field_name]
|
||||
field.state_set(model, states=states)
|
||||
invisible = field.get_state_attrs(model).get('invisible', False)
|
||||
field = record[self.field_name]
|
||||
field.state_set(record, states=states)
|
||||
invisible = field.get_state_attrs(record).get('invisible', False)
|
||||
cell.set_property('visible', not invisible)
|
||||
|
||||
if hasattr(self.treeview, 'editable') \
|
||||
and self.treeview.editable:
|
||||
readonly = field.get_state_attrs(model).get('readonly', False)
|
||||
readonly = field.get_state_attrs(record).get('readonly', False)
|
||||
if invisible:
|
||||
readonly = True
|
||||
|
||||
if not isinstance(cell, CellRendererToggle):
|
||||
bg_color = 'white'
|
||||
if not field.get_state_attrs(model).get('valid', True):
|
||||
if not field.get_state_attrs(record).get('valid', True):
|
||||
bg_color = COLORS.get('invalid', 'white')
|
||||
elif bool(int(field.get_state_attrs(model).get('required', 0))):
|
||||
elif bool(int(field.get_state_attrs(record).get('required', 0))):
|
||||
bg_color = COLORS.get('required', 'white')
|
||||
cell.set_property('background', bg_color)
|
||||
if bg_color == 'white':
|
||||
@@ -308,50 +302,50 @@ class Char(object):
|
||||
|
||||
cell.set_property('xalign', align)
|
||||
|
||||
def get_color(self, model):
|
||||
return model.expr_eval(self.treeview.colors, check_load=False)
|
||||
def get_color(self, record):
|
||||
return record.expr_eval(self.treeview.colors, check_load=False)
|
||||
|
||||
def open_remote(self, model, create, changed=False, text=None):
|
||||
def open_remote(self, record, create, changed=False, text=None):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_textual_value(self, model):
|
||||
return model[self.field_name].get_client(model) or ''
|
||||
def get_textual_value(self, record):
|
||||
return record[self.field_name].get_client(record) or ''
|
||||
|
||||
def value_from_text(self, model, text):
|
||||
def value_from_text(self, record, text):
|
||||
return text
|
||||
|
||||
class Int(Char):
|
||||
|
||||
def __init__(self, field_name, model, treeview=None, attrs=None,
|
||||
window=None):
|
||||
super(Int, self).__init__(field_name, model, treeview=treeview,
|
||||
attrs=attrs, window=window)
|
||||
def __init__(self, field_name, model_name, treeview, window, attrs=None):
|
||||
super(Int, self).__init__(field_name, model_name, treeview, window,
|
||||
attrs=attrs)
|
||||
self.renderer = CellRendererInteger()
|
||||
|
||||
def value_from_text(self, model, text):
|
||||
def value_from_text(self, record, text):
|
||||
return int(text)
|
||||
|
||||
def get_textual_value(self, model):
|
||||
def get_textual_value(self, record):
|
||||
return locale.format('%d',
|
||||
model[self.field_name].get_client(model) or 0, True)
|
||||
record[self.field_name].get_client(record) or 0, True)
|
||||
|
||||
class Boolean(Int):
|
||||
|
||||
def __init__(self, *args):
|
||||
super(Boolean, self).__init__(*args)
|
||||
def __init__(self, field_name, model_name, treeview, window, attrs=None):
|
||||
super(Boolean, self).__init__(field_name, model_name, treeview, window,
|
||||
attrs=attrs)
|
||||
self.renderer = CellRendererToggle()
|
||||
self.renderer.connect('toggled', self._sig_toggled)
|
||||
|
||||
def get_textual_value(self, model):
|
||||
return model[self.field_name].get_client(model)
|
||||
def get_textual_value(self, record):
|
||||
return record[self.field_name].get_client(record)
|
||||
|
||||
def _sig_toggled(self, renderer, path):
|
||||
store = self.treeview.get_model()
|
||||
model = store.get_value(store.get_iter(path), 0)
|
||||
field = model[self.field_name]
|
||||
if not field.get_state_attrs(model).get('readonly', False):
|
||||
value = model[self.field_name].get_client(model)
|
||||
model[self.field_name].set_client(model, int(not value))
|
||||
record = store.get_value(store.get_iter(path), 0)
|
||||
field = record[self.field_name]
|
||||
if not field.get_state_attrs(record).get('readonly', False):
|
||||
value = record[self.field_name].get_client(record)
|
||||
record[self.field_name].set_client(record, int(not value))
|
||||
self.treeview.set_cursor(path)
|
||||
return True
|
||||
|
||||
@@ -359,24 +353,20 @@ class Boolean(Int):
|
||||
class Date(Char):
|
||||
server_format = DT_FORMAT
|
||||
|
||||
def __init__(self, field_name, model, treeview=None, attrs=None,
|
||||
window=None):
|
||||
def __init__(self, field_name, model_name, treeview, window, attrs=None):
|
||||
super(Date, self).__init__(field_name, model_name, treeview, window,
|
||||
attrs=attrs)
|
||||
self.display_format = date_format()
|
||||
self.field_name = field_name
|
||||
self.model = model
|
||||
self.attrs = attrs or {}
|
||||
self.renderer = CellRendererDate(self.display_format)
|
||||
self.treeview = treeview
|
||||
self.window = window
|
||||
|
||||
def get_textual_value(self, model):
|
||||
value = model[self.field_name].get_client(model)
|
||||
def get_textual_value(self, record):
|
||||
value = record[self.field_name].get_client(record)
|
||||
if not value:
|
||||
return ''
|
||||
date = datetime.date(*time.strptime(value, self.server_format)[:3])
|
||||
return common.datetime_strftime(date, self.display_format)
|
||||
|
||||
def value_from_text(self, model, text):
|
||||
def value_from_text(self, record, text):
|
||||
if not text:
|
||||
return False
|
||||
try:
|
||||
@@ -389,14 +379,13 @@ class Date(Char):
|
||||
class Datetime(Date):
|
||||
server_format = DHM_FORMAT
|
||||
|
||||
def __init__(self, field_name, model, treeview=None, attrs=None,
|
||||
window=None):
|
||||
super(Datetime, self).__init__(field_name, model,
|
||||
treeview=treeview, attrs=attrs, window=window)
|
||||
def __init__(self, field_name, model_name, treeview, window, attrs=None):
|
||||
super(Datetime, self).__init__(field_name, model_name, treeview,
|
||||
window, attrs=attrs)
|
||||
self.display_format = date_format() + ' ' + HM_FORMAT
|
||||
|
||||
def get_textual_value(self, model):
|
||||
value = model[self.field_name].get_client(model)
|
||||
def get_textual_value(self, record):
|
||||
value = record[self.field_name].get_client(record)
|
||||
if not value:
|
||||
return ''
|
||||
date = datetime.datetime(*time.strptime(value,
|
||||
@@ -413,7 +402,7 @@ class Datetime(Date):
|
||||
pass
|
||||
return common.datetime_strftime(date, self.display_format)
|
||||
|
||||
def value_from_text(self, model, text):
|
||||
def value_from_text(self, record, text):
|
||||
if not text:
|
||||
return False
|
||||
try:
|
||||
@@ -436,30 +425,29 @@ class Datetime(Date):
|
||||
|
||||
class Float(Char):
|
||||
|
||||
def __init__(self, field_name, model, treeview=None, attrs=None,
|
||||
window=None):
|
||||
super(Float, self).__init__(field_name, model, treeview=treeview,
|
||||
attrs=attrs, window=window)
|
||||
def __init__(self, field_name, model_name, treeview, window, attrs=None):
|
||||
super(Float, self).__init__(field_name, model_name, treeview, window,
|
||||
attrs=attrs)
|
||||
self.renderer = CellRendererFloat()
|
||||
|
||||
def setter(self, column, cell, store, iter):
|
||||
super(Float, self).setter(column, cell, store, iter)
|
||||
model = store.get_value(iter, 0)
|
||||
record = store.get_value(iter, 0)
|
||||
if isinstance(self.attrs.get('digits'), str):
|
||||
digits = model.expr_eval(self.attrs['digits'])
|
||||
digits = record.expr_eval(self.attrs['digits'])
|
||||
else:
|
||||
digits = self.attrs.get('digits', (16, 2))
|
||||
cell.digits = digits
|
||||
|
||||
def get_textual_value(self, model):
|
||||
def get_textual_value(self, record):
|
||||
if isinstance(self.attrs.get('digits'), str):
|
||||
digit = model.expr_eval(self.attrs['digits'])[1]
|
||||
digit = record.expr_eval(self.attrs['digits'])[1]
|
||||
else:
|
||||
digit = self.attrs.get('digits', (16, 2))[1]
|
||||
return locale.format('%.'+str(digit)+'f',
|
||||
model[self.field_name].get_client(model) or 0.0, True)
|
||||
record[self.field_name].get_client(record) or 0.0, True)
|
||||
|
||||
def value_from_text(self, model, text):
|
||||
def value_from_text(self, record, text):
|
||||
try:
|
||||
return locale.atof(text)
|
||||
except:
|
||||
@@ -468,72 +456,71 @@ class Float(Char):
|
||||
|
||||
class FloatTime(Char):
|
||||
|
||||
def __init__(self, field_name, model, treeview=None, attrs=None,
|
||||
window=None):
|
||||
super(FloatTime, self).__init__(field_name, model, treeview=treeview,
|
||||
attrs=attrs, window=window)
|
||||
def __init__(self, field_name, model_name, treeview, window, attrs=None):
|
||||
super(FloatTime, self).__init__(field_name, model_name, treeview,
|
||||
window, attrs=attrs)
|
||||
self.conv = None
|
||||
if attrs and attrs.get('float_time'):
|
||||
self.conv = rpc.CONTEXT.get(attrs['float_time'])
|
||||
|
||||
def get_textual_value(self, model):
|
||||
val = model[self.field_name].get_client(model)
|
||||
def get_textual_value(self, record):
|
||||
val = record[self.field_name].get_client(record)
|
||||
return common.float_time_to_text(val, self.conv)
|
||||
|
||||
def value_from_text(self, model, text):
|
||||
def value_from_text(self, record, text):
|
||||
return common.text_to_float_time(text, self.conv)
|
||||
|
||||
class M2O(Char):
|
||||
|
||||
def value_from_text(self, model, text):
|
||||
modelfield = model.mgroup.mfields[self.field_name]
|
||||
if not text and not modelfield.get_state_attrs(
|
||||
model)['required']:
|
||||
def value_from_text(self, record, text):
|
||||
field = record.group.fields[self.field_name]
|
||||
if not text and not field.get_state_attrs(
|
||||
record)['required']:
|
||||
return False
|
||||
|
||||
relation = model[self.field_name].attrs['relation']
|
||||
rpc_relation = RPCProxy(relation)
|
||||
|
||||
domain = model[self.field_name].domain_get(model)
|
||||
context = model[self.field_name].context_get(model)
|
||||
|
||||
relation = record[self.field_name].attrs['relation']
|
||||
domain = record[self.field_name].domain_get(record)
|
||||
context = record[self.field_name].context_get(record)
|
||||
if text:
|
||||
dom = [('rec_name', 'ilike', '%' + text + '%'),
|
||||
domain]
|
||||
else:
|
||||
dom = domain
|
||||
args = ('model', relation, 'search', dom, 0, None, None,
|
||||
context)
|
||||
try:
|
||||
if text:
|
||||
dom = [('rec_name', 'ilike', '%' + text + '%'),
|
||||
domain]
|
||||
else:
|
||||
dom = domain
|
||||
ids = rpc_relation.search(dom, 0, None, None, context)
|
||||
ids = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
return '???'
|
||||
ids = common.process_exception(exception, self.window, *args)
|
||||
if not ids:
|
||||
return '???'
|
||||
if len(ids) != 1:
|
||||
return self.search_remote(relation, ids,
|
||||
domain=domain, context=context)[0]
|
||||
return ids[0]
|
||||
|
||||
def open_remote(self, model, create=True, changed=False, text=None):
|
||||
modelfield = model.mgroup.mfields[self.field_name]
|
||||
relation = modelfield.attrs['relation']
|
||||
def open_remote(self, record, create=True, changed=False, text=None):
|
||||
field = record.group.fields[self.field_name]
|
||||
relation = field.attrs['relation']
|
||||
|
||||
domain = modelfield.domain_get(model)
|
||||
context = modelfield.context_get(model)
|
||||
domain = field.domain_get(record)
|
||||
context = field.context_get(record)
|
||||
if create:
|
||||
obj_id = None
|
||||
elif not changed:
|
||||
obj_id = modelfield.get(model)
|
||||
obj_id = field.get(record)
|
||||
else:
|
||||
rpc_relation = RPCProxy(relation)
|
||||
|
||||
if text:
|
||||
dom = [('rec_name', 'ilike', '%' + text + '%'), domain]
|
||||
else:
|
||||
dom = domain
|
||||
args = ('model', relation, 'search', dom, 0, None, None, context)
|
||||
try:
|
||||
if text:
|
||||
dom = [('rec_name', 'ilike', '%' + text + '%'), domain]
|
||||
else:
|
||||
dom = domain
|
||||
ids = rpc_relation.search(dom, 0, None, None, context)
|
||||
ids = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
return False, False
|
||||
ids = common.process_exception(exception, self.window, *args)
|
||||
if not ids:
|
||||
return False, False
|
||||
if len(ids) == 1:
|
||||
return True, ids[0]
|
||||
searched = self.search_remote(relation, ids, domain=domain,
|
||||
@@ -541,29 +528,41 @@ class M2O(Char):
|
||||
if searched[0]:
|
||||
return True, searched
|
||||
return False, False
|
||||
dia = M2ODialog(relation, obj_id, domain=domain, context=context,
|
||||
window=self.window)
|
||||
res, value = dia.run()
|
||||
dia.destroy()
|
||||
if res:
|
||||
screen = Screen(relation, self.window, domain=domain, context=context,
|
||||
view_type=['form'])
|
||||
if obj_id:
|
||||
screen.load([obj_id])
|
||||
win = WinForm(screen, self.window)
|
||||
else:
|
||||
win = WinForm(screen, self.window, new=True)
|
||||
value = False
|
||||
while win.run():
|
||||
if screen.save_current():
|
||||
value = (screen.current_record.id,
|
||||
screen.current_record.rec_name())
|
||||
break
|
||||
else:
|
||||
screen.display()
|
||||
win.destroy()
|
||||
if value:
|
||||
return True, value
|
||||
else:
|
||||
return False, False
|
||||
|
||||
def search_remote(self, relation, ids=None, domain=None, context=None):
|
||||
rpc_relation = RPCProxy(relation)
|
||||
|
||||
win = WinSearch(relation, sel_multi=False, ids=ids, context=context,
|
||||
domain=domain, parent=self.window)
|
||||
found = win.run()
|
||||
if found:
|
||||
arg = ('model', relation, 'read', found[0], ['rec_name'],
|
||||
context)
|
||||
try:
|
||||
name = rpc_relation.read(found[0], ['rec_name'],
|
||||
context)['rec_name']
|
||||
return found[0], name
|
||||
res = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
return False, None
|
||||
res = common.process_exception(exception, self.window, *args)
|
||||
if not res:
|
||||
return False, None
|
||||
return found[0], res['rec_name']
|
||||
else:
|
||||
return False, None
|
||||
|
||||
@@ -579,24 +578,25 @@ class O2M(Char):
|
||||
super(O2M, self).setter(column, cell, store, iter)
|
||||
cell.set_property('xalign', 0.5)
|
||||
|
||||
def get_textual_value(self, model):
|
||||
return '( ' + str(len(model[self.field_name].\
|
||||
get_client(model).models)) + ' )'
|
||||
def get_textual_value(self, record):
|
||||
return '( ' + str(len(record[self.field_name].\
|
||||
get_client(record))) + ' )'
|
||||
|
||||
def value_from_text(self, model, text):
|
||||
def value_from_text(self, record, text):
|
||||
pass
|
||||
|
||||
def open_remote(self, model, create=True, changed=False, text=None):
|
||||
models = model.value[self.field_name]
|
||||
modelfield = model.mgroup.mfields[self.field_name]
|
||||
relation = modelfield.attrs['relation']
|
||||
context = modelfield.context_get(model)
|
||||
def open_remote(self, record, create=True, changed=False, text=None):
|
||||
group = record.value[self.field_name]
|
||||
field = record.group.fields[self.field_name]
|
||||
relation = field.attrs['relation']
|
||||
context = field.context_get(record)
|
||||
|
||||
dia = O2MDialog(relation, parent=model, model=models,
|
||||
attrs=modelfield.attrs, default_get_ctx=context,
|
||||
window=self.window)
|
||||
res, value = dia.run()
|
||||
dia.destroy()
|
||||
screen = Screen(relation, self.window, view_type=['tree', 'form'],
|
||||
exclude_field=field.attrs.get('relation_field'))
|
||||
screen.group = group
|
||||
win = WinForm(screen, self.window, view_type='tree', context=context)
|
||||
win.run()
|
||||
win.destroy()
|
||||
return False, False
|
||||
|
||||
|
||||
@@ -606,53 +606,55 @@ class M2M(Char):
|
||||
super(M2M, self).setter(column, cell, store, iter)
|
||||
cell.set_property('xalign', 0.5)
|
||||
|
||||
def get_textual_value(self, model):
|
||||
return '( ' + str(len(model[self.field_name].\
|
||||
get_client(model).models)) + ' )'
|
||||
def get_textual_value(self, record):
|
||||
return '( ' + str(len(record[self.field_name].\
|
||||
get_client(record))) + ' )'
|
||||
|
||||
def value_from_text(self, model, text):
|
||||
def value_from_text(self, record, text):
|
||||
if not text:
|
||||
return []
|
||||
if not (text[0] != '('):
|
||||
return model[self.field_name].get(model)
|
||||
relation = model[self.field_name].attrs['relation']
|
||||
rpc_relation = RPCProxy(relation)
|
||||
domain = model[self.field_name].domain_get(model)
|
||||
context = model[self.field_name].context_get(model)
|
||||
return record[self.field_name].get(record)
|
||||
field = record[self.field_name]
|
||||
relation = field.attrs['relation']
|
||||
domain = field.domain_get(record)
|
||||
context = field.context_get(record)
|
||||
if text:
|
||||
dom = [('rec_name', 'ilike', '%' + text + '%'),
|
||||
domain]
|
||||
else:
|
||||
dom = domain
|
||||
args = ('model', relation, 'search', dom, 0, _LIMIT, None, context)
|
||||
try:
|
||||
if text:
|
||||
dom = [('rec_name', 'ilike', '%' + text + '%'),
|
||||
domain]
|
||||
else:
|
||||
dom = domain
|
||||
ids = rpc_relation.search(dom, 0, _LIMIT, None, context)
|
||||
ids = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
return []
|
||||
ids = common.process_exception(exception, self.window, *args)
|
||||
if ids is False:
|
||||
return []
|
||||
win = WinSearch(relation, sel_multi=True, ids=ids, context=context,
|
||||
domain=domain, parent=self.window)
|
||||
found = win.run()
|
||||
return found or []
|
||||
|
||||
def open_remote(self, model, create=True, changed=False, text=None):
|
||||
modelfield = model[self.field_name]
|
||||
relation = modelfield.attrs['relation']
|
||||
|
||||
rpc_relation = RPCProxy(relation)
|
||||
context = model[self.field_name].context_get(model)
|
||||
domain = model[self.field_name].domain_get(model)
|
||||
def open_remote(self, record, create=True, changed=False, text=None):
|
||||
field = record[self.field_name]
|
||||
relation = field.attrs['relation']
|
||||
context = field.context_get(record)
|
||||
domain = field.domain_get(record)
|
||||
if create:
|
||||
if text and len(text) and text[0] != '(':
|
||||
domain.append(('name', '=', text))
|
||||
args = ('model', relation, 'search', domain)
|
||||
try:
|
||||
ids = rpc_relation.search(domain)
|
||||
ids = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
return False, None
|
||||
ids = common.process_exception(exception, self.window, *args)
|
||||
if ids is False:
|
||||
return False, None
|
||||
if ids and len(ids)==1:
|
||||
return True, ids
|
||||
else:
|
||||
ids = [x.id for x in model[self.field_name].get_client(model)]
|
||||
ids = [x.id for x in field.get_client(record)]
|
||||
win = WinSearch(relation, sel_multi=True, ids=ids, context=context,
|
||||
domain=domain, parent=self.window)
|
||||
found = win.run()
|
||||
@@ -670,21 +672,22 @@ class Selection(Char):
|
||||
selection = self.attrs.get('selection', [])[:]
|
||||
self.selection = selection[:]
|
||||
if 'relation' in self.attrs:
|
||||
args = ('model', self.attrs['relation'], 'search_read',
|
||||
self.attrs.get('domain', []), 0, None, None, rpc.CONTEXT,
|
||||
['rec_name'])
|
||||
try:
|
||||
result = rpc.execute('model',
|
||||
self.attrs['relation'], 'search_read',
|
||||
self.attrs.get('domain', []),
|
||||
0, None, None, rpc.CONTEXT, ['rec_name'])
|
||||
selection = [(x['id'], x['rec_name']) for x in result]
|
||||
result = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
selection = []
|
||||
result = common.process_exception(exception, self.window, *args)
|
||||
if not result:
|
||||
result = []
|
||||
selection = [(x['id'], x['rec_name']) for x in result]
|
||||
self.selection = selection[:]
|
||||
else:
|
||||
if not isinstance(selection, (list, tuple)):
|
||||
try:
|
||||
selection = rpc.execute('model',
|
||||
self.model, selection, rpc.CONTEXT)
|
||||
self.model_name, selection, rpc.CONTEXT)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
selection = []
|
||||
@@ -710,13 +713,13 @@ class Selection(Char):
|
||||
self.renderer.set_property('model', selection_data)
|
||||
self.renderer.set_property('text-column', 1)
|
||||
|
||||
def get_textual_value(self, model):
|
||||
value = model[self.field_name].get(model)
|
||||
def get_textual_value(self, record):
|
||||
value = record[self.field_name].get(record)
|
||||
if isinstance(value, (list, tuple)):
|
||||
value = value[0]
|
||||
return dict(self.selection).get(value, '')
|
||||
|
||||
def value_from_text(self, model, text):
|
||||
def value_from_text(self, record, text):
|
||||
res = False
|
||||
for val, txt in self._selection:
|
||||
if txt[:len(text)].lower() == text.lower():
|
||||
@@ -728,16 +731,15 @@ class Selection(Char):
|
||||
|
||||
class Reference(Char):
|
||||
|
||||
def __init__(self, field_name, model, treeview=None, attrs=None,
|
||||
window=None):
|
||||
super(Reference, self).__init__(field_name, model, treeview=treeview,
|
||||
attrs=attrs, window=window)
|
||||
def __init__(self, field_name, model_name, treeview, window, attrs=None):
|
||||
super(Reference, self).__init__(field_name, model_name, treeview,
|
||||
window, attrs=attrs)
|
||||
self._selection = {}
|
||||
selection = attrs.get('selection', [])
|
||||
if not isinstance(selection, (list, tuple)):
|
||||
try:
|
||||
selection = rpc.execute('model',
|
||||
model, selection, rpc.CONTEXT)
|
||||
model_name, selection, rpc.CONTEXT)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
selection = []
|
||||
@@ -745,25 +747,30 @@ class Reference(Char):
|
||||
for i, j in selection:
|
||||
self._selection[i] = str(j)
|
||||
|
||||
def get_textual_value(self, model):
|
||||
value = model[self.field_name].get_client(model)
|
||||
def get_textual_value(self, record):
|
||||
value = record[self.field_name].get_client(record)
|
||||
if not value:
|
||||
model, (obj_id, name) = '', (0, '')
|
||||
else:
|
||||
model, (obj_id, name) = value
|
||||
if model:
|
||||
if not name and obj_id:
|
||||
args = ('model', model, 'read', obj_id, ['rec_name'],
|
||||
rpc.CONTEXT)
|
||||
try:
|
||||
name = RPCProxy(model).read(obj_id, ['rec_name'],
|
||||
rpc.CONTEXT)['rec_name']
|
||||
res = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
res = common.process_exception(exception, self.window,
|
||||
*args)
|
||||
if not res:
|
||||
name = '???'
|
||||
else:
|
||||
name = res['rec_name']
|
||||
return self._selection.get(model, model) + ',' + name
|
||||
else:
|
||||
return name
|
||||
|
||||
def value_from_text(self, model, text):
|
||||
def value_from_text(self, record, text):
|
||||
pass
|
||||
|
||||
|
||||
@@ -775,9 +782,10 @@ class ProgressBar(object):
|
||||
'top_to_bottom': gtk.PROGRESS_TOP_TO_BOTTOM,
|
||||
}
|
||||
|
||||
def __init__(self, field_name, model, treeview=None, attrs=None, window=None):
|
||||
def __init__(self, field_name, model_name, treeview, window, attrs=None):
|
||||
super(ProgressBar, self).__init__()
|
||||
self.field_name = field_name
|
||||
self.model = model
|
||||
self.model_name = model_name
|
||||
self.attrs = attrs or {}
|
||||
self.renderer = gtk.CellRendererProgress()
|
||||
orientation = self.orientations.get(self.attrs.get('orientation',
|
||||
@@ -787,29 +795,29 @@ class ProgressBar(object):
|
||||
self.window = window
|
||||
|
||||
def setter(self, column, cell, store, iter):
|
||||
model = store.get_value(iter, 0)
|
||||
value = float(self.get_textual_value(model) or 0.0)
|
||||
record = store.get_value(iter, 0)
|
||||
value = float(self.get_textual_value(record) or 0.0)
|
||||
cell.set_property('value', value)
|
||||
if isinstance(self.attrs.get('digits'), str):
|
||||
digit = model.expr_eval(self.attrs['digits'])[1]
|
||||
digit = record.expr_eval(self.attrs['digits'])[1]
|
||||
else:
|
||||
digit = self.attrs.get('digits', (16, 2))[1]
|
||||
text = locale.format('%.' + str(digit) + 'f', value, True)
|
||||
cell.set_property('text', text + '%')
|
||||
|
||||
def open_remote(self, model, create, changed=False, text=None):
|
||||
def open_remote(self, record, create, changed=False, text=None):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_textual_value(self, model):
|
||||
return model[self.field_name].get_client(model) or ''
|
||||
def get_textual_value(self, record):
|
||||
return record[self.field_name].get_client(record) or ''
|
||||
|
||||
def value_from_text(self, model, text):
|
||||
def value_from_text(self, record, text):
|
||||
return float(text)
|
||||
|
||||
|
||||
class Button(object):
|
||||
|
||||
def __init__(self, treeview=None, attrs=None, window=None, screen=None):
|
||||
def __init__(self, treeview, windown, screen, attrs=None):
|
||||
super(Button, self).__init__()
|
||||
self.attrs = attrs or {}
|
||||
self.renderer = CellRendererButton(attrs.get('string', _('Unknown')))
|
||||
@@ -823,24 +831,24 @@ class Button(object):
|
||||
if not path:
|
||||
return True
|
||||
store = self.treeview.get_model()
|
||||
model = store.get_value(store.get_iter(path), 0)
|
||||
record = store.get_value(store.get_iter(path), 0)
|
||||
|
||||
state_changes = PYSONDecoder().decode(model.expr_eval(
|
||||
state_changes = PYSONDecoder().decode(record.expr_eval(
|
||||
self.attrs.get('states', {}), check_load=False))
|
||||
if state_changes.get('invisible') \
|
||||
or state_changes.get('readonly'):
|
||||
return True
|
||||
|
||||
self.screen.current_model = model
|
||||
self.screen.current_record = record
|
||||
obj_id = self.screen.save_current()
|
||||
if obj_id:
|
||||
if not self.attrs.get('confirm', False) or \
|
||||
common.sur(self.attrs['confirm'], self.window):
|
||||
button_type = self.attrs.get('type', 'workflow')
|
||||
ctx = rpc.CONTEXT.copy()
|
||||
ctx.update(model.context_get())
|
||||
ctx.update(record.context_get())
|
||||
if button_type == 'workflow':
|
||||
args = ('model', self.screen.name,
|
||||
args = ('model', self.screen.model_name,
|
||||
'workflow_trigger_validate', obj_id,
|
||||
self.attrs['name'], ctx)
|
||||
try:
|
||||
@@ -848,7 +856,7 @@ class Button(object):
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window, *args)
|
||||
elif button_type == 'object':
|
||||
args = ('model', self.screen.name,
|
||||
args = ('model', self.screen.model_name,
|
||||
self.attrs['name'], [obj_id], ctx)
|
||||
try:
|
||||
rpc.execute(*args)
|
||||
@@ -865,7 +873,7 @@ class Button(object):
|
||||
self.window, *args)
|
||||
if action_id:
|
||||
Action.execute(action_id, {
|
||||
'model': self.screen.name,
|
||||
'model': self.screen.model_name,
|
||||
'id': obj_id,
|
||||
'ids': [obj_id],
|
||||
}, self.window, context=ctx)
|
||||
@@ -873,9 +881,6 @@ class Button(object):
|
||||
raise Exception('Unallowed button type')
|
||||
self.screen.reload(writen=True)
|
||||
else:
|
||||
if self.screen.form:
|
||||
self.screen.form.message_info(
|
||||
_('Invalid Form, correct red fields!'))
|
||||
self.screen.display()
|
||||
|
||||
CELLTYPES = {
|
||||
|
||||
@@ -15,6 +15,9 @@ class ScreenContainer(object):
|
||||
self.vbox.pack_end(self.viewport)
|
||||
self.filter_vbox = None
|
||||
self.button = None
|
||||
self.alternate_viewport = gtk.Viewport()
|
||||
self.alternate_viewport.set_shadow_type(gtk.SHADOW_NONE)
|
||||
self.alternate_view = False
|
||||
|
||||
def widget_get(self):
|
||||
return self.vbox
|
||||
@@ -70,6 +73,15 @@ class ScreenContainer(object):
|
||||
self.filter_vbox.hide()
|
||||
|
||||
def set(self, widget):
|
||||
if self.alternate_view:
|
||||
if self.alternate_viewport.get_child():
|
||||
self.alternate_viewport.remove(
|
||||
self.alternate_viewport.get_child())
|
||||
if widget == self.viewport.get_child():
|
||||
self.viewport.remove(self.viewport.get_child())
|
||||
self.alternate_viewport.add(widget)
|
||||
self.alternate_viewport.show_all()
|
||||
return
|
||||
if self.viewport.get_child():
|
||||
self.viewport.remove(self.viewport.get_child())
|
||||
self.viewport.add(widget)
|
||||
|
||||
@@ -36,7 +36,7 @@ class WidgetParse(ParserInterface):
|
||||
widget = PARSERS[node.localName](self.window, self.parent,
|
||||
self.attrs, screen)
|
||||
wid, child, buttons, on_write, notebooks, cursor_widget = \
|
||||
widget.parse(screen.resource, node, fields)
|
||||
widget.parse(screen.model_name, node, fields)
|
||||
screen.set_on_write(on_write)
|
||||
res = PARSERS2[node.localName](self.window, screen, wid, child,
|
||||
buttons, toolbar, notebooks, cursor_widget)
|
||||
|
||||
@@ -14,14 +14,10 @@ import os
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
|
||||
class WinExport(object):
|
||||
"Window export"
|
||||
|
||||
def __init__(self, model, ids, fields, preload=None, parent=None,
|
||||
context=None):
|
||||
if preload is None:
|
||||
preload = []
|
||||
def __init__(self, model, ids, fields, parent=None, context=None):
|
||||
self.dialog = gtk.Dialog(
|
||||
title= _("Export to CSV"),
|
||||
parent=parent,
|
||||
@@ -187,9 +183,6 @@ class WinExport(object):
|
||||
self.model1 = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
|
||||
self.model2 = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
|
||||
|
||||
for i in preload:
|
||||
self.model2.set(self.model2.append(), 0, i[1], 1, i[0])
|
||||
|
||||
self.fields = {}
|
||||
|
||||
def model_populate(fields, prefix_node='', prefix=None,
|
||||
@@ -278,45 +271,64 @@ class WinExport(object):
|
||||
self.model2.clear()
|
||||
|
||||
def fill_predefwin(self):
|
||||
ir_export = rpc.RPCProxy('ir.export')
|
||||
ir_export_line = rpc.RPCProxy('ir.export.line')
|
||||
args = ('model', 'ir.export', 'search',
|
||||
[('resource', '=', self.model)], 0, None, None, rpc.CONTEXT)
|
||||
try:
|
||||
export_ids = ir_export.search([('resource', '=', self.model)])
|
||||
export_ids = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.parent)
|
||||
return
|
||||
for export in ir_export.read(export_ids):
|
||||
try:
|
||||
fields = ir_export_line.read(export['export_fields'])
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.parent)
|
||||
continue
|
||||
self.predef_model.append((
|
||||
export['id'],
|
||||
[f['name'] for f in fields],
|
||||
export_ids = common.process_exception(exception, self.parent,
|
||||
*args)
|
||||
if not export_ids:
|
||||
return
|
||||
args = ('model', 'ir.export', 'read', export_ids, None, rpc.CONTEXT)
|
||||
try:
|
||||
exports = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
exports = common.process_exception(exception, self.parent, *args)
|
||||
if not exports:
|
||||
return
|
||||
args = ('model', 'ir.export.line', 'read',
|
||||
[x['export_fields'] for x in exports], None, rpc.CONTEXT)
|
||||
try:
|
||||
lines = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
lines = common.process_exception(exception, self.parent, *args)
|
||||
if not lines:
|
||||
return
|
||||
id2lines = {}
|
||||
for line in lines:
|
||||
id2lines.setdefault(line['export'], []).append(line)
|
||||
for export in exports:
|
||||
self.predef_model.append((export['id'],
|
||||
[x['name'] for x in id2lines[export['id']]],
|
||||
export['name'],
|
||||
', '.join(self.fields_data[f['name']]['string'] \
|
||||
for f in fields),
|
||||
))
|
||||
','.join(self.fields_data[x['name']]['string']
|
||||
for x in id2lines[export['id']])))
|
||||
self.pref_export.set_model(self.predef_model)
|
||||
|
||||
def add_predef(self, widget):
|
||||
name = common.ask('What is the name of this export?', self.parent)
|
||||
name = common.ask(_('What is the name of this export?'), self.parent)
|
||||
if not name:
|
||||
return
|
||||
ir_export = rpc.RPCProxy('ir.export')
|
||||
iter = self.model2.get_iter_root()
|
||||
fields = []
|
||||
while iter:
|
||||
field_name = self.model2.get_value(iter, 1)
|
||||
fields.append(field_name)
|
||||
iter = self.model2.iter_next(iter)
|
||||
args = ('model', 'ir.export', 'create', {
|
||||
'name': name,
|
||||
'resource': self.model,
|
||||
'export_fields': [('create', {
|
||||
'name': x,
|
||||
}) for x in fields],
|
||||
}, rpc.CONTEXT)
|
||||
try:
|
||||
new_id = ir_export.create({'name' : name, 'resource' : self.model,
|
||||
'export_fields' : [('create', {'name' : f}) for f in fields]})
|
||||
new_id = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.dialog)
|
||||
return
|
||||
new_ids = common.process_exception(exception, self.dialog, *args)
|
||||
if not new_id:
|
||||
return
|
||||
self.predef_model.append((
|
||||
new_id,
|
||||
fields,
|
||||
@@ -331,13 +343,13 @@ class WinExport(object):
|
||||
(model, i) = sel
|
||||
if not i:
|
||||
return None
|
||||
ir_export = rpc.RPCProxy('ir.export')
|
||||
export_id = model.get_value(i, 0)
|
||||
args = ('model', 'ir.export', 'delete', export_id, rpc.CONTEXT)
|
||||
try:
|
||||
ir_export.delete(export_id)
|
||||
rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.dialog)
|
||||
return
|
||||
if not common.process_exception(exception, self.dialog, *args):
|
||||
return
|
||||
for i in range(len(self.predef_model)):
|
||||
if self.predef_model[i][0] == export_id:
|
||||
del self.predef_model[i]
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from tryton.common import TRYTON_ICON
|
||||
import tryton.common as common
|
||||
import gtk
|
||||
import pango
|
||||
import gettext
|
||||
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
class WinForm(object):
|
||||
"Form window"
|
||||
|
||||
def __init__(self, screen, parent, view_type='form', new=False,
|
||||
context=None):
|
||||
|
||||
self.parent = parent
|
||||
self.screen = screen
|
||||
self.context = context
|
||||
self.prev_view = self.screen.current_view
|
||||
self.screen.screen_container.alternate_view = True
|
||||
switch_new = False
|
||||
if view_type == 'form' and not self.screen.current_record:
|
||||
switch_new = True
|
||||
if view_type not in (x.view_type for x in self.screen.views) and \
|
||||
view_type not in self.screen.view_to_load:
|
||||
self.screen.add_view_id(False, view_type, display=True)
|
||||
else:
|
||||
self.screen.switch_view(view_type=view_type)
|
||||
if new and not switch_new:
|
||||
self.screen.new(context=self.context)
|
||||
self.win = gtk.Dialog(_('Link'), parent,
|
||||
gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT)
|
||||
self.win.connect('close', self._sig_close)
|
||||
self.win.set_property('default-width', 760)
|
||||
self.win.set_property('default-height', 500)
|
||||
self.win.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
self.win.set_icon(TRYTON_ICON)
|
||||
self.win.set_has_separator(False)
|
||||
|
||||
self.accel_group = gtk.AccelGroup()
|
||||
self.win.add_accel_group(self.accel_group)
|
||||
|
||||
self.but_cancel = None
|
||||
if new:
|
||||
icon_cancel = gtk.STOCK_CANCEL
|
||||
self.but_cancel = self.win.add_button(icon_cancel,
|
||||
gtk.RESPONSE_CANCEL)
|
||||
|
||||
self.but_ok = self.win.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
self.but_ok.add_accelerator('clicked', self.accel_group,
|
||||
gtk.keysyms.Return, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE)
|
||||
|
||||
self.win.set_default_response(gtk.RESPONSE_OK)
|
||||
|
||||
self.win.set_title(self.screen.current_view.title)
|
||||
|
||||
title = gtk.Label()
|
||||
title.set_use_markup(True)
|
||||
title.modify_font(pango.FontDescription("12"))
|
||||
title.set_label('<b>' + self.screen.current_view.title + '</b>')
|
||||
title.set_padding(20, 3)
|
||||
title.set_alignment(0.0, 0.5)
|
||||
title.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000"))
|
||||
title.show()
|
||||
|
||||
self.info_label = gtk.Label()
|
||||
self.info_label.set_padding(3, 3)
|
||||
self.info_label.set_alignment(1.0, 0.5)
|
||||
|
||||
self.eb_info = gtk.EventBox()
|
||||
self.eb_info.add(self.info_label)
|
||||
self.eb_info.connect('button-release-event',
|
||||
lambda *a: self.message_info(''))
|
||||
|
||||
vbox = gtk.VBox()
|
||||
vbox.pack_start(self.eb_info, expand=True, fill=True, padding=5)
|
||||
vbox.show()
|
||||
|
||||
hbox = gtk.HBox()
|
||||
hbox.pack_start(title, expand=True, fill=True)
|
||||
hbox.pack_start(vbox, expand=False, fill=True, padding=20)
|
||||
hbox.show()
|
||||
|
||||
frame = gtk.Frame()
|
||||
frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
|
||||
frame.add(hbox)
|
||||
frame.show()
|
||||
|
||||
eb = gtk.EventBox()
|
||||
eb.add(frame)
|
||||
eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#ffffff"))
|
||||
eb.show()
|
||||
|
||||
self.win.vbox.pack_start(eb, expand=False, fill=True, padding=3)
|
||||
|
||||
if view_type == 'tree':
|
||||
hbox = gtk.HBox(homogeneous=False, spacing=0)
|
||||
tooltips = common.Tooltips()
|
||||
|
||||
self.but_new = gtk.Button()
|
||||
tooltips.set_tip(self.but_new, _('Create a new record'))
|
||||
self.but_new.connect('clicked', self._sig_new)
|
||||
img_new = gtk.Image()
|
||||
img_new.set_from_stock('tryton-new', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_new.set_alignment(0.5, 0.5)
|
||||
self.but_new.add(img_new)
|
||||
self.but_new.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(self.but_new, expand=False, fill=False)
|
||||
|
||||
self.but_del = gtk.Button()
|
||||
tooltips.set_tip(self.but_del, _('Delete selected record'))
|
||||
self.but_del.connect('clicked', self._sig_remove)
|
||||
img_del = gtk.Image()
|
||||
img_del.set_from_stock('tryton-delete', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_del.set_alignment(0.5, 0.5)
|
||||
self.but_del.add(img_del)
|
||||
self.but_del.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(self.but_del, expand=False, fill=False)
|
||||
|
||||
hbox.pack_start(gtk.VSeparator(), expand=False, fill=True)
|
||||
|
||||
but_pre = gtk.Button()
|
||||
tooltips.set_tip(but_pre, _('Previous'))
|
||||
but_pre.connect('clicked', self._sig_previous)
|
||||
img_pre = gtk.Image()
|
||||
img_pre.set_from_stock('tryton-go-previous', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_pre.set_alignment(0.5, 0.5)
|
||||
but_pre.add(img_pre)
|
||||
but_pre.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(but_pre, expand=False, fill=False)
|
||||
|
||||
self.label = gtk.Label('(0,0)')
|
||||
hbox.pack_start(self.label, expand=False, fill=False)
|
||||
|
||||
but_next = gtk.Button()
|
||||
tooltips.set_tip(but_next, _('Next'))
|
||||
but_next.connect('clicked', self._sig_next)
|
||||
img_next = gtk.Image()
|
||||
img_next.set_from_stock('tryton-go-next', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_next.set_alignment(0.5, 0.5)
|
||||
but_next.add(img_next)
|
||||
but_next.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(but_next, expand=False, fill=False)
|
||||
|
||||
hbox.pack_start(gtk.VSeparator(), expand=False, fill=True)
|
||||
|
||||
but_switch = gtk.Button()
|
||||
tooltips.set_tip(but_switch, _('Switch'))
|
||||
but_switch.connect('clicked', self.switch_view)
|
||||
img_switch = gtk.Image()
|
||||
img_switch.set_from_stock('tryton-fullscreen', gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
img_switch.set_alignment(0.5, 0.5)
|
||||
but_switch.add(img_switch)
|
||||
but_switch.set_relief(gtk.RELIEF_NONE)
|
||||
hbox.pack_start(but_switch, expand=False, fill=False)
|
||||
|
||||
tooltips.enable()
|
||||
|
||||
alignment = gtk.Alignment(1.0)
|
||||
alignment.add(hbox)
|
||||
alignment.show_all()
|
||||
|
||||
self.win.vbox.pack_start(alignment, expand=False, fill=True)
|
||||
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
scroll.set_placement(gtk.CORNER_TOP_LEFT)
|
||||
scroll.set_shadow_type(gtk.SHADOW_NONE)
|
||||
scroll.show()
|
||||
self.win.vbox.pack_start(scroll, expand=True, fill=True)
|
||||
|
||||
scroll.add(self.screen.screen_container.alternate_viewport)
|
||||
|
||||
width, height = self.screen.current_view.widget.size_request()
|
||||
scroll.set_size_request(width, height + 30)
|
||||
|
||||
if view_type == 'tree':
|
||||
self.screen.signal_connect(self, 'record-message', self._sig_label)
|
||||
self.screen.screen_container.alternate_viewport.connect(
|
||||
'key-press-event', self.on_keypress)
|
||||
|
||||
self.screen.display()
|
||||
self.screen.current_view.set_cursor()
|
||||
|
||||
def message_info(self, message, color='red'):
|
||||
if message:
|
||||
self.info_label.set_label(message)
|
||||
self.eb_info.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(
|
||||
COLOR_SCHEMES.get(color, 'white')))
|
||||
self.eb_info.show_all()
|
||||
else:
|
||||
self.info_label.set_label('')
|
||||
self.eb_info.hide()
|
||||
|
||||
def on_keypress(self, widget, event):
|
||||
if (event.keyval == gtk.keysyms.F3) \
|
||||
and self.but_new.get_property('sensitive'):
|
||||
self._sig_new(widget)
|
||||
return False
|
||||
if event.keyval in (gtk.keysyms.Delete, gtk.keysyms.KP_Delete) \
|
||||
and widget == self.screen.screen_container.alternate_viewport:
|
||||
self._sig_remove(widget)
|
||||
return False
|
||||
|
||||
def switch_view(self, widget):
|
||||
self.screen.switch_view()
|
||||
|
||||
def _sig_new(self, widget):
|
||||
self.screen.new(context=self.context)
|
||||
self.screen.current_view.widget.set_sensitive(True)
|
||||
|
||||
def _sig_next(self, widget):
|
||||
self.screen.display_next()
|
||||
|
||||
def _sig_previous(self, widget):
|
||||
self.screen.display_prev()
|
||||
|
||||
def _sig_remove(self, widget):
|
||||
self.screen.remove(delete=True)
|
||||
|
||||
def _sig_activate(self, *args):
|
||||
self._sig_add()
|
||||
self.wid_text.grab_focus()
|
||||
|
||||
def _sig_add(self, *args):
|
||||
domain = []
|
||||
context = rpc.CONTEXT.copy()
|
||||
|
||||
try:
|
||||
if self.wid_text.get_text():
|
||||
dom = [('rec_name', 'ilike',
|
||||
'%' + self.wid_text.get_text() + '%'), domain]
|
||||
else:
|
||||
dom = domain
|
||||
ids = rpc.execute('model', self.attrs['relation'],
|
||||
'search', dom, 0, _LIMIT, None, context)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.window)
|
||||
return False
|
||||
if len(ids) != 1:
|
||||
win = WinSearch(self.attrs['relation'], sel_multi=True, ids=ids,
|
||||
context=context, domain=domain, parent=self.window,
|
||||
views_preload=self.attrs.get('views', {}))
|
||||
ids = win.run()
|
||||
|
||||
res_id = None
|
||||
if ids:
|
||||
res_id = ids[0]
|
||||
self.screen.load(ids, modified=True)
|
||||
self.screen.display(res_id=res_id)
|
||||
if self.screen.current_view:
|
||||
self.screen.current_view.set_cursor()
|
||||
self.wid_text.set_text('')
|
||||
|
||||
def _sig_label(self, screen, signal_data):
|
||||
name = '_'
|
||||
if signal_data[0] >= 0:
|
||||
name = str(signal_data[0] + 1)
|
||||
line = '(%s/%s)' % (name, signal_data[1])
|
||||
self.label.set_text(line)
|
||||
|
||||
def _sig_close(self, widget):
|
||||
if self.screen.current_view:
|
||||
self.screen.current_view.set_value()
|
||||
if self.but_cancel:
|
||||
self.screen.remove(delete=True)
|
||||
elif self.screen.current_record and \
|
||||
not self.screen.current_record.validate():
|
||||
if self.screen.current_view:
|
||||
self.screen.current_view.set_cursor()
|
||||
self.screen.current_view.display()
|
||||
widget.emit_stop_by_name('close')
|
||||
|
||||
def run(self):
|
||||
end = False
|
||||
while not end:
|
||||
res = self.win.run()
|
||||
self.screen.current_view.set_value()
|
||||
end = (res != gtk.RESPONSE_OK) \
|
||||
or (not self.screen.current_record \
|
||||
or self.screen.current_record.validate())
|
||||
if not end:
|
||||
self.screen.current_view.set_cursor()
|
||||
self.screen.display()
|
||||
if self.but_cancel:
|
||||
self.but_cancel.set_label(gtk.STOCK_CLOSE)
|
||||
|
||||
if res == gtk.RESPONSE_OK:
|
||||
return True
|
||||
elif res == gtk.RESPONSE_CANCEL:
|
||||
self.screen.remove(delete=True)
|
||||
return False
|
||||
|
||||
def new(self):
|
||||
self.screen.new(context=self.context)
|
||||
self.screen.current_view.display()
|
||||
self.screen.current_view.set_cursor(new=True)
|
||||
|
||||
def destroy(self):
|
||||
self.screen.screen_container.alternate_view = False
|
||||
viewport = self.screen.screen_container.alternate_viewport
|
||||
if viewport.get_child():
|
||||
viewport.remove(viewport.get_child())
|
||||
self.screen.switch_view(view_type=self.prev_view.view_type)
|
||||
self.screen.signal_unconnect(self)
|
||||
self.win.destroy()
|
||||
self.parent.present()
|
||||
@@ -14,7 +14,7 @@ _ = gettext.gettext
|
||||
class WinImport(object):
|
||||
"Window import"
|
||||
|
||||
def __init__(self, model, fields, preload=None, parent=None):
|
||||
def __init__(self, model, fields, parent=None):
|
||||
self.dialog = gtk.Dialog(
|
||||
title=_("Import from CSV"), parent=parent,
|
||||
flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT
|
||||
@@ -195,9 +195,6 @@ class WinImport(object):
|
||||
gobject.TYPE_STRING)
|
||||
self.model2 = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
|
||||
|
||||
for field in (preload or []):
|
||||
self.model2.set(self.model2.append(), 0, field[1], 1, field[0])
|
||||
|
||||
self.fields = {}
|
||||
self.fields_invert = {}
|
||||
|
||||
@@ -207,28 +204,26 @@ class WinImport(object):
|
||||
fields_order.sort(lambda x, y: -cmp(fields[x].get('string', ''),
|
||||
fields[y].get('string', '')))
|
||||
for field in fields_order:
|
||||
if (fields[field]['type'] not in ('reference',)) \
|
||||
and (not fields[field].get('readonly', False) \
|
||||
or not dict(fields[field].get('states', {}).get(
|
||||
'draft', [('readonly', True)])).get('readonly',
|
||||
True)):
|
||||
self.fields_data[prefix_node+field] = fields[field]
|
||||
st_name = prefix_value+fields[field]['string'] or field
|
||||
if not fields[field].get('readonly', False):
|
||||
self.fields_data[prefix_node + field] = fields[field]
|
||||
st_name = prefix_value + fields[field]['string'] or field
|
||||
node = self.model1.insert(prefix, 0, [st_name,
|
||||
prefix_node+field,
|
||||
(fields[field].get('required', False) and \
|
||||
'#ddddff') or 'white'])
|
||||
self.fields[prefix_node+field] = st_name
|
||||
self.fields_invert[st_name] = prefix_node+field
|
||||
self.fields_invert[st_name] = prefix_node + field
|
||||
if fields[field]['type'] == 'one2many' and level > 0:
|
||||
args = ('model', fields[field]['relation'],
|
||||
'fields_get', None, rpc.CONTEXT)
|
||||
try:
|
||||
fields2 = rpc.execute('model',
|
||||
fields[field]['relation'], 'fields_get',
|
||||
None, rpc.CONTEXT)
|
||||
fields2 = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.dialog)
|
||||
continue
|
||||
model_populate(fields2, prefix_node+field+'/', node,
|
||||
fields2 = common.process_exception(exception,
|
||||
self.dialog, *args)
|
||||
if not fields2:
|
||||
continue
|
||||
model_populate(fields2, prefix_node + field + '/', node,
|
||||
st_name+'/', level-1)
|
||||
model_populate(fields)
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ from tryton.gui.window.view_form.screen import Screen
|
||||
import tryton.gui.window.view_form.widget_search as widget_search
|
||||
from tryton.config import TRYTON_ICON
|
||||
import tryton.common as common
|
||||
from tryton.gui.window.win_form import WinForm
|
||||
|
||||
_ = gettext.gettext
|
||||
|
||||
@@ -47,7 +48,8 @@ class WinSearch(object):
|
||||
self.win.vbox.pack_start(scrollwindow, expand=True, fill=True)
|
||||
|
||||
self.screen = Screen(model, self.win, view_type=['tree'],
|
||||
context=context, views_preload=views_preload)
|
||||
context=context, views_preload=views_preload,
|
||||
row_activate=self.sig_activate)
|
||||
self.view = self.screen.current_view
|
||||
self.view.unset_editable()
|
||||
sel = self.view.widget_tree.get_selection()
|
||||
@@ -61,44 +63,12 @@ class WinSearch(object):
|
||||
viewport.add(self.screen.widget)
|
||||
scrollwindow.add(viewport)
|
||||
scrollwindow.show_all()
|
||||
self.view.widget_tree.connect('row_activated', self.sig_activate)
|
||||
self.view.widget_tree.connect('button_press_event', self.sig_button)
|
||||
|
||||
self.model_name = model
|
||||
|
||||
if 'tree' in views_preload:
|
||||
view_form = views_preload['tree']
|
||||
else:
|
||||
ctx = self.context.copy()
|
||||
ctx.update(rpc.CONTEXT)
|
||||
try:
|
||||
args = ('model', self.model_name, 'fields_view_get',
|
||||
False, 'tree', ctx)
|
||||
view_form = rpc.execute(*args)
|
||||
except Exception, exception:
|
||||
view_form = common.process_exception(exception, self.parent, *args)
|
||||
self.form = widget_search.Form(view_form['arch'], view_form['fields'],
|
||||
model, parent=self.win, call=(self, self.find))
|
||||
|
||||
self.title = _('Search: %s') % self.form.name
|
||||
self.title_results = _('Search: %s (%%d result(s))') % \
|
||||
self.form.name.replace('%', '%%')
|
||||
self.win.set_title(self.title)
|
||||
|
||||
hbox.pack_start(self.form.widget)
|
||||
self.ids = ids
|
||||
if self.ids:
|
||||
self.reload()
|
||||
self.old_search = None
|
||||
self.old_offset = self.old_limit = None
|
||||
if self.ids:
|
||||
self.old_search = []
|
||||
self.old_limit = self.form.get_limit()
|
||||
self.old_offset = self.form.get_offset()
|
||||
|
||||
self.view.widget.show_all()
|
||||
if self.form.focusable:
|
||||
self.form.focusable.grab_focus()
|
||||
if ids:
|
||||
self.screen.load(ids)
|
||||
|
||||
self.win.set_size_request(700, 500)
|
||||
|
||||
@@ -113,37 +83,6 @@ class WinSearch(object):
|
||||
self.win.response(gtk.RESPONSE_OK)
|
||||
return False
|
||||
|
||||
def find(self, *args):
|
||||
limit = self.form.get_limit()
|
||||
offset = self.form.get_offset()
|
||||
if (self.old_search == self.form.value) \
|
||||
and (self.old_limit==limit) \
|
||||
and (self.old_offset==offset):
|
||||
self.win.response(gtk.RESPONSE_OK)
|
||||
return False
|
||||
self.old_offset = offset
|
||||
self.old_limit = limit
|
||||
value = self.form.value
|
||||
value += self.domain
|
||||
try:
|
||||
self.ids = rpc.execute('model', self.model_name, 'search', value,
|
||||
offset, limit, None, rpc.CONTEXT)
|
||||
except Exception, exception:
|
||||
common.process_exception(exception, self.win)
|
||||
return False
|
||||
self.reload()
|
||||
self.old_search = self.form.value
|
||||
self.win.set_title(self.title_results % len(self.ids))
|
||||
return True
|
||||
|
||||
def reload(self):
|
||||
self.screen.clear()
|
||||
self.screen.load(self.ids)
|
||||
sel = self.view.widget_tree.get_selection()
|
||||
|
||||
def sel_ids_get(self):
|
||||
return self.screen.sel_ids_get()
|
||||
|
||||
def destroy(self):
|
||||
self.parent.present()
|
||||
self.screen.destroy()
|
||||
@@ -154,22 +93,24 @@ class WinSearch(object):
|
||||
while not end:
|
||||
button = self.win.run()
|
||||
if button == gtk.RESPONSE_OK:
|
||||
res = self.sel_ids_get()
|
||||
res = self.screen.sel_ids_get()
|
||||
end = True
|
||||
elif button == gtk.RESPONSE_APPLY:
|
||||
end = not self.find()
|
||||
end = not self.screen.search_filter()
|
||||
if end:
|
||||
res = self.sel_ids_get()
|
||||
res = self.screen.sel_ids_get()
|
||||
elif button == gtk.RESPONSE_ACCEPT:
|
||||
from tryton.gui.window.view_form.view.form_gtk.many2one \
|
||||
import Dialog
|
||||
dia = Dialog(self.model_name, window=self.win,
|
||||
domain=self.domain, context=self.context)
|
||||
res, value = dia.run()
|
||||
if res:
|
||||
res = [value[0]]
|
||||
else:
|
||||
res = None
|
||||
res = None
|
||||
screen = Screen(self.model_name, self.win, domain=self.domain,
|
||||
context=self.context, view_type=['form'])
|
||||
win = WinForm(screen, self.win, new=True)
|
||||
while win.run():
|
||||
if screen.save_current():
|
||||
res = [screen.current_record.id]
|
||||
break
|
||||
else:
|
||||
screen.display()
|
||||
win.destroy()
|
||||
end = True
|
||||
else:
|
||||
res = None
|
||||
|
||||
@@ -175,7 +175,7 @@ class Wizard(SignalEvent):
|
||||
|
||||
self.screen = Screen(obj_name, self.window, view_type=[],
|
||||
context=context)
|
||||
self.screen.add_view_custom(arch, fields, display=True)
|
||||
self.screen.add_view(arch, fields, display=True)
|
||||
self.screen.widget.show()
|
||||
|
||||
title = gtk.Label()
|
||||
|
||||
+1
-22
@@ -168,9 +168,8 @@ def logout():
|
||||
|
||||
def context_reload():
|
||||
global CONTEXT, TIMEZONE
|
||||
user = RPCProxy('res.user')
|
||||
try:
|
||||
context = user.get_preferences(True, {})
|
||||
context = execute('model', 'res.user', 'get_preferences', True, {})
|
||||
except:
|
||||
return
|
||||
CONTEXT = {}
|
||||
@@ -224,23 +223,3 @@ def execute(*args):
|
||||
|
||||
def execute_nonblocking(*args):
|
||||
return _execute(False, *args)
|
||||
|
||||
class RPCProxy(object):
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.__attrs = {}
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr not in self.__attrs:
|
||||
self.__attrs[attr] = RPCFunction(self.name, attr)
|
||||
return self.__attrs[attr]
|
||||
|
||||
class RPCFunction(object):
|
||||
|
||||
def __init__(self, name, func_name):
|
||||
self.name = name
|
||||
self.func = func_name
|
||||
|
||||
def __call__(self, *args):
|
||||
return execute('model', self.name, self.func, *args)
|
||||
@@ -24,7 +24,7 @@ class SignalEvent(object):
|
||||
return True
|
||||
|
||||
def signal_unconnect(self, key, signal=None):
|
||||
if not signal:
|
||||
if signal is None:
|
||||
signal = self.__connects.keys()
|
||||
else:
|
||||
signal = [signal]
|
||||
|
||||
@@ -55,7 +55,7 @@ class Dialog(object):
|
||||
val[i] = fields[i]['value']
|
||||
|
||||
self.screen = Screen(obj_name, self.dia, view_type=[], context=context)
|
||||
self.screen.add_view_custom(arch, fields, display=True)
|
||||
self.screen.add_view(arch, fields, display=True)
|
||||
|
||||
title = gtk.Label()
|
||||
title.set_use_markup(True)
|
||||
@@ -110,7 +110,7 @@ class Dialog(object):
|
||||
self.dia.set_title(self.screen.current_view.title)
|
||||
self.dia.show()
|
||||
self.screen.new(default=False)
|
||||
self.screen.current_model.set(val)
|
||||
self.screen.current_record.set(val)
|
||||
self.screen.current_view.set_cursor()
|
||||
|
||||
def run(self, datas=None):
|
||||
@@ -119,7 +119,7 @@ class Dialog(object):
|
||||
while True:
|
||||
res = self.dia.run()
|
||||
self.screen.current_view.set_value()
|
||||
if self.screen.current_model.validate() \
|
||||
if self.screen.current_record.validate() \
|
||||
or (res<0) or (self.states[res]=='end'):
|
||||
break
|
||||
self.screen.display()
|
||||
@@ -206,7 +206,7 @@ class Wizard(object):
|
||||
dia = Dialog(res['arch'], res['fields'], res['state'],
|
||||
res['object'], parent, action=action,
|
||||
size=res['size'], context=ctx)
|
||||
dia.screen.current_model.set(datas['form'])
|
||||
dia.screen.current_record.set(datas['form'])
|
||||
res2 = dia.run(datas['form'])
|
||||
if not res2:
|
||||
break
|
||||
|
||||
Reference in new issue
Block a user