Use explicit callback instead of implicit gtk main iteration in rpc calls
The implicit gtk main iteration leads to bad ordered processing of events. So as explicit is better than implicit, rpc calls that don't need to block until the result use a callback. review3461002
This commit is contained in:
1 parent
ba78ccbaf4
commit
4ca7d9b11a
10 files changed
+276
-248
No files matched your search
+21
-13
@@ -54,23 +54,31 @@ class Action(object):
|
||||
|
||||
@staticmethod
|
||||
def execute(act_id, data, action_type=None, context=None):
|
||||
if not action_type:
|
||||
res = False
|
||||
def get_action_type(actions):
|
||||
try:
|
||||
res, = RPCExecute('model', 'ir.action', 'read', [act_id],
|
||||
['type'], context=context)
|
||||
action, = actions()
|
||||
except RPCException:
|
||||
return
|
||||
if not res:
|
||||
raise Exception('ActionNotFound')
|
||||
action_type = res['type']
|
||||
try:
|
||||
res, = RPCExecute('model', action_type, 'search_read',
|
||||
action_type = action['type']
|
||||
exec_action(action_type)
|
||||
|
||||
def exec_action(action_type):
|
||||
def callback(actions):
|
||||
try:
|
||||
action, = actions()
|
||||
except RPCException:
|
||||
return
|
||||
Action._exec_action(action, data)
|
||||
|
||||
RPCExecute('model', action_type, 'search_read',
|
||||
[('action', '=', act_id)], 0, 1, None, None,
|
||||
context=context)
|
||||
except RPCException:
|
||||
return
|
||||
Action._exec_action(res, data)
|
||||
context=context, callback=callback)
|
||||
|
||||
if not action_type:
|
||||
RPCExecute('model', 'ir.action', 'read', [act_id],
|
||||
['type'], context=context, callback=get_action_type)
|
||||
else:
|
||||
exec_action(action_type)
|
||||
|
||||
@staticmethod
|
||||
def _exec_action(action, data=None, context=None):
|
||||
|
||||
+52
-27
@@ -14,7 +14,6 @@ import unicodedata
|
||||
from functools import partial
|
||||
from tryton.config import CONFIG
|
||||
from tryton.config import TRYTON_ICON, PIXMAPS_DIR
|
||||
import time
|
||||
import sys
|
||||
import xmlrpclib
|
||||
try:
|
||||
@@ -1276,42 +1275,59 @@ class RPCProgress(object):
|
||||
self.error = True
|
||||
self.res = False
|
||||
self.exception = exception
|
||||
return True
|
||||
if not self.res:
|
||||
self.error = True
|
||||
else:
|
||||
if not self.res:
|
||||
self.error = True
|
||||
if self.callback:
|
||||
# Post to GTK queue to be run by the main thread
|
||||
gobject.idle_add(self.process)
|
||||
return True
|
||||
|
||||
def run(self, process_exception_p=True, main_iteration_p=True):
|
||||
session = rpc._SESSION
|
||||
thread.start_new_thread(self.start, ())
|
||||
def run(self, process_exception_p=True, callback=None):
|
||||
self.process_exception_p = process_exception_p
|
||||
self.callback = callback
|
||||
self.session = rpc._SESSION
|
||||
if self.parent.window:
|
||||
watch = gtk.gdk.Cursor(gtk.gdk.WATCH)
|
||||
self.parent.window.set_cursor(watch)
|
||||
|
||||
watch = None
|
||||
i = 0
|
||||
while (not self.res) and (not self.error):
|
||||
i += 1
|
||||
if i > 1:
|
||||
watch = gtk.gdk.Cursor(gtk.gdk.WATCH)
|
||||
self.parent.window.set_cursor(watch)
|
||||
if main_iteration_p:
|
||||
with gtk.gdk.lock:
|
||||
while gtk.events_pending():
|
||||
gtk.main_iteration()
|
||||
time.sleep(0.1)
|
||||
if callback:
|
||||
thread.start_new_thread(self.start, ())
|
||||
return
|
||||
else:
|
||||
self.start()
|
||||
return self.process()
|
||||
|
||||
def process(self):
|
||||
if self.parent.window:
|
||||
self.parent.window.set_cursor(None)
|
||||
if self.exception:
|
||||
if process_exception_p:
|
||||
if self.process_exception_p:
|
||||
def rpc_execute(*args):
|
||||
return RPCProgress('execute',
|
||||
args).run(process_exception_p, main_iteration_p)
|
||||
args).run(self.process_exception_p, self.callback)
|
||||
result = process_exception(self.exception, *self.args,
|
||||
rpc_execute=rpc_execute, session=session)
|
||||
rpc_execute=rpc_execute, session=self.session)
|
||||
if self.callback:
|
||||
return
|
||||
if result is False:
|
||||
raise RPCException(self.exception)
|
||||
return result
|
||||
self.exception = RPCException(self.exception)
|
||||
else:
|
||||
self.exception = None
|
||||
self.res = result
|
||||
else:
|
||||
self.exception
|
||||
|
||||
def return_():
|
||||
if self.exception:
|
||||
raise self.exception
|
||||
return self.res
|
||||
else:
|
||||
return self.res
|
||||
|
||||
if self.callback:
|
||||
self.callback(return_)
|
||||
else:
|
||||
return return_()
|
||||
|
||||
|
||||
def RPCExecute(*args, **kwargs):
|
||||
@@ -1320,8 +1336,17 @@ def RPCExecute(*args, **kwargs):
|
||||
rpc_context.update(kwargs['context'])
|
||||
args = args + (rpc_context,)
|
||||
process_exception = kwargs.get('process_exception', True)
|
||||
main_iteration = kwargs.get('main_iteration', True)
|
||||
return RPCProgress('execute', args).run(process_exception, main_iteration)
|
||||
callback = kwargs.get('callback')
|
||||
return RPCProgress('execute', args).run(process_exception, callback)
|
||||
|
||||
|
||||
def RPCContextReload(callback=None):
|
||||
def update(context):
|
||||
rpc.CONTEXT.clear()
|
||||
rpc.CONTEXT.update(context())
|
||||
if callback:
|
||||
callback()
|
||||
RPCExecute('model', 'res.user', 'get_preferences', True, callback=update)
|
||||
|
||||
|
||||
class Tooltips(object):
|
||||
|
||||
+17
-14
@@ -39,20 +39,23 @@ def update_completion(entry, record, field, model, domain=None):
|
||||
domain = field.domain_get(record)
|
||||
context = field.context_get(record)
|
||||
domain = [('rec_name', 'ilike', '%' + search_text + '%'), domain]
|
||||
try:
|
||||
results = RPCExecute('model', model, 'search_read', domain, 0,
|
||||
CONFIG['client.limit'], None, ['rec_name'], context=context,
|
||||
process_exception=False)
|
||||
except (TrytonError, TrytonServerError):
|
||||
results = []
|
||||
if search_text != entry.get_text().decode('utf-8'):
|
||||
return False
|
||||
completion_model.clear()
|
||||
for result in results:
|
||||
completion_model.append([result['rec_name'], result['id']])
|
||||
completion_model.search_text = search_text
|
||||
# Force display of popup
|
||||
entry.emit('changed')
|
||||
|
||||
def callback(results):
|
||||
try:
|
||||
results = results()
|
||||
except (TrytonError, TrytonServerError):
|
||||
results = []
|
||||
if search_text != entry.get_text().decode('utf-8'):
|
||||
return False
|
||||
completion_model.clear()
|
||||
for result in results:
|
||||
completion_model.append([result['rec_name'], result['id']])
|
||||
completion_model.search_text = search_text
|
||||
# Force display of popup
|
||||
entry.emit('changed')
|
||||
RPCExecute('model', model, 'search_read', domain, 0,
|
||||
CONFIG['client.limit'], None, ['rec_name'], context=context,
|
||||
process_exception=False, callback=callback)
|
||||
return False
|
||||
search_text = entry.get_text().decode('utf-8')
|
||||
gobject.timeout_add(300, update, search_text, domain)
|
||||
+33
-31
@@ -23,10 +23,6 @@ def populate(menu, model, record, title=''):
|
||||
return
|
||||
elif record.id < 0:
|
||||
return
|
||||
try:
|
||||
toolbar = RPCExecute('model', model, 'view_toolbar_get')
|
||||
except RPCException:
|
||||
return
|
||||
|
||||
def load(record):
|
||||
if isinstance(record, (int, long)):
|
||||
@@ -72,31 +68,37 @@ def populate(menu, model, record, title=''):
|
||||
action_menu.append(attachment_item)
|
||||
attachment_item.connect('activate', attachment)
|
||||
|
||||
for atype, icon, label, flavor in (
|
||||
('action', 'tryton-executable', _('Actions...'), None),
|
||||
('relate', 'tryton-go-jump', _('Relate...'), None),
|
||||
('print', 'tryton-print-open', _('Report...'), 'open'),
|
||||
('print', 'tryton-print-email', _('E-Mail...'), 'email'),
|
||||
('print', 'tryton-print', _('Print...'), 'print'),
|
||||
):
|
||||
if len(action_menu):
|
||||
action_menu.append(gtk.SeparatorMenuItem())
|
||||
title_item = gtk.ImageMenuItem(icon)
|
||||
title_item.set_label(label)
|
||||
action_menu.append(title_item)
|
||||
if not toolbar[atype]:
|
||||
title_item.set_sensitive(False)
|
||||
continue
|
||||
submenu = gtk.Menu()
|
||||
title_item.set_submenu(submenu)
|
||||
for action in toolbar[atype]:
|
||||
action = action.copy()
|
||||
item = gtk.MenuItem(action['name'])
|
||||
submenu.append(item)
|
||||
if flavor == 'print':
|
||||
action['direct_print'] = True
|
||||
elif flavor == 'email':
|
||||
action['email_print'] = True
|
||||
item.connect('activate', activate, action, atype)
|
||||
|
||||
def set_toolbar(toolbar):
|
||||
try:
|
||||
toolbar = toolbar()
|
||||
except RPCException:
|
||||
return
|
||||
for atype, icon, label, flavor in (
|
||||
('action', 'tryton-executable', _('Actions...'), None),
|
||||
('relate', 'tryton-go-jump', _('Relate...'), None),
|
||||
('print', 'tryton-print-open', _('Report...'), 'open'),
|
||||
('print', 'tryton-print-email', _('E-Mail...'), 'email'),
|
||||
('print', 'tryton-print', _('Print...'), 'print'),
|
||||
):
|
||||
if len(action_menu):
|
||||
action_menu.append(gtk.SeparatorMenuItem())
|
||||
title_item = gtk.ImageMenuItem(icon)
|
||||
title_item.set_label(label)
|
||||
action_menu.append(title_item)
|
||||
if not toolbar[atype]:
|
||||
title_item.set_sensitive(False)
|
||||
continue
|
||||
submenu = gtk.Menu()
|
||||
title_item.set_submenu(submenu)
|
||||
for action in toolbar[atype]:
|
||||
action = action.copy()
|
||||
item = gtk.MenuItem(action['name'])
|
||||
submenu.append(item)
|
||||
if flavor == 'print':
|
||||
action['direct_print'] = True
|
||||
elif flavor == 'email':
|
||||
action['email_print'] = True
|
||||
item.connect('activate', activate, action, atype)
|
||||
menu.show_all()
|
||||
RPCExecute('model', model, 'view_toolbar_get', callback=set_toolbar)
|
||||
menu.show_all()
|
||||
+66
-57
@@ -16,7 +16,7 @@ import webbrowser
|
||||
import threading
|
||||
|
||||
import tryton.rpc as rpc
|
||||
from tryton.common import RPCExecute, RPCException
|
||||
from tryton.common import RPCExecute, RPCException, RPCContextReload
|
||||
from tryton.config import CONFIG, TRYTON_ICON, get_config_dir
|
||||
import tryton.common as common
|
||||
from tryton.pyson import PYSONDecoder
|
||||
@@ -325,31 +325,35 @@ class Main(object):
|
||||
return False
|
||||
if getattr(gmodel, 'search_text', None) == search_text:
|
||||
return False
|
||||
try:
|
||||
result = RPCExecute('model', 'ir.model', 'global_search',
|
||||
|
||||
def callback(result):
|
||||
try:
|
||||
result = result()
|
||||
except RPCException:
|
||||
result = []
|
||||
if search_text != widget.get_text().decode('utf-8'):
|
||||
return False
|
||||
gmodel.clear()
|
||||
for r in result:
|
||||
_, model, model_name, record_id, record_name, icon = r
|
||||
if icon:
|
||||
text = common.to_xml(record_name)
|
||||
common.ICONFACTORY.register_icon(icon)
|
||||
pixbuf = widget.render_icon(stock_id=icon,
|
||||
size=gtk.ICON_SIZE_BUTTON, detail=None)
|
||||
else:
|
||||
text = '<b>%s:</b>\n %s' % (
|
||||
common.to_xml(model_name),
|
||||
common.to_xml(record_name))
|
||||
pixbuf = None
|
||||
gmodel.append([pixbuf, text, model, record_id])
|
||||
gmodel.search_text = search_text
|
||||
# Force display of popup
|
||||
widget.emit('changed')
|
||||
|
||||
RPCExecute('model', 'ir.model', 'global_search',
|
||||
search_text, CONFIG['client.limit'],
|
||||
self.menu_screen.model_name)
|
||||
except RPCException:
|
||||
result = []
|
||||
if search_text != widget.get_text().decode('utf-8'):
|
||||
return False
|
||||
gmodel.clear()
|
||||
for r in result:
|
||||
_, model, model_name, record_id, record_name, icon = r
|
||||
if icon:
|
||||
text = common.to_xml(record_name)
|
||||
common.ICONFACTORY.register_icon(icon)
|
||||
pixbuf = widget.render_icon(stock_id=icon,
|
||||
size=gtk.ICON_SIZE_BUTTON, detail=None)
|
||||
else:
|
||||
text = '<b>%s:</b>\n %s' % (
|
||||
common.to_xml(model_name),
|
||||
common.to_xml(record_name))
|
||||
pixbuf = None
|
||||
gmodel.append([pixbuf, text, model, record_id])
|
||||
gmodel.search_text = search_text
|
||||
# Force display of popup
|
||||
widget.emit('changed')
|
||||
self.menu_screen.model_name, callback=callback)
|
||||
return False
|
||||
|
||||
def changed(widget):
|
||||
@@ -842,38 +846,43 @@ class Main(object):
|
||||
self.notebook.set_current_page(page - 1)
|
||||
|
||||
def get_preferences(self):
|
||||
rpc.context_reload()
|
||||
try:
|
||||
prefs = RPCExecute('model', 'res.user', 'get_preferences',
|
||||
False)
|
||||
except RPCException:
|
||||
prefs = {}
|
||||
threads = []
|
||||
for target in (
|
||||
common.ICONFACTORY.load_icons,
|
||||
common.MODELACCESS.load_models,
|
||||
common.VIEW_SEARCH.load_searches,
|
||||
):
|
||||
t = threading.Thread(target=target)
|
||||
threads.append(t)
|
||||
t.start()
|
||||
for t in threads:
|
||||
t.join()
|
||||
if prefs and 'language_direction' in prefs:
|
||||
translate.set_language_direction(prefs['language_direction'])
|
||||
CONFIG['client.language_direction'] = \
|
||||
prefs['language_direction']
|
||||
self.sig_win_menu(prefs=prefs)
|
||||
for action_id in prefs.get('actions', []):
|
||||
Action.execute(action_id, {})
|
||||
self.set_title(prefs.get('status_bar', ''))
|
||||
if prefs and 'language' in prefs:
|
||||
translate.setlang(prefs['language'], prefs.get('locale'))
|
||||
if CONFIG['client.lang'] != prefs['language']:
|
||||
self.set_menubar()
|
||||
self.favorite_unset()
|
||||
CONFIG['client.lang'] = prefs['language']
|
||||
CONFIG.save()
|
||||
def _set_preferences(prefs):
|
||||
try:
|
||||
prefs = prefs()
|
||||
except RPCException:
|
||||
prefs = {}
|
||||
threads = []
|
||||
for target in (
|
||||
common.ICONFACTORY.load_icons,
|
||||
common.MODELACCESS.load_models,
|
||||
common.VIEW_SEARCH.load_searches,
|
||||
):
|
||||
t = threading.Thread(target=target)
|
||||
threads.append(t)
|
||||
t.start()
|
||||
for t in threads:
|
||||
t.join()
|
||||
if prefs and 'language_direction' in prefs:
|
||||
translate.set_language_direction(prefs['language_direction'])
|
||||
CONFIG['client.language_direction'] = \
|
||||
prefs['language_direction']
|
||||
self.sig_win_menu(prefs=prefs)
|
||||
for action_id in prefs.get('actions', []):
|
||||
Action.execute(action_id, {})
|
||||
self.set_title(prefs.get('status_bar', ''))
|
||||
if prefs and 'language' in prefs:
|
||||
translate.setlang(prefs['language'], prefs.get('locale'))
|
||||
if CONFIG['client.lang'] != prefs['language']:
|
||||
self.set_menubar()
|
||||
self.favorite_unset()
|
||||
CONFIG['client.lang'] = prefs['language']
|
||||
CONFIG.save()
|
||||
|
||||
def _get_preferences():
|
||||
RPCExecute('model', 'res.user', 'get_preferences', False,
|
||||
callback=_set_preferences)
|
||||
|
||||
RPCContextReload(_get_preferences)
|
||||
|
||||
def sig_user_preferences(self, widget):
|
||||
if not self.close_pages():
|
||||
|
||||
@@ -410,7 +410,7 @@ class M2OField(CharField):
|
||||
if not rec_name and value >= 0:
|
||||
try:
|
||||
result, = RPCExecute('model', self.attrs['relation'], 'read',
|
||||
[value], ['rec_name'], main_iteration=False)
|
||||
[value], ['rec_name'])
|
||||
except RPCException:
|
||||
return False
|
||||
rec_name = result['rec_name'] or ''
|
||||
@@ -603,8 +603,7 @@ class O2MField(CharField):
|
||||
if field_names:
|
||||
try:
|
||||
fields.update(RPCExecute('model', self.attrs['relation'],
|
||||
'fields_get', list(field_names),
|
||||
main_iteration=False, context=context))
|
||||
'fields_get', list(field_names), context=context))
|
||||
except RPCException:
|
||||
return
|
||||
|
||||
@@ -681,8 +680,7 @@ class O2MField(CharField):
|
||||
if field_names:
|
||||
try:
|
||||
fields = RPCExecute('model', self.attrs['relation'],
|
||||
'fields_get', list(field_names), main_iteration=False,
|
||||
context=context)
|
||||
'fields_get', list(field_names), context=context)
|
||||
except RPCException:
|
||||
return False
|
||||
else:
|
||||
@@ -855,7 +853,7 @@ class ReferenceField(CharField):
|
||||
if not rec_name and ref_id >= 0:
|
||||
try:
|
||||
result, = RPCExecute('model', ref_model, 'read', [ref_id],
|
||||
['rec_name'], main_iteration=False)
|
||||
['rec_name'])
|
||||
except RPCException:
|
||||
return
|
||||
rec_name = result['rec_name']
|
||||
@@ -910,8 +908,7 @@ class BinaryField(CharField):
|
||||
context = record.context_get()
|
||||
try:
|
||||
values, = RPCExecute('model', record.model_name, 'read',
|
||||
[record.id], [self.name], main_iteration=False,
|
||||
context=context)
|
||||
[record.id], [self.name], context=context)
|
||||
except RPCException:
|
||||
return ''
|
||||
_, filename = tempfile.mkstemp(prefix='tryton_')
|
||||
|
||||
@@ -203,7 +203,7 @@ class Group(SignalEvent, list):
|
||||
for fnct in self.on_write:
|
||||
try:
|
||||
res += RPCExecute('model', self.model_name, fnct, ids,
|
||||
main_iteration=False, context=self.context)
|
||||
context=self.context)
|
||||
except RPCException:
|
||||
return []
|
||||
return list({}.fromkeys(res))
|
||||
@@ -392,7 +392,7 @@ class Group(SignalEvent, list):
|
||||
if len(new) and len(to_add):
|
||||
try:
|
||||
values = RPCExecute('model', self.model_name, 'default_get',
|
||||
to_add.keys(), main_iteration=False, context=self.context)
|
||||
to_add.keys(), context=self.context)
|
||||
except RPCException:
|
||||
return False
|
||||
for record in new:
|
||||
|
||||
@@ -118,8 +118,7 @@ class Record(SignalEvent):
|
||||
exception = None
|
||||
try:
|
||||
values = RPCExecute('model', self.model_name, 'read',
|
||||
id2record.keys(), fnames, context=ctx,
|
||||
main_iteration=False)
|
||||
id2record.keys(), fnames, context=ctx)
|
||||
except RPCException, exception:
|
||||
values = [{'id': x} for x in id2record]
|
||||
default_values = dict((f, None) for f in fnames)
|
||||
@@ -286,7 +285,7 @@ class Record(SignalEvent):
|
||||
values = self._get_on_change_args(self.modified_fields)
|
||||
try:
|
||||
RPCExecute('model', self.model_name, 'pre_validate', values,
|
||||
main_iteration=False, context=self.context_get())
|
||||
context=self.context_get())
|
||||
except RPCException:
|
||||
return False
|
||||
return True
|
||||
@@ -297,8 +296,7 @@ class Record(SignalEvent):
|
||||
value = self.get()
|
||||
try:
|
||||
res, = RPCExecute('model', self.model_name, 'create',
|
||||
[value], main_iteration=False,
|
||||
context=self.context_get())
|
||||
[value], context=self.context_get())
|
||||
except RPCException:
|
||||
return False
|
||||
old_id = self.id
|
||||
@@ -312,8 +310,7 @@ class Record(SignalEvent):
|
||||
context['_timestamp'] = self.get_timestamp()
|
||||
try:
|
||||
RPCExecute('model', self.model_name, 'write',
|
||||
[self.id], value, main_iteration=False,
|
||||
context=context)
|
||||
[self.id], value, context=context)
|
||||
except RPCException:
|
||||
return False
|
||||
self._loaded.clear()
|
||||
@@ -346,7 +343,7 @@ class Record(SignalEvent):
|
||||
reload_ids = list(reload_ids)
|
||||
try:
|
||||
RPCExecute('model', record.model_name, 'delete', list(record_ids),
|
||||
main_iteration=False, context=ctx)
|
||||
context=ctx)
|
||||
except RPCException:
|
||||
return False
|
||||
if reload_ids:
|
||||
@@ -357,8 +354,7 @@ class Record(SignalEvent):
|
||||
if len(self.group.fields):
|
||||
try:
|
||||
vals = RPCExecute('model', self.model_name, 'default_get',
|
||||
self.group.fields.keys(), main_iteration=False,
|
||||
context=self.context_get())
|
||||
self.group.fields.keys(), context=self.context_get())
|
||||
except RPCException:
|
||||
return
|
||||
if (self.parent
|
||||
@@ -380,8 +376,7 @@ class Record(SignalEvent):
|
||||
def rec_name(self):
|
||||
try:
|
||||
return RPCExecute('model', self.model_name, 'read', [self.id],
|
||||
['rec_name'], main_iteration=False,
|
||||
context=self.context_get())[0]['rec_name']
|
||||
['rec_name'], context=self.context_get())[0]['rec_name']
|
||||
except RPCException:
|
||||
return ''
|
||||
|
||||
@@ -532,8 +527,7 @@ class Record(SignalEvent):
|
||||
args = self._get_on_change_args(attr)
|
||||
try:
|
||||
res = RPCExecute('model', self.model_name, 'on_change_' +
|
||||
fieldname, args, main_iteration=False,
|
||||
context=self.context_get())
|
||||
fieldname, args, context=self.context_get())
|
||||
except RPCException:
|
||||
return
|
||||
self.set_on_change(res)
|
||||
@@ -564,8 +558,7 @@ class Record(SignalEvent):
|
||||
if fieldnames:
|
||||
try:
|
||||
result = RPCExecute('model', self.model_name, 'on_change_with',
|
||||
values, list(fieldnames), main_iteration=False,
|
||||
context=self.context_get())
|
||||
values, list(fieldnames), context=self.context_get())
|
||||
except RPCException:
|
||||
return
|
||||
self.set_on_change(result)
|
||||
@@ -576,7 +569,7 @@ class Record(SignalEvent):
|
||||
try:
|
||||
result = RPCExecute('model', self.model_name,
|
||||
'on_change_with_' + fieldname, values,
|
||||
main_iteration=False, context=self.context_get())
|
||||
context=self.context_get())
|
||||
except RPCException:
|
||||
return
|
||||
self.group.fields[fieldname].set_on_change(self, result)
|
||||
@@ -594,8 +587,7 @@ class Record(SignalEvent):
|
||||
args = self._get_on_change_args(autocomplete)
|
||||
try:
|
||||
res = RPCExecute('model', self.model_name, 'autocomplete_' +
|
||||
fieldname, args, main_iteration=False,
|
||||
context=self.context_get())
|
||||
fieldname, args, context=self.context_get())
|
||||
except RPCException:
|
||||
# ensure res is a list
|
||||
res = []
|
||||
@@ -610,7 +602,7 @@ class Record(SignalEvent):
|
||||
'search_count', [
|
||||
('resource', '=',
|
||||
'%s,%s' % (self.model_name, self.id)),
|
||||
], main_iteration=False)
|
||||
])
|
||||
except RPCException:
|
||||
return 0
|
||||
return self.attachment_count
|
||||
|
||||
+68
-66
@@ -3,17 +3,16 @@
|
||||
import gtk
|
||||
import pango
|
||||
import gettext
|
||||
import socket
|
||||
|
||||
from tryton.signal_event import SignalEvent
|
||||
import tryton.rpc as rpc
|
||||
import tryton.common as common
|
||||
from tryton.gui.window.view_form.screen import Screen
|
||||
from tryton.gui import Main
|
||||
from tryton.exceptions import TrytonServerError, TrytonServerUnavailable
|
||||
from tryton.exceptions import TrytonServerError
|
||||
from tryton.gui.window.nomodal import NoModal
|
||||
from tryton.common.button import Button
|
||||
from tryton.common import RPCExecute, RPCException, TRYTON_ICON
|
||||
from tryton.common import RPCExecute, RPCException, RPCContextReload
|
||||
from tryton.common import TRYTON_ICON
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
@@ -55,83 +54,85 @@ class Wizard(object):
|
||||
self.email_print = email_print
|
||||
self.email = email
|
||||
self.context = context
|
||||
try:
|
||||
result = RPCExecute('wizard', action, 'create')
|
||||
except RPCException:
|
||||
return
|
||||
self.session_id, self.start_state, self.end_state = result
|
||||
self.state = self.start_state
|
||||
self.process()
|
||||
|
||||
def callback(result):
|
||||
try:
|
||||
result = result()
|
||||
except RPCException:
|
||||
return
|
||||
self.session_id, self.start_state, self.end_state = result
|
||||
self.state = self.start_state
|
||||
self.process()
|
||||
RPCExecute('wizard', action, 'create', callback=callback)
|
||||
|
||||
def process(self):
|
||||
from tryton.action import Action
|
||||
if self.__processing or self.__waiting_response:
|
||||
return
|
||||
try:
|
||||
self.__processing = True
|
||||
while self.state != self.end_state:
|
||||
ctx = self.context.copy()
|
||||
ctx['active_id'] = self.id
|
||||
ctx['active_ids'] = self.ids
|
||||
ctx['active_model'] = self.model
|
||||
ctx['action_id'] = self.action_id
|
||||
if self.screen:
|
||||
data = {
|
||||
self.screen_state: self.screen.get_on_change_value(),
|
||||
}
|
||||
else:
|
||||
data = {}
|
||||
try:
|
||||
result = RPCExecute('wizard', self.action, 'execute',
|
||||
self.session_id, data, self.state, context=ctx)
|
||||
except RPCException, rpc_exception:
|
||||
if (not isinstance(rpc_exception.exception,
|
||||
TrytonServerError)
|
||||
or not self.screen):
|
||||
self.state = self.end_state
|
||||
break
|
||||
self.__processing = True
|
||||
|
||||
if 'view' in result:
|
||||
self.clean()
|
||||
view = result['view']
|
||||
self.update(view['fields_view'], view['defaults'],
|
||||
view['buttons'])
|
||||
self.screen_state = view['state']
|
||||
self.__waiting_response = True
|
||||
else:
|
||||
ctx = self.context.copy()
|
||||
ctx['active_id'] = self.id
|
||||
ctx['active_ids'] = self.ids
|
||||
ctx['active_model'] = self.model
|
||||
ctx['action_id'] = self.action_id
|
||||
if self.screen:
|
||||
data = {
|
||||
self.screen_state: self.screen.get_on_change_value(),
|
||||
}
|
||||
else:
|
||||
data = {}
|
||||
|
||||
def callback(result):
|
||||
try:
|
||||
result = result()
|
||||
except RPCException, rpc_exception:
|
||||
if (not isinstance(rpc_exception.exception,
|
||||
TrytonServerError)
|
||||
or not self.screen):
|
||||
self.state = self.end_state
|
||||
self.end()
|
||||
self.__processing = False
|
||||
return
|
||||
|
||||
if 'actions' in result:
|
||||
sensitive_widget = self.widget.get_toplevel()
|
||||
if not 'view' in result:
|
||||
self.end()
|
||||
for action in result['actions']:
|
||||
Action._exec_action(*action, context=ctx)
|
||||
if (not 'view' in result
|
||||
or (action[0]['type'] == 'ir.action.wizard'
|
||||
and not sensitive_widget.props.sensitive)):
|
||||
return
|
||||
if self.__waiting_response:
|
||||
break
|
||||
if 'view' in result:
|
||||
self.clean()
|
||||
view = result['view']
|
||||
self.update(view['fields_view'], view['defaults'],
|
||||
view['buttons'])
|
||||
self.screen_state = view['state']
|
||||
self.__waiting_response = True
|
||||
else:
|
||||
self.state = self.end_state
|
||||
|
||||
if 'actions' in result:
|
||||
sensitive_widget = self.widget.get_toplevel()
|
||||
if not 'view' in result:
|
||||
self.end()
|
||||
for action in result['actions']:
|
||||
Action._exec_action(*action, context=ctx)
|
||||
if (not 'view' in result
|
||||
or (action[0]['type'] == 'ir.action.wizard'
|
||||
and not sensitive_widget.props.sensitive)):
|
||||
self.__processing = False
|
||||
return
|
||||
|
||||
if self.state == self.end_state:
|
||||
self.end()
|
||||
finally:
|
||||
self.__processing = False
|
||||
|
||||
RPCExecute('wizard', self.action, 'execute', self.session_id, data,
|
||||
self.state, context=ctx, callback=callback)
|
||||
|
||||
def destroy(self):
|
||||
if self.screen:
|
||||
self.screen.destroy()
|
||||
|
||||
def end(self):
|
||||
try:
|
||||
return RPCExecute('wizard', self.action, 'delete', self.session_id,
|
||||
process_exception=False)
|
||||
if self.action == 'ir.module.module.config_wizard':
|
||||
rpc.context_reload()
|
||||
Main.get_main().sig_win_menu()
|
||||
except (TrytonServerError, socket.error, TrytonServerUnavailable):
|
||||
pass
|
||||
def end(self, callback=None):
|
||||
RPCExecute('wizard', self.action, 'delete', self.session_id,
|
||||
process_exception=False, callback=callback)
|
||||
if self.action == 'ir.module.module.config_wizard':
|
||||
RPCContextReload(Main.get_main().sig_win_menu)
|
||||
|
||||
def clean(self):
|
||||
for widget in self.widget.get_children():
|
||||
@@ -360,8 +361,9 @@ class WizardDialog(Wizard, NoModal):
|
||||
dialog.screen.client_action(action)
|
||||
|
||||
def end(self):
|
||||
action = super(WizardDialog, self).end()
|
||||
self.destroy(action=action)
|
||||
def callback(action):
|
||||
self.destroy(action=action())
|
||||
super(WizardDialog, self).end(callback=callback)
|
||||
|
||||
def close(self, widget, event=None):
|
||||
if self.end_state in self.states:
|
||||
|
||||
@@ -130,16 +130,6 @@ def logout():
|
||||
_KEYWORD_CACHE = {}
|
||||
|
||||
|
||||
def context_reload():
|
||||
global CONTEXT
|
||||
try:
|
||||
context = execute('model', 'res.user', 'get_preferences', True, {})
|
||||
except Fault:
|
||||
return
|
||||
CONTEXT = {}
|
||||
CONTEXT.update(context)
|
||||
|
||||
|
||||
def _execute(blocking, *args):
|
||||
global CONNECTION, _USER, _SESSION
|
||||
if CONNECTION is None:
|
||||
|
||||
Reference in new issue
Block a user