details: https://code.tryton.org/tryton/commit/23864f40889b
branch: default
user: Cédric Krier <[email protected]>
date: Tue Mar 10 15:45:24 2026 +0100
description:
Add generic management for label style in form widget
diffstat:
sao/src/view/form.js | 57 ++++------
tryton/tryton/gui/window/view_form/view/form_gtk/many2many.py | 23 +---
tryton/tryton/gui/window/view_form/view/form_gtk/one2many.py | 28 +---
tryton/tryton/gui/window/view_form/view/form_gtk/widget.py | 11 +-
4 files changed, 43 insertions(+), 76 deletions(-)
diffs (336 lines):
diff -r 42cf694cdab3 -r 23864f40889b sao/src/view/form.js
--- a/sao/src/view/form.js Tue Mar 10 14:54:48 2026 +0100
+++ b/sao/src/view/form.js Tue Mar 10 15:45:24 2026 +0100
@@ -1287,6 +1287,7 @@
this.position = 0;
this.visible = true;
this.labelled = null; // Element which received the labelledby
+ this.label = null; // Optional element rendering the field label
},
display: function() {
var field = this.field;
@@ -1350,6 +1351,10 @@
}
}
this.set_invisible(invisible);
+ if (this.label) {
+ Sao.common.apply_label_attributes(
+ this.label, readonly, required);
+ }
},
get _styled_el() {
return this.el;
@@ -3268,7 +3273,6 @@
Sao.View.Form.One2Many._super.init.call(this, view, attributes);
this._readonly = true;
- this._required = false;
this._position = undefined;
this._length = 0;
@@ -3280,16 +3284,16 @@
});
this.el.append(this.menu);
- this.title = jQuery('<label/>', {
+ this.label = jQuery('<label/>', {
'class': this.class_ + '-string',
text: attributes.string
});
- this.menu.append(this.title);
-
- this.title.uniqueId();
+ this.menu.append(this.label);
+
+ this.label.uniqueId();
this.el.uniqueId();
- this.el.attr('aria-labelledby', this.title.attr('id'));
- this.title.attr('for', this.el.attr('id'));
+ this.el.attr('aria-labelledby', this.label.attr('id'));
+ this.label.attr('for', this.el.attr('id'));
var toolbar = jQuery('<div/>', {
'class': this.class_ + '-toolbar'
@@ -3335,7 +3339,7 @@
).appendTo(buttons);
this.but_previous.click(disable_during(this.previous.bind(this)));
- this.label = jQuery('<span/>', {
+ this.badge = jQuery('<span/>', {
'class': 'badge',
}).text('_ / 0'
).appendTo(jQuery('<span/>', {
@@ -3511,15 +3515,6 @@
set_readonly: function(readonly) {
Sao.View.Form.One2Many._super.set_readonly.call(this, readonly);
this.prm.done(() => this._set_button_sensitive());
- this._set_label_state();
- },
- set_required: function(required) {
- this._required = required;
- this._set_label_state();
- },
- _set_label_state: function() {
- Sao.common.apply_label_attributes(this.title, this._readonly,
- this._required);
},
_set_button_sensitive: function() {
var size_limit, o2m_size;
@@ -3947,7 +3942,7 @@
}
}
var message = name + ' / ' + Sao.common.humanize(size);
- this.label.text(message).attr('title', message);
+ this.badge.text(message).attr('title', message);
this.prm.done(() => this._set_button_sensitive());
},
validate: function() {
@@ -4013,7 +4008,6 @@
Sao.View.Form.Many2Many._super.init.call(this, view, attributes);
this._readonly = true;
- this._required = false;
this._position = 0;
this.el = jQuery('<div/>', {
@@ -4024,16 +4018,16 @@
});
this.el.append(this.menu);
- this.title = jQuery('<label/>', {
+ this.label = jQuery('<label/>', {
'class': this.class_ + '-string',
text: attributes.string
});
- this.menu.append(this.title);
-
- this.title.uniqueId();
+ this.menu.append(this.label);
+
+ this.label.uniqueId();
this.el.uniqueId();
- this.el.attr('aria-labelledby', this.title.attr('id'));
- this.title.attr('for', this.el.attr('id'));
+ this.el.attr('aria-labelledby', this.label.attr('id'));
+ this.label.attr('for', this.el.attr('id'));
var toolbar = jQuery('<div/>', {
'class': this.class_ + '-toolbar'
@@ -4074,7 +4068,7 @@
).appendTo(buttons);
this.but_add.click(this.add.bind(this));
- this.label = jQuery('<span/>', {
+ this.badge = jQuery('<span/>', {
'class': 'badge',
}).text('_ / 0'
).appendTo(jQuery('<span/>', {
@@ -4150,15 +4144,6 @@
set_readonly: function(readonly) {
Sao.View.Form.Many2Many._super.set_readonly.call(this, readonly);
this._set_button_sensitive();
- this._set_label_state();
- },
- set_required: function(required) {
- this._required = required;
- this._set_label_state();
- },
- _set_label_state: function() {
- Sao.common.apply_label_attributes(this.title, this._readonly,
- this._required);
},
_set_button_sensitive: function() {
var size_limit = false,
@@ -4203,7 +4188,7 @@
}
}
var message = name + ' / ' + Sao.common.humanize(size);
- this.label.text(message).attr('title', message);
+ this.badge.text(message).attr('title', message);
this._set_button_sensitive();
},
display: function() {
diff -r 42cf694cdab3 -r 23864f40889b
tryton/tryton/gui/window/view_form/view/form_gtk/many2many.py
--- a/tryton/tryton/gui/window/view_form/view/form_gtk/many2many.py Tue Mar
10 14:54:48 2026 +0100
+++ b/tryton/tryton/gui/window/view_form/view/form_gtk/many2many.py Tue Mar
10 15:45:24 2026 +0100
@@ -35,10 +35,10 @@
hbox = Gtk.HBox(homogeneous=False, spacing=0)
hbox.set_border_width(2)
- self.title = Gtk.Label(
+ self.label = Gtk.Label(
label=set_underline(attrs.get('string', '')),
use_underline=True, halign=Gtk.Align.START)
- hbox.pack_start(self.title, expand=True, fill=True, padding=0)
+ hbox.pack_start(self.label, expand=True, fill=True, padding=0)
hbox.pack_start(Gtk.VSeparator(), expand=False, fill=True, padding=0)
@@ -71,8 +71,8 @@
self.but_add.set_relief(Gtk.ReliefStyle.NONE)
hbox.pack_start(self.but_add, expand=False, fill=False, padding=0)
- self.label = Gtk.Label(label='(_/0)')
- hbox.pack_start(self.label, expand=False, fill=False, padding=0)
+ self.badge = Gtk.Label(label='(_/0)')
+ hbox.pack_start(self.badge, expand=False, fill=False, padding=0)
self.but_remove = Gtk.Button(can_focus=False)
tooltips.set_tip(self.but_remove, _('Remove selected record'))
@@ -114,7 +114,7 @@
vbox.pack_start(self.screen.widget, expand=True, fill=True, padding=0)
- self.title.set_mnemonic_widget(
+ self.label.set_mnemonic_widget(
self.screen.current_view.mnemonic_widget)
self.screen.widget.connect('key_press_event', self.on_keypress)
@@ -281,19 +281,10 @@
screen, callback, new=True, save_current=True, defaults=defaults)
def _readonly_set(self, value):
- self._readonly = value
+ super()._readonly_set(value)
self._set_button_sensitive()
self.wid_text.set_sensitive(not value)
self.wid_text.set_editable(not value)
- self._set_label_state()
-
- def _required_set(self, value):
- self._required = value
- self._set_label_state()
-
- def _set_label_state(self):
- common.apply_label_attributes(
- self.title, self._readonly, self._required)
def _set_button_sensitive(self):
if self.record and self.field:
@@ -330,7 +321,7 @@
if selected > 1:
name += '#%i' % selected
name = '(%s/%s)' % (name, common.humanize(size))
- self.label.set_text(name)
+ self.badge.set_text(name)
self._set_button_sensitive()
def display(self):
diff -r 42cf694cdab3 -r 23864f40889b
tryton/tryton/gui/window/view_form/view/form_gtk/one2many.py
--- a/tryton/tryton/gui/window/view_form/view/form_gtk/one2many.py Tue Mar
10 14:54:48 2026 +0100
+++ b/tryton/tryton/gui/window/view_form/view/form_gtk/one2many.py Tue Mar
10 15:45:24 2026 +0100
@@ -30,17 +30,16 @@
vbox = Gtk.VBox(homogeneous=False, spacing=2)
self.widget.add(vbox)
self._readonly = True
- self._required = False
self._position = None
self._length = 0
self.title_box = hbox = Gtk.HBox(homogeneous=False, spacing=0)
hbox.set_border_width(2)
- self.title = Gtk.Label(
+ self.label = Gtk.Label(
label=set_underline(attrs.get('string', '')),
use_underline=True, halign=Gtk.Align.START)
- hbox.pack_start(self.title, expand=True, fill=True, padding=0)
+ hbox.pack_start(self.label, expand=True, fill=True, padding=0)
hbox.pack_start(Gtk.VSeparator(), expand=False, fill=True, padding=0)
@@ -62,8 +61,8 @@
self.but_pre.set_relief(Gtk.ReliefStyle.NONE)
hbox.pack_start(self.but_pre, expand=False, fill=False, padding=0)
- self.label = Gtk.Label(label='(_/0)')
- hbox.pack_start(self.label, expand=False, fill=False, padding=0)
+ self.badge = Gtk.Label(label='(_/0)')
+ hbox.pack_start(self.badge, expand=False, fill=False, padding=0)
self.but_next = Gtk.Button(can_focus=False)
tooltips.set_tip(self.but_next, _('Next'))
@@ -175,7 +174,7 @@
vbox.pack_start(self.screen.widget, expand=True, fill=True, padding=0)
- self.title.set_mnemonic_widget(
+ self.label.set_mnemonic_widget(
self.screen.current_view.mnemonic_widget)
self.screen.widget.connect('key_press_event', self.on_keypress)
@@ -266,25 +265,16 @@
string = self.attrs.get('string', '')
if mnemonic_widget:
string = set_underline(string)
- self.title.set_mnemonic_widget(mnemonic_widget)
- self.title.set_label(string)
+ self.label.set_mnemonic_widget(mnemonic_widget)
+ self.label.set_label(string)
@property
def modified(self):
return self.screen.current_view.modified
def _readonly_set(self, value):
- self._readonly = value
+ super()._readonly_set(value)
self._set_button_sensitive()
- self._set_label_state()
-
- def _required_set(self, value):
- self._required = value
- self._set_label_state()
-
- def _set_label_state(self):
- common.apply_label_attributes(
- self.title, self._readonly, self._required)
def _set_button_sensitive(self):
if self.record and self.field:
@@ -555,7 +545,7 @@
if selected > 1:
name += '#%i' % selected
name = '(%s/%s)' % (name, common.humanize(size))
- self.label.set_text(name)
+ self.badge.set_text(name)
self._set_button_sensitive()
def display(self):
diff -r 42cf694cdab3 -r 23864f40889b
tryton/tryton/gui/window/view_form/view/form_gtk/widget.py
--- a/tryton/tryton/gui/window/view_form/view/form_gtk/widget.py Tue Mar
10 14:54:48 2026 +0100
+++ b/tryton/tryton/gui/window/view_form/view/form_gtk/widget.py Tue Mar
10 15:45:24 2026 +0100
@@ -26,6 +26,7 @@
self.mnemonic_widget = None
self.visible = True
self._readonly = False
+ self.label = None # optional label
@property
def field_name(self):
@@ -110,13 +111,11 @@
if self.view.screen.readonly:
readonly = True
self._readonly_set(readonly)
- self._required_set(not readonly and states.get('required', False))
+ required = not readonly and states.get('required', False)
+ self._required_set(required)
if self._styled_widget:
widget_class(self._styled_widget, 'readonly', readonly)
- widget_class(
- self._styled_widget,
- 'required',
- not readonly and states.get('required', False))
+ widget_class(self._styled_widget, 'required', required)
widget_class(
self._styled_widget,
'invalid',
@@ -128,6 +127,8 @@
and self.field_name in self.record.modified_fields)
self.invisible_set(self.attrs.get(
'invisible', states.get('invisible', False)))
+ if self.label:
+ common.apply_label_attributes(self.label, readonly, required)
def get_value(self):
pass