details: https://code.tryton.org/tryton/commit/3bccf6f3ed9c
branch: default
user: Cédric Krier <[email protected]>
date: Mon Aug 31 13:45:03 2026 +0200
description:
Add editable state on field
diffstat:
sao/src/model.js | 4 ++++
tryton/tryton/gui/window/view_form/model/field.py | 2 ++
trytond/CHANGELOG | 1 +
trytond/doc/ref/fields.rst | 7 ++++++-
trytond/trytond/model/fields/field.py | 11 +++++++----
5 files changed, 20 insertions(+), 5 deletions(-)
diffs (82 lines):
diff -r e6d7121c620c -r 3bccf6f3ed9c sao/src/model.js
--- a/sao/src/model.js Mon Aug 31 13:43:41 2026 +0200
+++ b/sao/src/model.js Mon Aug 31 13:45:03 2026 +0200
@@ -1701,6 +1701,10 @@
this.get_state_attrs(record)[state] =
this.description[state];
}
+ if ((state == 'readonly') &&
+ !(Object.hasOwn(state_changes, 'editable') ?
state_changes.editable : true)) {
+ this.get_state_attrs(record).readonly = true;
+ }
}
if (record.group.readonly ||
this.get_state_attrs(record).domain_readonly ||
diff -r e6d7121c620c -r 3bccf6f3ed9c
tryton/tryton/gui/window/view_form/model/field.py
--- a/tryton/tryton/gui/window/view_form/model/field.py Mon Aug 31 13:43:41
2026 +0200
+++ b/tryton/tryton/gui/window/view_form/model/field.py Mon Aug 31 13:45:03
2026 +0200
@@ -194,6 +194,8 @@
self.get_state_attrs(record)[key] = state_changes[key]
elif key in self.attrs:
self.get_state_attrs(record)[key] = self.attrs[key]
+ if key == 'readonly' and not state_changes.get('editable', True):
+ self.get_state_attrs(record)['readonly'] = True
if (record.group.readonly
or self.get_state_attrs(record).get('domain_readonly')
or record.parent_name == self.name):
diff -r e6d7121c620c -r 3bccf6f3ed9c trytond/CHANGELOG
--- a/trytond/CHANGELOG Mon Aug 31 13:43:41 2026 +0200
+++ b/trytond/CHANGELOG Mon Aug 31 13:45:03 2026 +0200
@@ -1,3 +1,4 @@
+* Add editable state on field
* Enforce readonly on field when checking access
* Add the icon parameter to register_authentication_service
* Add routes for sao custom in base router
diff -r e6d7121c620c -r 3bccf6f3ed9c trytond/doc/ref/fields.rst
--- a/trytond/doc/ref/fields.rst Mon Aug 31 13:43:41 2026 +0200
+++ b/trytond/doc/ref/fields.rst Mon Aug 31 13:45:03 2026 +0200
@@ -61,10 +61,15 @@
A dictionary that defines dynamic states of the field and overrides the
static one.
- Possible keys are ``required``, ``readonly`` and ``invisible``.
+ Possible keys are ``required``, ``readonly``, ``editable`` and
+ ``invisible``.
The values are :class:`~trytond.pyson.PYSON` statements that is evaluated
with the values of the record.
+ .. note::
+
+ ``editable`` is not enforced but only used for the UI.
+
.. attribute:: Field.on_change
A set of field names.
diff -r e6d7121c620c -r 3bccf6f3ed9c trytond/trytond/model/fields/field.py
--- a/trytond/trytond/model/fields/field.py Mon Aug 31 13:43:41 2026 +0200
+++ b/trytond/trytond/model/fields/field.py Mon Aug 31 13:45:03 2026 +0200
@@ -50,10 +50,12 @@
def states_validate(value):
assert isinstance(value, dict), 'states must be a dict'
- assert set(value).issubset({'required', 'readonly', 'invisible'}), (
- 'extra keys "%(keys)s" in states' % {
- 'keys': set(value) - {'required', 'readonly', 'invisible'},
- })
+ assert set(value).issubset(
+ {'required', 'readonly', 'editable', 'invisible'}), (
+ 'extra keys "%(keys)s" in states' % {
+ 'keys': set(value) - {
+ 'required', 'readonly', 'editable', 'invisible'},
+ })
for state in value:
assert isinstance(value[state], (bool, PYSON)), \
'values of states must be PYSON'
@@ -413,6 +415,7 @@
def edition_depends(self):
depends = get_eval_fields(self.domain)
depends |= get_eval_fields(self.states.get('readonly'))
+ depends |= get_eval_fields(self.states.get('editable'))
depends |= get_eval_fields(self.states.get('required'))
return self.depends | depends