File: number_entry.py

package info (click to toggle)
tryton-client 7.0.27-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,476 kB
  • sloc: python: 27,180; sh: 37; makefile: 18
file content (105 lines) | stat: -rw-r--r-- 3,644 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# This file is part of Tryton.  The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import gettext
import locale
from decimal import Decimal, InvalidOperation

from gi.repository import Gdk, GObject, Gtk

__all__ = ['NumberEntry']

_ = gettext.gettext


class NumberEntry(Gtk.Entry, Gtk.Editable):
    # Override Editable to avoid modify the base implementation of Entry
    __gtype_name__ = 'NumberEntry'
    __digits = None

    def __init__(self, *args, **kwargs):
        self.monetary = kwargs.pop('monetary', False)
        self.convert = kwargs.pop('convert', float)
        super().__init__(*args, **kwargs)
        self.set_alignment(1.0)
        self.connect('key-press-event', self.__class__.__key_press_event)

    @GObject.Property(
        default=None, nick=_("Digits"), blurb=_("The number of decimal"))
    def digits(self):
        return self.__digits

    @digits.setter
    def digits(self, value):
        self.__digits = value

    @GObject.Property
    def value(self):
        text = self.get_text()
        if text:
            try:
                return self.convert(locale.delocalize(text, self.monetary))
            except ValueError:
                pass
        return None

    @property
    def __decimal_point(self):
        return locale.localeconv()[
            self.monetary and 'mon_decimal_point' or 'decimal_point']

    @property
    def __thousands_sep(self):
        return locale.localeconv()[
            self.monetary and 'mon_thousands_sep' or 'thousands_sep']

    # XXX: Override vfunc because position is inout
    # https://gitlab.gnome.org/GNOME/pygobject/issues/12
    def do_insert_text(self, new_text, length, position):
        buffer_ = self.get_buffer()
        text = self.get_buffer().get_text()
        text = text[:position] + new_text + text[position:]
        value = None
        if text not in ['-', self.__decimal_point, self.__thousands_sep]:
            try:
                value = Decimal(locale.delocalize(text, self.monetary))
            except (ValueError, InvalidOperation):
                return position
        try:
            if (value and self.__digits is not None
                    and (round(value, self.__digits) != value
                        or value.as_tuple().exponent < -self.__digits)):
                return position
        except InvalidOperation:
            return position
        length = len(new_text.encode('utf-8'))
        buffer_.insert_text(position, new_text, length)
        return position + length

    def __key_press_event(self, event):
        for name in ['KP_Decimal', 'KP_Separator']:
            if event.keyval == Gdk.keyval_from_name(name):
                text = self.__decimal_point
                if self.get_selection_bounds():
                    self.delete_text(*self.get_selection_bounds())
                self.do_insert_text(
                    text, len(text), self.props.cursor_position)
                self.set_position(self.props.cursor_position + len(text))
                return True


GObject.type_register(NumberEntry)


if __name__ == '__main__':
    win = Gtk.Window()
    win.connect('delete-event', Gtk.main_quit)
    vbox = Gtk.VBox()
    e = NumberEntry()
    vbox.pack_start(NumberEntry(), expand=False, fill=False, padding=0)
    vbox.pack_start(NumberEntry(digits=2), expand=False, fill=False, padding=0)
    vbox.pack_start(NumberEntry(digits=0), expand=False, fill=False, padding=0)
    vbox.pack_start(
        NumberEntry(digits=-2), expand=False, fill=False, padding=0)
    win.add(vbox)
    win.show_all()
    Gtk.main()