diff --git a/tryton/common/__init__.py b/tryton/common/__init__.py index f60cbc8ddf..b7650d20b2 100644 --- a/tryton/common/__init__.py +++ b/tryton/common/__init__.py @@ -3,5 +3,5 @@ from common import * from datetime_strftime import * from domain_inversion import domain_inversion, eval_domain, localize_domain, \ - merge, inverse_leaf + merge, inverse_leaf, concat from environment import EvalEnvironment diff --git a/tryton/common/domain_inversion.py b/tryton/common/domain_inversion.py index 7d82befdd8..f28eddde7c 100644 --- a/tryton/common/domain_inversion.py +++ b/tryton/common/domain_inversion.py @@ -175,6 +175,17 @@ def merge(domain, domoperator=None): return [merge(domain)] +def concat(*domains, **kwargs): + domoperator = kwargs.get('domoperator') + result = [] + if domoperator: + result.append(domoperator) + for domain in domains: + if domain: + result.append(domain) + return simplify(merge(result)) + + def parse(domain): if is_leaf(domain): return domain @@ -446,6 +457,17 @@ def test_merge(): ['d', '=', 5], ['e', '=', 6], ['f', '=', 7]] +def test_concat(): + domain1 = [['a', '=', 1]] + domain2 = [['b', '=', 2]] + assert concat(domain1, domain2) == ['AND', ['a', '=', 1], ['b', '=', 2]] + assert concat([], domain1) == domain1 + assert concat(domain2, []) == domain2 + assert concat([], []) == [] + assert concat(domain1, domain2, domoperator='OR') == [ + 'OR', [['a', '=', 1]], [['b', '=', 2]]] + + def test_evaldomain(): domain = [['x', '>', 5]] assert eval_domain(domain, {'x': 6}) diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py index 9cd870a997..06e20ad14a 100644 --- a/tryton/gui/window/view_form/model/field.py +++ b/tryton/gui/window/view_form/model/field.py @@ -6,7 +6,7 @@ import tempfile import locale from tryton.common import datetime_strftime, \ domain_inversion, eval_domain, localize_domain, \ - merge, inverse_leaf, EvalEnvironment + merge, inverse_leaf, concat, EvalEnvironment import tryton.common as common import time import datetime @@ -54,14 +54,10 @@ class Field(object): def domain_get(self, record): screen_domain, attr_domain = self.domains_get(record) - return [localize_domain(screen_domain), attr_domain] + return concat(localize_domain(screen_domain), attr_domain) def validation_domains(self, record): - screen_domain, attr_domain = self.domains_get(record) - if attr_domain: - return (screen_domain, [screen_domain, attr_domain]) - else: - return screen_domain, screen_domain + return concat(*self.domains_get(record)) def context_get(self, record): context = record.context_get().copy() @@ -83,7 +79,7 @@ class Field(object): return True res = True self.get_state_attrs(record)['domain_readonly'] = False - inverted_domain, domain = self.validation_domains(record) + domain = self.validation_domains(record) if not softvalidation: res = res and self.check_required(record) if isinstance(domain, bool): @@ -91,19 +87,22 @@ class Field(object): elif domain == [('id', '=', False)]: res = False else: - if (isinstance(inverted_domain, list) - and len(inverted_domain) == 1 - and inverted_domain[0][1] == '='): + if (isinstance(domain, list) + and len(domain) == 1 + and domain[0][1] == '='): # If the inverted domain is so constraint that only one value # is possible we should use it. But we must also pay attention # to the fact that the original domain might be a 'OR' domain # and thus not preventing the modification of fields. - leftpart, _, value = inverted_domain[0][:3] + leftpart, _, value = domain[0][:3] if value is False: # XXX to remove once server domains are fixed value = None setdefault = True - original_domain = merge(record.group.domain) + if record.group.domain: + original_domain = merge(record.group.domain) + else: + original_domain = merge(domain) domain_readonly = original_domain[0] == 'AND' if '.' in leftpart: recordpart, localpart = leftpart.split('.', 1) @@ -439,12 +438,12 @@ class M2OField(Field): def validation_domains(self, record): screen_domain, attr_domain = self.domains_get(record) - return screen_domain, screen_domain + return screen_domain def domain_get(self, record): screen_domain, attr_domain = self.domains_get(record) - return [localize_domain(inverse_leaf(screen_domain), self.name), - attr_domain] + return concat(localize_domain(inverse_leaf(screen_domain), self.name), + attr_domain) def get_state_attrs(self, record): result = super(M2OField, self).get_state_attrs(record) @@ -723,7 +722,7 @@ class O2MField(Field): def validation_domains(self, record): screen_domain, attr_domain = self.domains_get(record) - return screen_domain, screen_domain + return screen_domain def validate(self, record, softvalidation=False): if self.attrs.get('readonly'): @@ -753,8 +752,8 @@ class O2MField(Field): def domain_get(self, record): screen_domain, attr_domain = self.domains_get(record) - return [localize_domain(inverse_leaf(screen_domain), self.name), - attr_domain] + return concat(localize_domain(inverse_leaf(screen_domain), self.name), + attr_domain) class M2MField(O2MField): @@ -910,11 +909,12 @@ class DictField(Field): def validation_domains(self, record): screen_domain, attr_domain = self.domains_get(record) - return screen_domain, screen_domain + return screen_domain def domain_get(self, record): screen_domain, attr_domain = self.domains_get(record) - return [localize_domain(inverse_leaf(screen_domain)), attr_domain] + return concat(localize_domain(inverse_leaf(screen_domain)), + attr_domain) TYPES = { 'char': CharField,