diff --git a/sao/src/view/tree.js b/sao/src/view/tree.js
index eb8def9819..c7006e962d 100644
--- a/sao/src/view/tree.js
+++ b/sao/src/view/tree.js
@@ -72,7 +72,8 @@
this.view.columns.push(column);
if (attributes.optional) {
- this.view.optionals.push(column);
+ Sao.setdefault(
+ this.view.optionals, column.attributes.name, []).push(column);
}
if (parseInt(attributes.sum || '0', 10)) {
@@ -99,7 +100,7 @@
display_size: Sao.config.display_size,
init: function(view_id, screen, xml, children_field) {
this.children_field = children_field;
- this.optionals = [];
+ this.optionals = {};
this.sum_widgets = new Map();
this.columns = [];
this.selection_mode = (screen.attributes.selection_mode ||
@@ -254,7 +255,7 @@
this.set_drag_and_drop();
th = this.thead.find('th').first();
- if (this.optionals.length) {
+ if (!jQuery.isEmptyObject(this.optionals)) {
th.addClass('optional');
}
var menu = jQuery('
', {
@@ -283,15 +284,19 @@
},
tree_menu: function(evt) {
const toggle = evt => {
- var column = evt.data;
- column.set_visible(jQuery(evt.delegateTarget).prop('checked'));
+ let columns = evt.data;
+ let visible = jQuery(evt.delegateTarget).prop('checked');
+ columns.forEach(c => c.set_visible(visible));
this.save_optional();
this.display();
this.update_visible();
};
var menu = evt.data;
menu.empty();
- for (const optional of this.optionals) {
+ for (let columns of Object.values(this.optionals)) {
+ let visible = columns.some(c => c.get_visible());
+ let string = [...new Set(columns.map(c => c.attributes.string))]
+ .join(' / ');
menu.append(jQuery('', {
'role': 'presentation',
}).append(jQuery('', {
@@ -300,11 +305,11 @@
'class': 'checkbox',
}).append(jQuery('', {
'type': 'checkbox',
- 'checked': optional.get_visible(),
- }).change(optional, toggle))
- .append(' ' + optional.attributes.string))));
+ 'checked': visible,
+ }).change(columns, toggle))
+ .append(' ' + string))));
}
- if (this.optionals.length) {
+ if (!jQuery.isEmptyObject(this.optionals)) {
menu.append(jQuery('', {
'role': 'separator',
'class': 'divider hidden-xs',
@@ -331,12 +336,12 @@
})));
},
save_optional: function(store=true) {
- if (!this.optionals.length) {
+ if (jQuery.isEmptyObject(this.optionals)) {
return;
}
var fields = {};
- for (const column of this.optionals) {
- fields[column.attributes.name] = !column.get_visible();
+ for (let [name, columns] of Object.entries(this.optionals)) {
+ fields[name] = columns.every(c => !c.get_visible());
}
if (store) {
var tree_optional_model = new Sao.Model(
@@ -1510,7 +1515,7 @@
td.addClass('draggable-handle');
td.append(Sao.common.ICONFACTORY.get_icon_img('tryton-drag'));
}
- if (this.tree.optionals.length) {
+ if (!jQuery.isEmptyObject(this.tree.optionals)) {
td.addClass('optional');
}
this.el.append(td);
diff --git a/tryton/tryton/gui/window/view_form/view/list.py b/tryton/tryton/gui/window/view_form/view/list.py
index d2b0b06f96..6d51fb818f 100644
--- a/tryton/tryton/gui/window/view_form/view/list.py
+++ b/tryton/tryton/gui/window/view_form/view/list.py
@@ -5,6 +5,7 @@ import gettext
import json
import locale
import sys
+from collections import defaultdict
from functools import wraps
from io import StringIO
@@ -336,7 +337,7 @@ class TreeXMLViewParser(XMLViewParser):
self.view.treeview.append_column(column)
if 'optional' in attributes:
- self.view.optionals.append(column)
+ self.view.optionals[column.name].append(column)
def _parse_button(self, node, attributes):
button = Button(self.view, attributes)
@@ -437,7 +438,7 @@ class ViewTree(View):
def __init__(self, view_id, screen, xml, children_field):
self.children_field = children_field
- self.optionals = []
+ self.optionals = defaultdict(list)
self.sum_widgets = []
self.sum_box = Gtk.HBox()
self.treeview = None
@@ -521,21 +522,27 @@ class ViewTree(View):
self.treeview.append_column(column)
def optional_menu(self, column):
- def toggle(menuitem, column):
- column.set_visible(menuitem.get_active())
+ def toggle(menuitem, columns):
+ visible = menuitem.get_active()
+ for column in columns:
+ column.set_visible(visible)
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)
+ for name, columns in self.optionals.items():
+ visible = any(c.get_visible() for c in columns)
+ title = ' / '.join({c.get_title() for c in columns})
+ menuitem = Gtk.CheckMenuItem(label=title)
+ menuitem.set_active(visible)
+ menuitem.connect('toggled', toggle, columns)
menu.add(menuitem)
popup(menu, widget)
def save_optional(self):
- fields = {c.name: not c.get_visible() for c in self.optionals}
+ fields = {}
+ for name, columns in self.optionals.items():
+ fields[name] = all(not c.get_visible() for c in columns)
try:
RPCExecute(
'model', 'ir.ui.view_tree_optional', 'set_optional',