From 3cae98b262853266908a0c1961f577e8bc04da59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 3 Feb 2022 23:13:27 +0100 Subject: [PATCH] Add optional column on tree view issue10989 review374321002 --- CHANGELOG | 1 + tryton/common/popup_menu.py | 17 ++++++ tryton/gui/window/form.py | 17 +----- tryton/gui/window/view_form/screen/screen.py | 1 + tryton/gui/window/view_form/view/list.py | 56 +++++++++++++++++++- 5 files changed, 75 insertions(+), 17 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 9b86301c0d..f7b004a115 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Manage optional column * Default CSV encoding to UTF8 with BOM * Display the number of selected records * Humanize the count result diff --git a/tryton/common/popup_menu.py b/tryton/common/popup_menu.py index b578c5d9d8..0878cfec66 100644 --- a/tryton/common/popup_menu.py +++ b/tryton/common/popup_menu.py @@ -143,3 +143,20 @@ def populate(menu, model, record, title='', field=None, context=None): action_menu.append(email_item) email_item.connect('activate', email, toolbar) menu.show_all() + + +def popup(menu, widget): + def menu_position(menu, x, y, user_data): + widget_allocation = widget.get_allocation() + x, y = widget.get_window().get_root_coords( + widget_allocation.x, widget_allocation.y) + return (x, y + widget_allocation.height, False) + menu.show_all() + if hasattr(menu, 'popup_at_widget'): + menu.popup_at_widget( + widget, Gdk.Gravity.SOUTH_WEST, Gdk.Gravity.NORTH_WEST, + Gtk.get_current_event()) + else: + menu.popup( + None, None, menu_position, None, 0, + Gtk.get_current_event_time()) diff --git a/tryton/gui/window/form.py b/tryton/gui/window/form.py index 92357b7df5..e4c7c03a0d 100644 --- a/tryton/gui/window/form.py +++ b/tryton/gui/window/form.py @@ -17,6 +17,7 @@ from tryton.action import Action from tryton.common import ( RPCException, RPCExecute, message, sur, sur_3b, timezoned_date) from tryton.common.common import selection as selection_ +from tryton.common.popup_menu import popup from tryton.common.underline import set_underline from tryton.gui import Main from tryton.gui.window import Window @@ -587,21 +588,7 @@ class Form(TabContent): if not widget.props.active: menu.popdown() return - - def menu_position(menu, x, y, user_data): - widget_allocation = widget.get_allocation() - x, y = widget.get_window().get_root_coords( - widget_allocation.x, widget_allocation.y) - return (x, y + widget_allocation.height, False) - menu.show_all() - if hasattr(menu, 'popup_at_widget'): - menu.popup_at_widget( - widget, Gdk.Gravity.SOUTH_WEST, Gdk.Gravity.NORTH_WEST, - Gtk.get_current_event()) - else: - menu.popup( - None, None, menu_position, None, 0, - Gtk.get_current_event_time()) + popup(menu, widget) def record_message(self, position, size, max_size, record_id): name = str(position) if position else '_' diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index f0c25dabe4..9cf90fbb89 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -37,6 +37,7 @@ class Screen: # Width of tree columns per model # It is shared with all connection but it is the price for speed. tree_column_width = collections.defaultdict(lambda: {}) + tree_column_optional = {} def __init__(self, model_name, **attributes): context = attributes.get('context', {}) diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py index a2331805ee..98cbf9ffb7 100644 --- a/tryton/gui/window/view_form/view/list.py +++ b/tryton/gui/window/view_form/view/list.py @@ -14,7 +14,7 @@ from tryton.common import ( RPCException, RPCExecute, Tooltips, domain_inversion, node_attributes, simplify, unique_value) from tryton.common.cellrendererbutton import CellRendererButton -from tryton.common.popup_menu import populate +from tryton.common.popup_menu import populate, popup from tryton.config import CONFIG from tryton.gui.window import Window from tryton.pyson import PYSONDecoder @@ -334,6 +334,9 @@ class TreeXMLViewParser(XMLViewParser): self.view.treeview.append_column(column) + if 'optional' in attributes: + self.view.optionals.append(column) + if 'sum' in attributes: text = attributes['sum'] + _(':') label, sum_ = Gtk.Label(label=text), Gtk.Label() @@ -435,6 +438,7 @@ class ViewTree(View): def __init__(self, view_id, screen, xml, children_field): self.children_field = children_field + self.optionals = [] self.sum_widgets = [] self.sum_box = Gtk.HBox() self.treeview = None @@ -485,6 +489,23 @@ class ViewTree(View): self.display() + if self.optionals: + if self.draggable: + column = self.treeview.get_columns()[0] + else: + column = Gtk.TreeViewColumn() + column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) + column.name = None + column._type = 'optional' + self.treeview.insert_column(column, 0) + image = Gtk.Image() + image.set_from_pixbuf(common.IconFactory.get_pixbuf('tryton-menu')) + image.show() + column.set_widget(image) + column.set_fixed_width(25) + column.set_clickable(True) + column.connect('clicked', self.optional_menu) + # Add last column if necessary after display for updated visible for column in self.treeview.get_columns(): if column.get_expand() and column.get_visible(): @@ -496,6 +517,30 @@ class ViewTree(View): column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) self.treeview.append_column(column) + def optional_menu(self, column): + def toggle(menuitem, column): + column.set_visible(menuitem.get_active()) + self.save_optional() + + widget = column.get_widget() + menu = Gtk.Menu() + for optional in self.optionals: + menuitem = Gtk.CheckMenuItem(label=optional.get_title()) + menuitem.set_active(optional.get_visible()) + menuitem.connect('toggled', toggle, optional) + menu.add(menuitem) + popup(menu, widget) + + def save_optional(self): + fields = {c.name: not c.get_visible() for c in self.optionals} + try: + RPCExecute( + 'model', 'ir.ui.view_tree_optional', 'set_optional', + self.view_id, fields) + except RPCException: + pass + self.screen.tree_column_optional[self.view_id] = fields + def get_column_widget(self, column): 'Return the widget of the column' idx = [c for c in self.treeview.get_columns() @@ -1066,13 +1111,20 @@ class ViewTree(View): domain.append(tab_domain) domain = simplify(domain) decoder = PYSONDecoder(self.screen.context) + tree_column_optional = self.screen.tree_column_optional.get( + self.view_id, {}) for column in self.treeview.get_columns(): name = column.name if not name: continue widget = self.get_column_widget(column) widget.set_editable() - if decoder.decode(widget.attrs.get('tree_invisible', '0')): + if column.name in tree_column_optional: + optional = tree_column_optional[column.name] + else: + optional = bool(int(widget.attrs.get('optional', '0'))) + invisible = decoder.decode(widget.attrs.get('tree_invisible', '0')) + if invisible or optional: column.set_visible(False) elif name == self.screen.exclude_field: column.set_visible(False)