From a2bbd1acd2f50f05bccbe25adb975dcf31d2eaad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 6 Feb 2008 19:23:56 +0100 Subject: [PATCH] Allow to use invisibility in form and improve the states behavior --- tryton/gui/window/view_form/model/field.py | 6 +- .../window/view_form/view/form_gtk/char.py | 29 ++++---- .../window/view_form/view/form_gtk/float.py | 16 ++-- .../window/view_form/view/form_gtk/integer.py | 20 ++--- .../view_form/view/form_gtk/interface.py | 12 +++ .../window/view_form/view/form_gtk/parser.py | 73 +++++++++++++++---- .../gui/window/view_form/view/form_gtk/url.py | 1 - 7 files changed, 108 insertions(+), 49 deletions(-) diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py index 336d59b376..b899cb0172 100644 --- a/tryton/gui/window/view_form/model/field.py +++ b/tryton/gui/window/view_form/model/field.py @@ -91,11 +91,13 @@ class CharField(object): if values is None: values = {'state': 'draft'} state_changes = self.attrs.get('states', {}) - for key in ('readonly', 'required'): + if isinstance(state_changes, str): + state_changes = eval(state_changes) + for key in ('readonly', 'required', 'invisible'): if key in state_changes: self.get_state_attrs(model)[key] = \ eval(state_changes[key], values) - else: + elif key in self.attrs: self.get_state_attrs(model)[key] = self.attrs[key] if 'value' in state_changes: value = eval(state_changes['value'], values) diff --git a/tryton/gui/window/view_form/view/form_gtk/char.py b/tryton/gui/window/view_form/view/form_gtk/char.py index d80982d0a4..64da227b6c 100644 --- a/tryton/gui/window/view_form/view/form_gtk/char.py +++ b/tryton/gui/window/view_form/view/form_gtk/char.py @@ -7,28 +7,29 @@ class Char(WidgetInterface): def __init__(self, window, parent, model, attrs=None): super(Char, self).__init__(window, parent, model=model, attrs=attrs) - self.widget = gtk.Entry() - self.widget.set_property('activates_default', True) - self.widget.set_max_length(int(attrs.get('size', 16))) - self.widget.set_visibility(not attrs.get('invisible', False)) - self.widget.set_width_chars(5) + self.widget = gtk.HBox() + self.entry = gtk.Entry() + self.entry.set_property('activates_default', True) + self.entry.set_max_length(int(attrs.get('size', 16))) + self.entry.set_width_chars(5) - self.widget.connect('button_press_event', self._menu_open) - self.widget.connect('activate', self.sig_activate) - self.widget.connect('focus-in-event', lambda x, y: self._focus_in()) - self.widget.connect('focus-out-event', lambda x, y: self._focus_out()) + self.entry.connect('button_press_event', self._menu_open) + self.entry.connect('activate', self.sig_activate) + self.entry.connect('focus-in-event', lambda x, y: self._focus_in()) + self.entry.connect('focus-out-event', lambda x, y: self._focus_out()) + self.widget.pack_start(self.entry) def set_value(self, model, model_field): - return model_field.set_client(model, self.widget.get_text() or False) + return model_field.set_client(model, self.entry.get_text() or False) def display(self, model, model_field): super(Char, self).display(model, model_field) if not model_field: - self.widget.set_text('') + self.entry.set_text('') return False - self.widget.set_text(model_field.get(model) or '') + self.entry.set_text(model_field.get(model) or '') def _readonly_set(self, value): super(Char, self)._readonly_set(value) - self.widget.set_editable(not value) - self.widget.set_sensitive(not value) + self.entry.set_editable(not value) + self.entry.set_sensitive(not value) diff --git a/tryton/gui/window/view_form/view/form_gtk/float.py b/tryton/gui/window/view_form/view/form_gtk/float.py index a1f40cdfae..4d4d9d808e 100644 --- a/tryton/gui/window/view_form/view/form_gtk/float.py +++ b/tryton/gui/window/view_form/view/form_gtk/float.py @@ -12,7 +12,7 @@ class Float(Integer): def set_value(self, model, model_field): try: - value = locale.atof(self.widget.get_text()) + value = locale.atof(self.entry.get_text()) except: value = 0.0 return model_field.set_client(model, value) @@ -20,17 +20,17 @@ class Float(Integer): def display(self, model, model_field): super(Char, self).display(model, model_field) if not model_field: - self.widget.set_text('') + self.entry.set_text('') return False - self.widget.set_text(locale.format('%.' + str(self.digits[1]) + 'f', + self.entry.set_text(locale.format('%.' + str(self.digits[1]) + 'f', model_field.get(model) or 0.0, True)) - def sig_insert_text(self, widget, new_text, new_text_length, position): - value = widget.get_text() - position = widget.get_position() + 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:] try: if len(str(int(locale.atof(new_value)))) > self.digits[0]: - widget.stop_emission('insert-text') + entry.stop_emission('insert-text') except: - widget.stop_emission('insert-text') + entry.stop_emission('insert-text') 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 c0affbe94a..32fbd1e8fb 100644 --- a/tryton/gui/window/view_form/view/form_gtk/integer.py +++ b/tryton/gui/window/view_form/view/form_gtk/integer.py @@ -7,13 +7,13 @@ class Integer(Char): def __init__(self, window, parent, model, attrs=None): super(Integer, self).__init__(window, parent, model=model, attrs=attrs) - self.widget.set_max_length(0) - self.widget.set_alignment(1.0) - self.widget.connect('insert_text', self.sig_insert_text) + self.entry.set_max_length(0) + self.entry.set_alignment(1.0) + self.entry.connect('insert_text', self.sig_insert_text) def set_value(self, model, model_field): try: - value = locale.atoi(self.widget.get_text()) + value = locale.atoi(self.entry.get_text()) except: value = 0 return model_field.set_client(model, value) @@ -21,16 +21,16 @@ class Integer(Char): def display(self, model, model_field): super(Char, self).display(model, model_field) if not model_field: - self.widget.set_text('') + self.entry.set_text('') return False - self.widget.set_text(locale.format('%d', + self.entry.set_text(locale.format('%d', model_field.get(model) or 0, True)) - def sig_insert_text(self, widget, new_text, new_text_length, position): - value = widget.get_text() - position = widget.get_position() + 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:] try: locale.atoi(new_value) except: - widget.stop_emission('insert-text') + entry.stop_emission('insert-text') diff --git a/tryton/gui/window/view_form/view/form_gtk/interface.py b/tryton/gui/window/view_form/view/form_gtk/interface.py index aa97b758a2..ff177ff3ee 100644 --- a/tryton/gui/window/view_form/view/form_gtk/interface.py +++ b/tryton/gui/window/view_form/view/form_gtk/interface.py @@ -116,6 +116,9 @@ class WidgetInterface(object): def _color_widget(self): return self.widget + def _invisible_widget(self): + return self.widget + def color_set(self, name): widget = self._color_widget() colormap = widget.get_colormap() @@ -126,6 +129,13 @@ class WidgetInterface(object): widget.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("black")) widget.modify_text(gtk.STATE_INSENSITIVE, gtk.gdk.color_parse("black")) + def invisible_set(self, value): + widget = self._invisible_widget() + if value and value != '0': + widget.hide() + else: + widget.show() + def _menu_sig_default_set(self): deps = [] for wname, wview in self._view.view_form.widgets.items(): @@ -178,6 +188,8 @@ class WidgetInterface(object): self.color_set('required') else: self.color_set('normal') + self.invisible_set(modelfield.get_state_attrs(model).\ + get('invisible', False)) def sig_changed(self): if self.attrs.get('on_change', False): diff --git a/tryton/gui/window/view_form/view/form_gtk/parser.py b/tryton/gui/window/view_form/view/form_gtk/parser.py index 53f29d3d74..0313fc3d31 100644 --- a/tryton/gui/window/view_form/view/form_gtk/parser.py +++ b/tryton/gui/window/view_form/view/form_gtk/parser.py @@ -67,7 +67,9 @@ class Button(object): self.form.screen.display() def state_set(self, values): - state_changes = eval(self.attrs.get('states', {})) + state_changes = self.attrs.get('states', {}) + if isinstance(state_changes, str): + state_changes = eval(state_changes) if 'invisible' in state_changes: if eval(state_changes['invisible'], values): self.widget.hide() @@ -76,6 +78,43 @@ class Button(object): else: self.widget.show() +class Label(gtk.Label): + + def __init__(self, str=None, attrs=None): + super(Label, self).__init__(str=str) + self.attrs = attrs or {} + + def state_set(self, values): + state_changes = self.attrs.get('states', {}) + if isinstance(state_changes, str): + state_changes = eval(state_changes) + if 'invisible' in state_changes: + if eval(state_changes['invisible'], values): + self.hide() + else: + self.show() + else: + self.show() + + +class VBox(gtk.VBox): + + def __init__(self, homogeneous=False, spacing=0, attrs=None): + super(VBox, self).__init__(homogeneous, spacing) + self.attrs = attrs or {} + + def state_set(self, values): + state_changes = self.attrs.get('states', {}) + if isinstance(state_changes, str): + state_changes = eval(state_changes) + if 'invisible' in state_changes: + if eval(state_changes['invisible'], values): + self.hide() + else: + self.show() + else: + self.show() + class _container(object): def __init__(self, tooltips): @@ -108,7 +147,8 @@ class _container(object): table.resize(height + 1, self.col[-1]) def wid_add(self, widget, name='', expand=False, ypadding=2, rowspan=1, - colspan=1, translate=False, fname=None, help_tip=False, fill=False, xexpand=True, xfill=True): + colspan=1, translate=False, fname=None, help_tip=False, fill=False, + xexpand=True, xfill=True): (table, width, height) = self.cont[-1] if colspan > self.col[-1]: colspan = self.col[-1] @@ -125,24 +165,23 @@ class _container(object): xopt = xopt | gtk.EXPAND if xfill: xopt = xopt | gtk.FILL - hbox = gtk.HBox(spacing=3) - hbox.pack_start(widget) + widget = widget if help_tip: self.tooltips.set_tip(widget, help_tip) self.tooltips.enable() - if translate: + if translate and hasattr(widget, 'pack_start'): button = gtk.Button() img = gtk.Image() img.set_from_stock('gtk-preferences', gtk.ICON_SIZE_BUTTON) button.set_image(img) button.set_relief(gtk.RELIEF_NONE) self.trans_box.append((button, name, fname, widget)) - hbox.pack_start(button, fill=False, expand=False) - hbox.show_all() - table.attach(hbox, width, width + colspan, + widget.pack_start(button, fill=False, expand=False) + widget.show_all() + table.attach(widget, width, width + colspan, height, height + rowspan, yoptions=yopt, ypadding=ypadding, - xoptions=xopt, xpadding=2) + xoptions=xopt, xpadding=0) self.cont[-1] = (table, width + colspan, height) wid_list = table.get_children() wid_list.reverse() @@ -178,12 +217,17 @@ class ParserForm(ParserInterface): help_tip=attrs.get('help', False), fill=int(attrs.get('fill', 0))) elif node.localName == 'separator': - vbox = gtk.VBox() + text = attrs.get('string', '') if 'string' in attrs or 'name' in attrs: - text = attrs.get('string', '') if not text: if 'name' in attrs and attrs['name'] in fields: + if 'states' in fields[attrs['name']]: + attrs['states'] = \ + fields[attrs['name']]['states'] text = fields[attrs['name']]['string'] + vbox = VBox(attrs=attrs) + button_list.append(vbox) + if text: label = gtk.Label(text) label.set_alignment(0.0, 0.5) vbox.pack_start(label) @@ -196,6 +240,8 @@ class ParserForm(ParserInterface): text = attrs.get('string', '') if not text: if 'name' in attrs and attrs['name'] in fields: + if 'states' in fields[attrs['name']]: + attrs['states'] = fields[attrs['name']]['states'] if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: text = _(':') + fields[attrs['name']]['string'] else: @@ -208,7 +254,8 @@ class ParserForm(ParserInterface): text += node.data else: text += node.toxml() - label = gtk.Label(text) + label = Label(text, attrs) + button_list.append(label) label.set_use_markup(True) if 'align' in attrs: label.set_alignment(float(attrs['align'] or 0.0), 0.5) @@ -277,8 +324,6 @@ class ParserForm(ParserInterface): fields[name]['model'] = model if not ftype in WIDGETS_TYPE: continue - if attrs.get('invisible', False): - continue fields[name]['name'] = name if 'saves' in attrs: diff --git a/tryton/gui/window/view_form/view/form_gtk/url.py b/tryton/gui/window/view_form/view/form_gtk/url.py index 718e73f4ec..1101f8e042 100644 --- a/tryton/gui/window/view_form/view/form_gtk/url.py +++ b/tryton/gui/window/view_form/view/form_gtk/url.py @@ -15,7 +15,6 @@ class URL(WidgetInterface): self.entry = gtk.Entry() self.entry.set_max_length(int(attrs.get('size', 16))) - self.entry.set_visibility(not attrs.get('invisible', False)) self.entry.set_width_chars(5) self.entry.set_property('activates_default', True) self.entry.connect('activate', self.sig_activate)