Add color widget to form view

Closes #13800
This commit is contained in:
Cédric Krier
2025-01-08 16:53:34 +01:00
parent e119120af3
commit 093fb115ff
13 changed files with 150 additions and 7 deletions
+1
View File
@@ -1,3 +1,4 @@
* Support color widget on form view
Version 7.4.0 - 2024-11-04
--------------------------
+3 -3
View File
@@ -884,9 +884,9 @@ img.icon {
width: max-content;
max-width: 80ch;
}
.form-char, .form-password, .form-integer, .form-float, .form-timedelta,
.form-selection, .form-multiselection, .form-url, .form-email,
.form-callto, .form-sip, .form-pyson {
.form-char, .form-password, .form-color, .form-integer, .form-float,
.form-timedelta, .form-selection, .form-multiselection, .form-url,
.form-email, .form-callto, .form-sip, .form-pyson {
input, select {
min-width: 8ch;
}
+59 -1
View File
@@ -1774,6 +1774,35 @@ function eval_pyson(value){
}
});
Sao.View.Form.Color = Sao.class_(Sao.View.Form.Char, {
class_: 'form-color',
init: function(view, attributes) {
Sao.View.Form.Color._super.init.call(this, view, attributes);
this.color_input = jQuery('<input/>', {
'class': 'btn btn-default btn-sm',
'type': 'color',
'title': Sao.i18n.gettext(
'Select a color for "%1"', attributes.string),
}).appendTo(jQuery('<span/>', {
'class': 'input-group-btn',
}).appendTo(this.group));
this.color_input.change(this.set_color.bind(this));
},
set_color: function() {
this.input.val(this.color_input.val());
this.focus_out();
},
set_readonly: function(readonly) {
Sao.View.Form.Color._super.set_readonly.call(this, readonly);
this.color_input.prop('disabled', readonly);
},
display: function() {
Sao.View.Form.Color._super.display.call(this);
this.color_input.val(this.get_client_value());
},
});
Sao.View.Form.Date = Sao.class_(Sao.View.Form.Widget, {
class_: 'form-date',
_input: 'date',
@@ -5354,7 +5383,9 @@ function eval_pyson(value){
get_entries: function(type) {
switch (type) {
case 'char':
return Sao.View.Form.Dict.Entry;
return Sao.View.Form.Dict.Char;
case 'color':
return Sao.View.Form.Dict.Color;
case 'boolean':
return Sao.View.Form.Dict.Boolean;
case 'selection':
@@ -5436,6 +5467,32 @@ function eval_pyson(value){
}
});
Sao.View.Form.Dict.Color = Sao.class_(Sao.View.Form.Dict.Char, {
class_: 'dict-color',
create_widget: function() {
Sao.View.Form.Dict.Color._super.create_widget.call(this);
this.color_input = jQuery('<input/>', {
'class': 'btn btn-default btn-sm',
'type': 'color',
'title': Sao.i18n.gettext(
'Select a color for "%1"', this.definition.string),
}).prependTo(this.el.find('.input-group-btn'));
this.color_input.change(this.set_color.bind(this));
},
set_color: function() {
this.input.val(this.color_input.val());
this.parent_widget.focus_out();
},
set_value: function(value) {
Sao.View.Form.Dict.Color._super.set_value.call(this, value);
this.color_input.val(value || '');
},
set_readonly: function(readonly) {
Sao.View.Form.Dict.Color._super.set_readonly.call(this, readonly);
this.color_input.prop('disabled', readonly);
},
});
Sao.View.Form.Dict.Boolean = Sao.class_(Sao.View.Form.Dict.Entry, {
class_: 'dict-boolean',
create_widget: function() {
@@ -5800,6 +5857,7 @@ function eval_pyson(value){
'boolean': Sao.View.Form.Boolean,
'callto': Sao.View.Form.CallTo,
'char': Sao.View.Form.Char,
'color': Sao.View.Form.Color,
'date': Sao.View.Form.Date,
'datetime': Sao.View.Form.DateTime,
'dict': Sao.View.Form.Dict,
+1
View File
@@ -1,3 +1,4 @@
* Support color widget on form view
Version 7.4.0 - 2024-11-04
--------------------------
@@ -17,7 +17,7 @@ from tryton.gui.window.code_scanner import CodeScanner
from . import View, XMLViewParser
from .form_gtk.binary import Binary
from .form_gtk.calendar_ import Date, DateTime, Time
from .form_gtk.char import Char, Password
from .form_gtk.char import Char, Color, Password
from .form_gtk.checkbox import CheckBox
from .form_gtk.dictionary import DictWidget
from .form_gtk.document import Document
@@ -167,6 +167,7 @@ class FormXMLViewParser(XMLViewParser):
'boolean': CheckBox,
'callto': CallTo,
'char': Char,
'color': Color,
'date': Date,
'datetime': DateTime,
'dict': DictWidget,
@@ -2,7 +2,7 @@
# this repository contains the full copyright notices and license terms.
import gettext
from gi.repository import GLib, Gtk
from gi.repository import Gdk, GLib, Gtk
from tryton.common import IconFactory, Tooltips
from tryton.common.entry_position import reset_position
@@ -177,3 +177,40 @@ class Password(Char):
else:
entry = self.entry
entry.props.visibility = not self.entry.props.visibility
class Color(Char):
def __init__(self, view, attrs):
super().__init__(view, attrs)
self.color_button = Gtk.ColorButton()
self.color_button.connect('color-set', self.set_color)
self.color_button.set_title(
_('Select a color for "%s"') % attrs['string'])
Tooltips().set_tip(self.color_button, _("Select a color"))
self.widget.pack_start(
self.color_button, expand=False, fill=True, padding=0)
def set_color(self, button):
if self.autocomplete:
entry = self.entry.get_child()
else:
entry = self.entry
rgba = self.color_button.get_rgba()
rgb = list(map(lambda x: int(x * 255), list(rgba)[:3]))
entry.set_text('#{:02X}{:02X}{:02X}'.format(*rgb))
self._focus_out()
def _readonly_set(self, value):
super()._readonly_set(value)
self.color_button.set_sensitive(not value)
def display(self):
super().display()
if self.field and self.record:
value = self.field.get_client(self.record)
rgba = Gdk.RGBA()
if value:
rgba.parse(value)
self.color_button.set_rgba(rgba)
@@ -9,7 +9,7 @@ import operator
from collections import defaultdict
from decimal import Decimal
from gi.repository import GLib, GObject, Gtk
from gi.repository import Gdk, GLib, GObject, Gtk
from tryton.common import (
IconFactory, Tooltips, timezoned_date, untimezoned_date)
@@ -83,6 +83,42 @@ class DictCharEntry(DictEntry):
return self.get_value() != (value.get(self.name, '') or '')
class DictColorEntry(DictCharEntry):
def create_widget(self):
self.entry = super().create_widget()
widget = Gtk.HBox()
widget.pack_start(self.entry, expand=True, fill=True, padding=0)
self.button = Gtk.ColorButton()
self.button.connect('color-set', self.set_color)
self.button.set_title(
_('Select a color for "%s"') % self.definition['string'])
Tooltips().set_tip(self.button, _("Select a color"))
widget.pack_start(self.button, expand=False, fill=True, padding=0)
return widget
def set_color(self, button):
rgba = self.button.get_rgba()
rgb = map(lambda x: int(x * 255), list(rgba)[:3])
self.entry.set_text('#{:02X}{:02X}{:02X}'.format(*rgb))
self.parent_widget._focus_out()
def get_value(self):
return self.entry.get_text()
def set_value(self, value):
self.entry.set_text(str(value or ''))
reset_position(self.entry)
rgba = Gdk.RGBA()
if value:
rgba.parse(value)
self.button.set_rgba(rgba)
def set_readonly(self, readonly):
self.entry.set_editable(not readonly)
self.button.set_sensitive(not readonly)
class DictBooleanEntry(DictEntry):
def create_widget(self):
@@ -417,6 +453,7 @@ class DictDateEntry(DictEntry):
DICT_ENTRIES = {
'char': DictCharEntry,
'color': DictColorEntry,
'boolean': DictBooleanEntry,
'selection': DictSelectionEntry,
'multiselection': DictMultiSelectionEntry,
+1
View File
@@ -1,3 +1,4 @@
* Add color widget to form view
* Limit access to database from the same series
* Fill wizard state view instance with default value
* Replace passlib by pwdlib
+1
View File
@@ -930,6 +930,7 @@ Class attributes are:
* boolean
* integer
* char
* color
* float
* numeric
* date
+3
View File
@@ -98,6 +98,9 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.message" id="msg_dict_schema_char">
<field name="text">Char</field>
</record>
<record model="ir.message" id="msg_dict_schema_color">
<field name="text">Color</field>
</record>
<record model="ir.message" id="msg_dict_schema_float">
<field name="text">Float</field>
</record>
+1
View File
@@ -48,6 +48,7 @@ attlist.field &=
| "boolean"
| "callto"
| "char"
| "color"
| "date"
| "datetime"
| "dict"
+1
View File
@@ -226,6 +226,7 @@
<value>boolean</value>
<value>callto</value>
<value>char</value>
<value>color</value>
<value>date</value>
<value>datetime</value>
<value>dict</value>
+1
View File
@@ -40,6 +40,7 @@ class DictSchemaMixin(object):
('boolean', lazy_gettext('ir.msg_dict_schema_boolean')),
('integer', lazy_gettext('ir.msg_dict_schema_integer')),
('char', lazy_gettext('ir.msg_dict_schema_char')),
('color', lazy_gettext('ir.msg_dict_schema_color')),
('float', lazy_gettext('ir.msg_dict_schema_float')),
('numeric', lazy_gettext('ir.msg_dict_schema_numeric')),
('date', lazy_gettext('ir.msg_dict_schema_date')),