changeset 4a71d8ca9a27 in tryton:default
details: https://hg.tryton.org/tryton?cmd=changeset;node=4a71d8ca9a27
description:
Use Mixin to share common behavior between Form and Dict widgets
The Integer and Float widgets of form and dict can share the same Entry
handlers.
issue7989
review66511002
diffstat:
tryton/gui/window/view_form/view/form_gtk/dictionary.py | 71 ++++------------
tryton/gui/window/view_form/view/form_gtk/float.py | 72 +++++++++-------
tryton/gui/window/view_form/view/form_gtk/integer.py | 38 +++++---
3 files changed, 80 insertions(+), 101 deletions(-)
diffs (269 lines):
diff -r 74557f917ae5 -r 4a71d8ca9a27
tryton/gui/window/view_form/view/form_gtk/dictionary.py
--- a/tryton/gui/window/view_form/view/form_gtk/dictionary.py Sun Feb 03
20:29:09 2019 +0100
+++ b/tryton/gui/window/view_form/view/form_gtk/dictionary.py Sun Feb 03
20:41:27 2019 +0100
@@ -10,6 +10,9 @@
from decimal import Decimal
from .widget import Widget
+from .integer import IntegerMixin
+from .float import FloatMixin
+
from tryton.gui.window.win_search import WinSearch
from tryton.common import Tooltips, timezoned_date, untimezoned_date, \
IconFactory
@@ -153,29 +156,15 @@
self.widget.set_sensitive(not readonly)
-class DictIntegerEntry(DictEntry):
+class DictIntegerEntry(IntegerMixin, DictEntry):
expand = False
fill = False
def create_widget(self):
widget = super(DictIntegerEntry, self).create_widget()
- widget.set_width_chars(8)
- widget.set_max_length(0)
- widget.set_alignment(1.0)
- widget.connect('insert-text', self.sig_insert_text)
+ self._prepare_entry(widget)
return widget
- def sig_insert_text(self, entry, new_text, new_text_length, position):
- value = entry.get_text()
- position = entry.get_position()
- new_value = value[:position] + new_text + value[position:]
- if new_value == '-':
- return
- try:
- locale.atoi(new_value)
- except ValueError:
- entry.stop_emission('insert-text')
-
def get_value(self):
txt_value = self.widget.get_text()
if txt_value:
@@ -194,42 +183,16 @@
reset_position(self.widget)
-class DictFloatEntry(DictIntegerEntry):
-
- def digits(self):
- default = (16, 2)
- record = self.parent_widget.record
- if not record:
- return default
- return tuple(y if x is None else x for x, y in zip(
- record.expr_eval(self.definition.get('digits', default)),
- default))
-
- def sig_insert_text(self, entry, new_text, new_text_length, position):
- value = entry.get_text()
- position = entry.get_position()
- new_value = value[:position] + new_text + value[position:]
- decimal_point = locale.localeconv()['decimal_point']
+class DictFloatEntry(FloatMixin, DictIntegerEntry):
- if new_value in ('-', decimal_point):
- return
-
- digits = self.digits()
-
- try:
- locale.atof(new_value)
- except ValueError:
- entry.stop_emission('insert-text')
- return
-
- new_int = new_value
- new_decimal = ''
- if decimal_point in new_value:
- new_int, new_decimal = new_value.rsplit(decimal_point, 1)
-
- if (len(new_int) > digits[0]
- or len(new_decimal) > digits[1]):
- entry.stop_emission('insert-text')
+ @property
+ def digits(self):
+ record = self.parent_widget.record
+ if record:
+ digits = record.expr_eval(self.definition.get('digits'))
+ if not digits or any(d is None for d in digits):
+ return
+ return digits
def get_value(self):
txt_value = self.widget.get_text()
@@ -241,14 +204,14 @@
return None
def set_value(self, value):
- digits = self.digits()
+ digits = self.digits
if value is not None:
- txt_val = locale.format('%.' + str(digits[1]) + 'f', value, True)
+ txt_val = locale.format('%.*f', (digits[1], value), True)
else:
txt_val = ''
- self.widget.set_width_chars(sum(digits))
self.widget.set_text(txt_val)
reset_position(self.widget)
+ self._set_entry_width(self.widget)
class DictNumericEntry(DictFloatEntry):
diff -r 74557f917ae5 -r 4a71d8ca9a27
tryton/gui/window/view_form/view/form_gtk/float.py
--- a/tryton/gui/window/view_form/view/form_gtk/float.py Sun Feb 03
20:29:09 2019 +0100
+++ b/tryton/gui/window/view_form/view/form_gtk/float.py Sun Feb 03
20:41:27 2019 +0100
@@ -2,51 +2,59 @@
# this repository contains the full copyright notices and license terms.
import gtk
import locale
-from .integer import Integer
+from .integer import Integer, IntegerMixin
-class Float(Integer):
- "Float"
-
- def __init__(self, view, attrs):
- super(Float, self).__init__(view, attrs)
- self.entry.connect('key-press-event', self.key_press_event)
+class FloatMixin(IntegerMixin):
+ _width_chars = 18
- def display(self):
- super(Float, self).display()
- if self.field:
- digits = self.field.digits(self.record, factor=self.factor)
- if digits:
- self.entry.set_width_chars(sum(digits))
- else:
- self.entry.set_width_chars(18)
+ def _prepare_entry(self, entry):
+ super()._prepare_entry(entry)
+ entry.connect('key-press-event', self._key_press_event)
- def key_press_event(self, widget, event):
- for name in ('KP_Decimal', 'KP_Separator'):
- if event.keyval == gtk.gdk.keyval_from_name(name):
- event.keyval = int(gtk.gdk.unicode_to_keyval(
- ord(locale.localeconv()['decimal_point'])))
-
- def sig_insert_text(self, entry, new_text, new_text_length, position):
- if not self.record:
- entry.stop_emission('insert-text')
- return
-
+ def _insert_text(self, entry, new_text, new_text_length, position):
value = entry.get_text()
position = entry.get_position()
new_value = value[:position] + new_text + value[position:]
decimal_point = locale.localeconv()['decimal_point']
-
- if new_value in ('-', decimal_point):
+ if new_value in ['-', decimal_point]:
return
-
- digits = self.field.digits(self.record, factor=self.factor)
-
try:
value = locale.atof(new_value)
except ValueError:
entry.stop_emission('insert-text')
return
-
+ digits = self.digits
if digits and not (round(value, digits[1]) == float(value)):
entry.stop_emission('insert-text')
+
+ def _key_press_event(self, entry, event):
+ for name in ['KP_Decimal', 'KP_Separator']:
+ if event.keyval == gtk.gdk.keyval_from_name(name):
+ event.keyval = int(gtk.gdk.unicode_to_keyval(
+ ord(locale.localeconv()['decimal_point'])))
+
+ @property
+ def digits(self):
+ return NotImplementedError
+
+ def _set_entry_width(self, entry):
+ digits = self.digits
+ if digits:
+ width = sum(digits)
+ else:
+ width = self._width_chars
+ entry.set_width_chars(width)
+
+
+class Float(FloatMixin, Integer):
+ "Float"
+
+ @property
+ def digits(self):
+ if self.field and self.record:
+ return self.field.digits(self.record, factor=self.factor)
+
+ def display(self):
+ super(Float, self).display()
+ self._set_entry_width(self.entry)
diff -r 74557f917ae5 -r 4a71d8ca9a27
tryton/gui/window/view_form/view/form_gtk/integer.py
--- a/tryton/gui/window/view_form/view/form_gtk/integer.py Sun Feb 03
20:29:09 2019 +0100
+++ b/tryton/gui/window/view_form/view/form_gtk/integer.py Sun Feb 03
20:41:27 2019 +0100
@@ -4,7 +4,28 @@
import locale
-class Integer(Char):
+class IntegerMixin:
+ _width_chars = 8
+
+ def _prepare_entry(self, entry):
+ entry.set_width_chars(self._width_chars)
+ entry.set_max_length(0)
+ entry.set_alignment(1.0)
+ entry.connect('insert-text', self._insert_text)
+
+ def _insert_text(self, entry, new_text, new_text_length, position):
+ value = entry.get_text()
+ position = entry.get_position()
+ new_value = value[:position] + new_text + value[position:]
+ if new_value == '-':
+ return
+ try:
+ locale.atoi(new_value)
+ except ValueError:
+ entry.stop_emission('insert-text')
+
+
+class Integer(IntegerMixin, Char):
"Integer"
def __init__(self, view, attrs):
@@ -14,9 +35,7 @@
self.entry)
self.widget.set_child_packing(self.entry, False, False,
padding, pack_type)
- self.entry.set_max_length(0)
- self.entry.set_alignment(1.0)
- self.entry.connect('insert_text', self.sig_insert_text)
+ self._prepare_entry(self.entry)
self.factor = float(attrs.get('factor', 1))
def set_value(self):
@@ -29,14 +48,3 @@
else:
value = self.field.get_client(self.record, factor=self.factor)
return value
-
- def sig_insert_text(self, entry, new_text, new_text_length, position):
- value = entry.get_text()
- position = entry.get_position()
- new_value = value[:position] + new_text + value[position:]
- if new_value == '-':
- return
- try:
- locale.atoi(new_value)
- except ValueError:
- entry.stop_emission('insert-text')