From 028cef72672a48aa4f7808e00a0e01c9df42143c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 9 Dec 2008 20:24:27 +0100 Subject: [PATCH] Handle invisible states on list view --- CHANGELOG | 1 + tryton/common/cellrendererbutton.py | 10 +++ tryton/common/cellrendererdate.py | 11 +++ tryton/common/cellrenderertext.py | 11 +++ tryton/common/cellrenderertoggle.py | 70 +++++++++++++++++++ tryton/gui/window/view_form/model/field.py | 8 +-- tryton/gui/window/view_form/view/list.py | 5 +- .../view_form/view/list_gtk/editabletree.py | 7 +- .../window/view_form/view/list_gtk/parser.py | 70 ++++++++++++------- 9 files changed, 157 insertions(+), 36 deletions(-) create mode 100644 tryton/common/cellrenderertoggle.py diff --git a/CHANGELOG b/CHANGELOG index 7b140d8ab6..09ac88933f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Handle invisible states on list view * Add user warnings * Add Model in logs * Allow to duplicate many records at once diff --git a/tryton/common/cellrendererbutton.py b/tryton/common/cellrendererbutton.py index f261dc9b90..035fe0bd16 100644 --- a/tryton/common/cellrendererbutton.py +++ b/tryton/common/cellrendererbutton.py @@ -9,6 +9,8 @@ class CellRendererButton(gtk.GenericCellRenderer): __gproperties__ = { "text": (gobject.TYPE_STRING, None, "Text", "Displayed text", gobject.PARAM_READWRITE), + 'visible': (gobject.TYPE_INT, 'Visible', + 'Visible', 0, 10, 0, gobject.PARAM_READWRITE), } __gsignals__ = { @@ -21,6 +23,7 @@ class CellRendererButton(gtk.GenericCellRenderer): self.text = text self.set_property('mode', gtk.CELL_RENDERER_MODE_EDITABLE) self.clicking = False + self.visible = True def do_set_property(self, pspec, value): setattr(self, pspec.name, value) @@ -30,6 +33,11 @@ class CellRendererButton(gtk.GenericCellRenderer): def on_render(self, window, widget, background_area, cell_area, expose_area, flags): + if not self.visible: + return + # Handle Pixmap window as pygtk failed + if type(window) == gtk.gdk.Pixmap: + return state = gtk.STATE_NORMAL shadow = gtk.SHADOW_OUT if self.clicking and flags & gtk.CELL_RENDERER_SELECTED: @@ -61,6 +69,8 @@ class CellRendererButton(gtk.GenericCellRenderer): def on_start_editing(self, event, widget, path, background_area, cell_area, flags): + if not self.visible: + return if (event is None) or ((event.type == gtk.gdk.BUTTON_PRESS) \ or (event.type == gtk.gdk.KEY_PRESS \ and event.keyval == gtk.keysyms.space)): diff --git a/tryton/common/cellrendererdate.py b/tryton/common/cellrendererdate.py index 01a149b9fd..92a204fd2f 100644 --- a/tryton/common/cellrendererdate.py +++ b/tryton/common/cellrendererdate.py @@ -19,6 +19,8 @@ class CellRendererDate(gtk.GenericCellRenderer): 'Background Set', 0, 10, 0, gobject.PARAM_READWRITE), 'editable': (gobject.TYPE_INT, 'Editable', 'Editable', 0, 10, 0, gobject.PARAM_READWRITE), + 'visible': (gobject.TYPE_INT, 'Visible', + 'Visible', 0, 10, 0, gobject.PARAM_READWRITE), } def __init__(self, format): @@ -31,9 +33,12 @@ class CellRendererDate(gtk.GenericCellRenderer): self.cmd = '' self.text = self._renderer.get_property('text') self.editable = self._renderer.get_property('editable') + self.visible = True def do_set_property(self, pspec, value): setattr(self, pspec.name, value) + if pspec.name == 'visible': + return self._renderer.set_property(pspec.name, value) self.set_property("mode", self._renderer.get_property("mode")) @@ -45,6 +50,8 @@ class CellRendererDate(gtk.GenericCellRenderer): def on_render(self, window, widget, background_area, cell_area, expose_area, flags): + if not self.visible: + return # Handle Pixmap window as pygtk failed if type(window) == gtk.gdk.Pixmap: layout = widget.create_pango_layout(self.text) @@ -60,11 +67,15 @@ class CellRendererDate(gtk.GenericCellRenderer): def on_activate(self, event, widget, path, background_area, cell_area, flags): + if not self.visible: + return return self._renderer.activate(event, widget, path, background_area, cell_area, flags) def on_start_editing(self, event, widget, path, background_area, cell_area, flags): + if not self.visible: + return editable = DateEntry(self.format, self._date_cb, self._process_cb) colormap = editable.get_colormap() diff --git a/tryton/common/cellrenderertext.py b/tryton/common/cellrenderertext.py index e4c64ba0fb..817a5fed30 100644 --- a/tryton/common/cellrenderertext.py +++ b/tryton/common/cellrenderertext.py @@ -21,6 +21,8 @@ class CellRendererText(gtk.GenericCellRenderer): 'Editable', 0, 10, 0, gobject.PARAM_READWRITE), 'xalign': (gobject.TYPE_FLOAT, 'XAlign', 'XAlign', 0, 1, 0, gobject.PARAM_READWRITE), + 'visible': (gobject.TYPE_INT, 'Visible', + 'Visible', 0, 10, 0, gobject.PARAM_READWRITE), } def __init__(self): @@ -30,9 +32,12 @@ class CellRendererText(gtk.GenericCellRenderer): self.text = self._renderer.get_property('text') self.editable = self._renderer.get_property('editable') + self.visible = True def do_set_property(self, pspec, value): setattr(self, pspec.name, value) + if pspec.name == 'visible': + return self._renderer.set_property(pspec.name, value) self.set_property("mode", self._renderer.get_property("mode")) @@ -44,6 +49,8 @@ class CellRendererText(gtk.GenericCellRenderer): def on_render(self, window, widget, background_area, cell_area, expose_area, flags): + if not self.visible: + return # Handle Pixmap window as pygtk failed if type(window) == gtk.gdk.Pixmap: layout = widget.create_pango_layout(self.text) @@ -59,11 +66,15 @@ class CellRendererText(gtk.GenericCellRenderer): def on_activate(self, event, widget, path, background_area, cell_area, flags): + if not self.visible: + return return self._renderer.activate(event, widget, path, background_area, cell_area, flags) def on_start_editing(self, event, widget, path, background_area, cell_area, flags): + if not self.visible: + return if not event: event = gtk.gdk.Event(gtk.keysyms.Tab) editable = self._renderer.start_editing(event, widget, path, diff --git a/tryton/common/cellrenderertoggle.py b/tryton/common/cellrenderertoggle.py new file mode 100644 index 0000000000..bd30bb73c1 --- /dev/null +++ b/tryton/common/cellrenderertoggle.py @@ -0,0 +1,70 @@ +#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 gtk +import gobject +import pango + + +class CellRendererToggle(gtk.GenericCellRenderer): + __gproperties__ = { + 'activatable': (gobject.TYPE_INT, 'Activatable', + 'Activatable', 0, 10, 0, gobject.PARAM_READWRITE), + 'visible': (gobject.TYPE_INT, 'Visible', + 'Visible', 0, 10, 0, gobject.PARAM_READWRITE), + } + + __gsignals__ = { + 'toggled': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, + (gobject.TYPE_STRING, )), + } + + def __init__(self): + self.__gobject_init__() + self._renderer = gtk.CellRendererToggle() + self._renderer.connect('toggled', self._sig_toggled) + self.set_property("mode", self._renderer.get_property("mode")) + + self.activatable = self._renderer.get_property('activatable') + self.visible = True + + def do_set_property(self, pspec, value): + setattr(self, pspec.name, value) + if pspec.name == 'visible': + return + self._renderer.set_property(pspec.name, value) + self.set_property("mode", self._renderer.get_property("mode")) + + def do_get_property(self, pspec): + return getattr(self, pspec.name) + + def on_get_size(self, widget, cell_area): + return self._renderer.get_size(widget, cell_area) + + def on_render(self, window, widget, background_area, cell_area, + expose_area, flags): + if not self.visible: + return + # Handle Pixmap window as pygtk failed + if type(window) == gtk.gdk.Pixmap: + return + return self._renderer.render(window, widget, background_area, + cell_area, expose_area, flags) + + def on_activate(self, event, widget, path, background_area, cell_area, + flags): + if not self.visible: + return + return self._renderer.activate(event, widget, path, background_area, + cell_area, flags) + + def get_active(self): + return self._renderer.get_active() + + def set_active(self, setting): + return self._renderer.set_active(setting) + + def _sig_toggled(self, renderer, path): + if self.activatable and self.visible: + self.emit('toggled', path) + +gobject.type_register(CellRendererToggle) diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py index bf8af54c57..d421f92562 100644 --- a/tryton/gui/window/view_form/model/field.py +++ b/tryton/gui/window/view_form/model/field.py @@ -108,14 +108,14 @@ class CharField(object): def create(self, model): return False - def state_set(self, model): + def state_set(self, model, states=('readonly', 'required', 'invisible')): state_changes = self.attrs.get('states', {}) if isinstance(state_changes, basestring): try: state_changes = eval(state_changes) except: return - for key in ('readonly', 'required', 'invisible'): + for key in states: if key == 'readonly' and self.attrs.get(key, False): continue if key in state_changes: @@ -550,8 +550,8 @@ class O2MField(CharField): self.get_state_attrs(model)['valid'] = res return res - def state_set(self, model): - super(O2MField, self).state_set(model) + def state_set(self, model, states=('readonly', 'required', 'invisible')): + super(O2MField, self).state_set(model, states=states) if self.get_state_attrs(model).get('readonly', False): model.value[self.name].readonly = True else: diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py index 141c8c0712..77724eabb8 100644 --- a/tryton/gui/window/view_form/view/list.py +++ b/tryton/gui/window/view_form/view/list.py @@ -11,6 +11,7 @@ import gettext import tryton.common as common from tryton.config import CONFIG from tryton.common.cellrendererbutton import CellRendererButton +from tryton.common.cellrenderertoggle import CellRendererToggle _ = gettext.gettext @@ -561,7 +562,7 @@ class ViewList(ParserView): if not renderers: continue renderer = renderers[0] - if isinstance(renderer, gtk.CellRendererToggle): + if isinstance(renderer, CellRendererToggle): editable = renderer.get_property('activatable') elif isinstance(renderer, (gtk.CellRendererProgress, CellRendererButton)): @@ -595,7 +596,7 @@ class ViewList(ParserView): self.widget_tree.editable = False for col in self.widget_tree.get_columns(): for renderer in col.get_cell_renderers(): - if isinstance(renderer, gtk.CellRendererToggle): + if isinstance(renderer, CellRendererToggle): renderer.set_property('activatable', False) elif isinstance(renderer, (gtk.CellRendererProgress, CellRendererButton)): diff --git a/tryton/gui/window/view_form/view/list_gtk/editabletree.py b/tryton/gui/window/view_form/view/list_gtk/editabletree.py index 3febdbf847..3286394116 100644 --- a/tryton/gui/window/view_form/view/list_gtk/editabletree.py +++ b/tryton/gui/window/view_form/view/list_gtk/editabletree.py @@ -3,6 +3,7 @@ import gtk import parser import gettext from tryton.common.cellrendererbutton import CellRendererButton +from tryton.common.cellrenderertoggle import CellRendererToggle _ = gettext.gettext @@ -74,7 +75,7 @@ class EditableTreeView(gtk.TreeView): if not cols[idx].get_cell_renderers(): continue renderer = cols[idx].get_cell_renderers()[0] - if isinstance(renderer, gtk.CellRendererToggle): + if isinstance(renderer, CellRendererToggle): editable = renderer.get_property('activatable') elif isinstance(renderer, (gtk.CellRendererProgress, CellRendererButton)): @@ -93,7 +94,7 @@ class EditableTreeView(gtk.TreeView): if not cols[idx].get_cell_renderers(): continue renderer = cols[idx].get_cell_renderers()[0] - if isinstance(renderer, gtk.CellRendererToggle): + if isinstance(renderer, CellRendererToggle): editable = renderer.get_property('activatable') elif isinstance(renderer, (gtk.CellRendererProgress, CellRendererButton)): @@ -176,7 +177,7 @@ class EditableTreeView(gtk.TreeView): col = None for column in self.get_columns(): renderer = column.get_cell_renderers()[0] - if isinstance(renderer, gtk.CellRendererToggle): + if isinstance(renderer, CellRendererToggle): editable = renderer.get_property('activatable') elif isinstance(renderer, (gtk.CellRendererProgress, CellRendererButton)): diff --git a/tryton/gui/window/view_form/view/list_gtk/parser.py b/tryton/gui/window/view_form/view/list_gtk/parser.py index 2c290b3616..9734dbbb1f 100644 --- a/tryton/gui/window/view_form/view/list_gtk/parser.py +++ b/tryton/gui/window/view_form/view/list_gtk/parser.py @@ -23,6 +23,7 @@ import tryton.common as common from tryton.common.cellrendererbutton import CellRendererButton from tryton.common.cellrendererdate import CellRendererDate from tryton.common.cellrenderertext import CellRendererText +from tryton.common.cellrenderertoggle import CellRendererToggle from tryton.action import Action from tryton.translate import date_format import mx.DateTime @@ -107,7 +108,7 @@ class ParserTree(ParserInterface): renderer = cell.renderer readonly = not (editable and not node_attrs.get('readonly', False)) - if isinstance(renderer, gtk.CellRendererToggle): + if isinstance(renderer, CellRendererToggle): renderer.set_property('activatable', not readonly) elif isinstance(renderer, (gtk.CellRendererProgress, CellRendererButton)): @@ -247,41 +248,61 @@ class Char(object): def setter(self, column, cell, store, iter): model = store.get_value(iter, 0) text = self.get_textual_value(model) - cell.set_property('text', text) - fg_color = self.get_color(model) - cell.set_property('foreground', fg_color) - if fg_color == 'black': - cell.set_property('foreground-set', False) + + if isinstance(cell, CellRendererToggle): + cell.set_active(bool(text)) else: - cell.set_property('foreground-set', True) + cell.set_property('text', text) + fg_color = self.get_color(model) + cell.set_property('foreground', fg_color) + if fg_color == 'black': + cell.set_property('foreground-set', False) + else: + cell.set_property('foreground-set', True) + if self.attrs['type'] in ('float', 'integer', 'biginteger', 'boolean', 'numeric', 'float_time'): align = 1 else: align = 0 + + states = ('invisible') + if hasattr(self.treeview, 'editable') \ + and self.treeview.editable: + states = ('readonly', 'required', 'invisible') + + field = model[self.field_name] + field.state_set(model, states=states) + invisible = field.get_state_attrs(model).get('invisible', False) + cell.set_property('visible', not invisible) + if hasattr(self.treeview, 'editable') \ and self.treeview.editable: - field = model[self.field_name] - field.state_set(model) - bg_color = 'white' - if not field.get_state_attrs(model).get('valid', True): - bg_color = COLORS.get('invalid', 'white') - elif bool(int(field.get_state_attrs(model).get('required', 0))): - bg_color = COLORS.get('required', 'white') - cell.set_property('background', bg_color) - if bg_color == 'white': - cell.set_property('background-set', False) - else: - cell.set_property('background-set', True) - cell.set_property('foreground-set', True) readonly = field.get_state_attrs(model).get('readonly', False) - if isinstance(cell, gtk.CellRendererToggle): + if invisible: + readonly = True + + if not isinstance(cell, CellRendererToggle): + bg_color = 'white' + if not field.get_state_attrs(model).get('valid', True): + bg_color = COLORS.get('invalid', 'white') + elif bool(int(field.get_state_attrs(model).get('required', 0))): + bg_color = COLORS.get('required', 'white') + cell.set_property('background', bg_color) + if bg_color == 'white': + cell.set_property('background-set', False) + else: + cell.set_property('background-set', True) + cell.set_property('foreground-set', True) + + if isinstance(cell, CellRendererToggle): cell.set_property('activatable', not readonly) elif isinstance(cell, (gtk.CellRendererProgress, CellRendererButton)): pass else: cell.set_property('editable', not readonly) + cell.set_property('xalign', align) def get_color(self, model): @@ -314,17 +335,12 @@ class Boolean(Int): def __init__(self, *args): super(Boolean, self).__init__(*args) - self.renderer = gtk.CellRendererToggle() + self.renderer = CellRendererToggle() self.renderer.connect('toggled', self._sig_toggled) def get_textual_value(self, model): return model[self.field_name].get_client(model) - def setter(self, column, cell, store, iter): - model = store.get_value(iter, 0) - value = self.get_textual_value(model) - cell.set_active(bool(value)) - def _sig_toggled(self, renderer, path): store = self.treeview.get_model() model = store.get_value(store.get_iter(path), 0)