From 449b6b2b4c32e2e1267f7fe0223c333f252f159f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 9 Oct 2020 19:09:06 +0200 Subject: [PATCH] Add symbol widget issue9059 review276871002 --- CHANGELOG | 1 + COPYRIGHT | 3 ++ tryton/gui/window/about.py | 1 + tryton/gui/window/view_form/model/field.py | 22 +++++++++ tryton/gui/window/view_form/screen/screen.py | 3 ++ .../window/view_form/view/form_gtk/integer.py | 25 +++++++++++ tryton/gui/window/view_form/view/list.py | 2 + .../window/view_form/view/list_gtk/widget.py | 45 +++++++++++++++++++ 8 files changed, 102 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 29436328e2..d7b32927db 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Manage symbol widget * Fallback to model name as title * Manage deletable and writable state * Support e-mail template diff --git a/COPYRIGHT b/COPYRIGHT index 7487054a0a..9b15636420 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -8,6 +8,9 @@ Copyright (C) 2008-2020 B2CK SPRL. Copyright (C) 2010-2019 Nicolas Évrard. Copyright (C) 2011-2012 Rodrigo Hübner. Copyright (C) 2012-2013 Antoine Smolders. +Copyright (C) 2020 Maxime Richez +Copyright (C) 2020 SALUC SA + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/tryton/gui/window/about.py b/tryton/gui/window/about.py index 6a39a64966..efb717635d 100644 --- a/tryton/gui/window/about.py +++ b/tryton/gui/window/about.py @@ -19,6 +19,7 @@ AUTHORS = [ 'Hartmut Goebel', 'Korbinian Preisler ', 'Mathias Behrle ', + 'Maxime Richez ', 'Nicolas Évrard ', 'Sednacom ', 'Udo Spallek ', diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py index c41c16c1d5..1dc04c3f6f 100644 --- a/tryton/gui/window/view_form/model/field.py +++ b/tryton/gui/window/view_form/model/field.py @@ -355,6 +355,28 @@ class FloatField(Field): shift = int(round(math.log(abs(factor), 10))) return (digits[0] + shift, digits[1] - shift) + def get_symbol(self, record, symbol): + if record and symbol in record.group.fields: + value = self.get(record) or 0 + sign = 1 + if value < 0: + sign = -1 + elif value == 0: + sign = 0 + symbol_field = record.group.fields[symbol] + symbol_name = symbol_field.attrs.get('relation') + symbol_id = symbol_field.get(record) + if symbol_name and symbol_id is not None and symbol_id >= 0: + try: + return RPCExecute( + 'model', symbol_name, 'get_symbol', symbol_id, sign, + context=record.get_context()) + except RPCException: + logger.warn( + "Fail to fetch symbol for %s,%s", + symbol_name, symbol_id) + return '', 1 + def convert(self, value): try: return locale.atof(value) diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index 28d8eb4d00..d08a7e5082 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -209,6 +209,9 @@ class Screen(SignalEvent): for attr in ['string', 'factor']: if attributes.get(attr): ofields[name][attr] = attributes[attr] + symbol = attributes.get('symbol') + if symbol and symbol not in ofields: + ofields[symbol] = fields[symbol] fields = ofields if 'active' in view_tree['fields']: diff --git a/tryton/gui/window/view_form/view/form_gtk/integer.py b/tryton/gui/window/view_form/view/form_gtk/integer.py index 1d1de2ad9e..80269a953c 100644 --- a/tryton/gui/window/view_form/view/form_gtk/integer.py +++ b/tryton/gui/window/view_form/view/form_gtk/integer.py @@ -18,8 +18,17 @@ class Integer(Widget): self.entry.connect('activate', self.sig_activate) self.entry.connect('focus-out-event', lambda *a: self._focus_out()) self.entry.connect('key-press-event', self.send_modified) + self.symbol = attrs.get('symbol') + if self.symbol: + self.symbol_start = Gtk.Entry(editable=False) + self.widget.pack_start( + self.symbol_start, expand=False, fill=False, padding=1) self.widget.pack_start(self.entry, expand=False, fill=False, padding=0) self.factor = float(attrs.get('factor', 1)) + if self.symbol: + self.symbol_end = Gtk.Entry(editable=False) + self.widget.pack_start( + self.symbol_end, expand=False, fill=False, padding=1) @property def modified(self): @@ -47,8 +56,24 @@ class Integer(Widget): return 8 def display(self): + def set_symbol(entry, text): + if text: + entry.set_text(text) + entry.set_width_chars(len(text) + 1) + entry.show() + else: + entry.set_text('') + entry.hide() super().display() self.entry.set_width_chars(self.width) + if self.field and self.symbol: + symbol, position = self.field.get_symbol(self.record, self.symbol) + if position < 0.5: + set_symbol(self.symbol_start, symbol) + set_symbol(self.symbol_end, '') + else: + set_symbol(self.symbol_start, '') + set_symbol(self.symbol_end, symbol) value = self.get_client_value() self.entry.set_text(value) reset_position(self.entry) diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py index d38e25363f..9471f85b8c 100644 --- a/tryton/gui/window/view_form/view/list.py +++ b/tryton/gui/window/view_form/view/list.py @@ -414,6 +414,8 @@ class TreeXMLViewParser(XMLViewParser): width = int(attributes['width']) elif field_attrs: width = default_width.get(field_attrs['type'], 100) + if attributes.get('symbol'): + width += 20 else: width = 80 column.width = width diff --git a/tryton/gui/window/view_form/view/list_gtk/widget.py b/tryton/gui/window/view_form/view/list_gtk/widget.py index 7a0bb84dbd..92228d770f 100644 --- a/tryton/gui/window/view_form/view/list_gtk/widget.py +++ b/tryton/gui/window/view_form/view/list_gtk/widget.py @@ -207,6 +207,35 @@ class Affix(Cell): webbrowser.open(value, new=2) +class Symbol(Cell): + expand = False + + def __init__(self, view, attrs, position): + super().__init__() + self.attrs = attrs + self.symbol = attrs.get('symbol') + self.position = position + self.renderer = Gtk.CellRendererText() + self.view = view + + @realized + @CellCache.cache + def setter(self, column, cell, store, iter_, user_data=None): + record, field = self._get_record_field_from_iter(iter_, store) + invisible = field.get_state_attrs(record).get('invisible', False) + if invisible: + cell.set_property('text', '') + cell.set_property('visible', not invisible) + return + symbol, position = field.get_symbol(record, self.symbol) + if round(position) == self.position: + cell.set_property('text', symbol) + cell.set_property('visible', True) + else: + cell.set_property('text', '') + cell.set_property('visible', False) + + class GenericText(Cell): align = 0 editable = None @@ -328,6 +357,22 @@ class Int(GenericText): renderer = CellRendererInteger super(Int, self).__init__(view, attrs, renderer=renderer) self.factor = float(attrs.get('factor', 1)) + self.symbol = attrs.get('symbol') + if self.symbol: + self.renderer_prefix = Symbol(view, attrs, 0) + self.renderer_suffix = Symbol(view, attrs, 1) + + @property + def prefixes(self): + if self.symbol: + return [self.renderer_prefix] + return [] + + @property + def suffixes(self): + if self.symbol: + return [self.renderer_suffix] + return [] def get_textual_value(self, record): if not record: