diff --git a/CHANGELOG b/CHANGELOG index c1e077f139..7a483bfba7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Cache action keyword +* Always use cached views * Manage model access * Manage time format * Deactivate attachment button when record is not created diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index 93a941a530..a9f940d7f1 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -23,6 +23,10 @@ from tryton.common import RPCExecute, RPCException, MODELACCESS class Screen(SignalEvent): "Screen" + # Width of tree columns per model + # It is shared with all connection but it is the price for speed. + tree_column_width = collections.defaultdict(lambda: {}) + def __init__(self, model_name, view_ids=None, mode=None, context=None, views_preload=None, domain=None, row_activate=None, limit=None, readonly=False, exclude_field=None, sort=None, search_value=None, diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py index 6233da2051..2ebfdaa113 100644 --- a/tryton/gui/window/view_form/view/list.py +++ b/tryton/gui/window/view_form/view/list.py @@ -653,11 +653,13 @@ class ViewList(ParserView): del fields[last_col.name] if fields and any(fields.itervalues()): + model_name = self.screen.model_name try: RPCExecute('model', 'ir.ui.view_tree_width', 'set_width', - self.screen.model_name, fields) + model_name, fields) except RPCException: pass + self.screen.tree_column_width[model_name].update(fields) def destroy(self): self.save_width_height() diff --git a/tryton/gui/window/view_form/view/list_gtk/parser.py b/tryton/gui/window/view_form/view/list_gtk/parser.py index a97ce91faa..e046f1eefb 100644 --- a/tryton/gui/window/view_form/view/list_gtk/parser.py +++ b/tryton/gui/window/view_form/view/list_gtk/parser.py @@ -206,10 +206,12 @@ class ParserTree(ParserInterface): 'boolean': 20, 'binary': 200, } - if 'width' in node_attrs: - width = int(node_attrs['width']) - else: - width = twidth.get(fields[fname].attrs['type'], 100) + width = self.screen.tree_column_width[model_name].get(fname) + if not width: + if 'width' in node_attrs: + width = int(node_attrs['width']) + else: + width = twidth.get(fields[fname].attrs['type'], 100) col.width = width if width > 0: col.set_fixed_width(width) diff --git a/tryton/rpc.py b/tryton/rpc.py index 32ec540dad..bce81903a2 100644 --- a/tryton/rpc.py +++ b/tryton/rpc.py @@ -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 httplib -import itertools import logging import socket import os @@ -23,6 +22,7 @@ _DATABASE = '' CONTEXT = {} _VIEW_CACHE = {} _TOOLBAR_CACHE = {} +_KEYWORD_CACHE = {} TIMEZONE = 'utc' _SEMAPHORE = Semaphore() _CA_CERTS = os.path.join(get_config_dir(), 'ca_certs') @@ -72,9 +72,10 @@ def server_version(host, port): def login(username, password, host, port, database): global CONNECTION, _USER, _USERNAME, _SESSION, _HOST, _PORT, _DATABASE - global _VIEW_CACHE, _TOOLBAR_CACHE + global _VIEW_CACHE, _TOOLBAR_CACHE, _KEYWORD_CACHE _VIEW_CACHE = {} _TOOLBAR_CACHE = {} + _KEYWORD_CACHE = {} try: _SEMAPHORE.acquire() try: @@ -107,7 +108,7 @@ def login(username, password, host, port, database): def logout(): global CONNECTION, _USER, _USERNAME, _SESSION, _HOST, _PORT, _DATABASE - global _VIEW_CACHE, _TOOLBAR_CACHE + global _VIEW_CACHE, _TOOLBAR_CACHE, _KEYWORD_CACHE if IPCServer.instance: IPCServer.instance.stop() if CONNECTION is not None: @@ -130,6 +131,7 @@ def logout(): _DATABASE = '' _VIEW_CACHE = {} _TOOLBAR_CACHE = {} + _KEYWORD_CACHE = {} def context_reload(): @@ -155,23 +157,20 @@ def _execute(blocking, *args): if CONNECTION is None: raise TrytonServerError('NotLogged') key = False + model = args[1] method = args[2] if method == 'fields_view_get': - args, ctx = args[:-1], args[-1] - # Make sure all the arguments are present - args = tuple(arg if arg is not None else default - for arg, default in itertools.izip_longest(args, - ('', '', 'fields_view_get', None, 'form'), - fillvalue=None)) - key = str(args + (ctx,)) - if key in _VIEW_CACHE and _VIEW_CACHE[key][0]: - args += (_VIEW_CACHE[key][0], ctx) - else: - args += (ctx,) + key = str(args) + if key in _VIEW_CACHE: + return _VIEW_CACHE[key] elif method == 'view_toolbar_get': key = str(args) if key in _TOOLBAR_CACHE: return _TOOLBAR_CACHE[key] + elif model == 'ir.action.keyword' and method == 'get_keyword': + key = str(args) + if key in _KEYWORD_CACHE: + return _KEYWORD_CACHE[key] res = _SEMAPHORE.acquire(blocking) if not res: return @@ -185,12 +184,11 @@ def _execute(blocking, *args): finally: _SEMAPHORE.release() if key and method == 'fields_view_get': - if result is True and key in _VIEW_CACHE: - result = _VIEW_CACHE[key][1] - else: - _VIEW_CACHE[key] = (result['md5'], result) + _VIEW_CACHE[key] = result elif key and method == 'view_toolbar_get': _TOOLBAR_CACHE[key] = result + elif key and model == 'ir.action.keyword' and method == 'get_keyword': + _KEYWORD_CACHE[key] = result logging.getLogger('rpc.result').debug(repr(result)) return result