Reviewers: ,
Please review this at http://codereview.tryton.org/823002/
Affected files:
M tryton/config.py
M tryton/gui/main.py
M tryton/gui/window/view_form/screen/screen.py
M tryton/gui/window/view_form/view/list.py
M tryton/gui/window/view_form/view/list_gtk/parser.py
M tryton/gui/window/win_search.py
Index: tryton/config.py
===================================================================
--- a/tryton/config.py
+++ b/tryton/config.py
@@ -58,7 +58,7 @@
'client.form_tab': form_tab,
'client.maximize': False,
'client.save_width_height': True,
- 'client.save_tree_expanded_state': True,
+ 'client.save_tree_state': True,
'client.spellcheck': False,
'client.default_path': get_home_dir(),
'client.lang': locale.getdefaultlocale()[0],
Index: tryton/gui/main.py
===================================================================
--- a/tryton/gui/main.py
+++ b/tryton/gui/main.py
@@ -668,15 +668,15 @@
checkmenuitem_save_width_height.set_active(True)
checkmenuitem_save_tree_state = gtk.CheckMenuItem(
- _('Save Tree Expanded State'))
+ _('Save Tree State'))
checkmenuitem_save_tree_state.connect('activate',
lambda menuitem: CONFIG.__setitem__(
- 'client.save_tree_expanded_state',
+ 'client.save_tree_state',
menuitem.get_active()))
checkmenuitem_save_tree_state.set_accel_path(
- '<tryton>/Options/Form/Save Tree Expanded State')
+ '<tryton>/Options/Form/Save Tree State')
menu_form.add(checkmenuitem_save_tree_state)
- if CONFIG['client.save_tree_expanded_state']:
+ if CONFIG['client.save_tree_state']:
checkmenuitem_save_tree_state.set_active(True)
if gtkspell:
Index: tryton/gui/window/view_form/screen/screen.py
===================================================================
--- a/tryton/gui/window/view_form/screen/screen.py
+++ b/tryton/gui/window/view_form/screen/screen.py
@@ -83,8 +83,9 @@
self.fields_view_tree = None
self.sort = sort
self.view_to_load = []
- self.expanded_nodes = collections.defaultdict(
+ self.tree_states = collections.defaultdict(
lambda: collections.defaultdict(lambda: None))
+ self.tree_states_done = set()
self.domain_parser = None
self.pre_validate = False
self.view_to_load = mode[:]
@@ -598,46 +599,54 @@
def set_tree_state(self):
view = self.current_view
- if (not CONFIG['client.save_tree_expanded_state']
+ if (not CONFIG['client.save_tree_state']
or not self.current_view
or self.current_view.view_type != 'tree'
- or not self.current_view.children_field
or not self.group):
return
+ if id(view) in self.tree_states_done:
+ return
parent = self.parent.id if self.parent else None
- expanded_nodes = self.expanded_nodes[parent][view.children_field]
- if expanded_nodes is None:
+ state = self.tree_states[parent][view.children_field]
+ if state is None:
json_domain = self.get_tree_domain(parent)
try:
- expanded_nodes = RPCExecute('model',
- 'ir.ui.view_tree_expanded_state', 'get_expanded',
+ expanded_nodes, selected_nodes = RPCExecute('model',
+ 'ir.ui.view_tree_state', 'get',
self.model_name, json_domain,
self.current_view.children_field)
expanded_nodes = json.loads(expanded_nodes)
+ selected_nodes = json.loads(selected_nodes)
except RPCException:
expanded_nodes = []
- self.expanded_nodes[parent][view.children_field] =
expanded_nodes
+ selected_nodes = []
+ self.tree_states[parent][view.children_field] = (
+ expanded_nodes, selected_nodes)
+ else:
+ expanded_nodes, selected_nodes = state
view.expand_nodes(expanded_nodes)
+ view.select_nodes(selected_nodes)
+ self.tree_states_done.add(id(view))
def save_tree_state(self):
view = self.current_view
- if (not CONFIG['client.save_tree_expanded_state']
+ if (not CONFIG['client.save_tree_state']
or not view
or view.view_type != 'tree'
- or not view.children_field
or not (self.parent is None
or isinstance(self.parent, Record))):
return
parent = self.parent.id if self.parent else None
paths = view.get_expanded_paths()
- self.expanded_nodes[parent][view.children_field] = paths
+ selected_paths = view.get_selected_paths()
+ self.tree_states[parent][view.children_field] = (paths,
selected_paths)
json_domain = self.get_tree_domain(parent)
json_paths = json.dumps(paths)
+ json_selected_path = json.dumps(selected_paths)
try:
- RPCExecute('model', 'ir.ui.view_tree_expanded_state',
- 'set_expanded', self.model_name, json_domain,
- self.current_view.children_field, json_paths,
- process_exception=False)
+ RPCExecute('model', 'ir.ui.view_tree_state', 'set',
+ self.model_name, json_domain,
self.current_view.children_field,
+ json_paths, json_selected_path, process_exception=False)
except (TrytonServerError, TrytonServerUnavailable):
pass
@@ -650,7 +659,8 @@
return json_domain
def load(self, ids, set_cursor=True, modified=False):
- self.expanded_nodes.clear()
+ self.tree_states.clear()
+ self.tree_states_done.clear()
self.group.load(ids, modified=modified)
self.current_view.reset()
if ids:
Index: tryton/gui/window/view_form/view/list.py
===================================================================
--- a/tryton/gui/window/view_form/view/list.py
+++ b/tryton/gui/window/view_form/view/list.py
@@ -752,8 +752,7 @@
elif tree_sel.get_mode() == gtk.SELECTION_MULTIPLE:
model, paths = tree_sel.get_selected_rows()
if model and paths:
- iter_ = model.get_iter(paths[0])
- record = model.get_value(iter_, 0)
+ record = model.on_get_iter(paths[0])
self.screen.current_record = record
else:
self.screen.current_record = None
@@ -864,7 +863,11 @@
self.widget_tree.expand_to_path(path[:-1])
self.widget_tree.scroll_to_cell(path, focus_column,
use_align=False)
- self.widget_tree.set_cursor(path, focus_column, new)
+ current_path = self.widget_tree.get_cursor()[0]
+ selected_path = \
+ self.widget_tree.get_selection().get_selected_rows()[1]
+ if (current_path != path and path not in selected_path) or new:
+ self.widget_tree.set_cursor(path, focus_column, new)
def sel_ids_get(self):
def _func_sel_get(store, path, iter, ids):
@@ -898,6 +901,33 @@
else:
renderer.set_property('editable', False)
+ def get_selected_paths(self):
+ selection = self.widget_tree.get_selection()
+ model, rows = selection.get_selected_rows()
+ id_paths = []
+ for row in rows:
+ path = ()
+ id_path = []
+ for node in row:
+ path += (node,)
+ id_path.append(model.on_get_iter(path).id)
+ id_paths.append(id_path)
+ return id_paths
+
+ def select_nodes(self, nodes):
+ selection = self.widget_tree.get_selection()
+ if not nodes:
+ return
+ selection.unselect_all()
+ scroll = False
+ for node in nodes:
+ path = path_convert_id2pos(self.store, node)
+ if path:
+ selection.select_path(path)
+ if not scroll:
+ self.widget_tree.scroll_to_cell(path)
+ scroll = True
+
def get_expanded_paths(self, starting_path=None,
starting_id_path=None):
# Use id instead of position
# because the position may change between load
Index: tryton/gui/window/view_form/view/list_gtk/parser.py
===================================================================
--- a/tryton/gui/window/view_form/view/list_gtk/parser.py
+++ b/tryton/gui/window/view_form/view/list_gtk/parser.py
@@ -108,7 +108,6 @@
treeview.sequence = attrs.get('sequence', False)
treeview.colors = attrs.get('colors', '"black"')
treeview.keyword_open = attrs.get('keyword_open', False)
- treeview.connect('focus', self.set_selection)
self.treeview = treeview
treeview.set_property('rules-hint', True)
if not self.title:
@@ -296,12 +295,6 @@
treeview.set_fixed_height_mode(True)
return treeview, dict_widget, state_widgets, on_write, [], None
- def set_selection(self, treeview, direction):
- selection = treeview.get_selection()
- if len(treeview.get_model()) and not
selection.count_selected_rows():
- selection.select_path(0)
- return False
-
class Affix(object):
Index: tryton/gui/window/win_search.py
===================================================================
--- a/tryton/gui/window/win_search.py
+++ b/tryton/gui/window/win_search.py
@@ -56,6 +56,7 @@
self.screen = Screen(model, domain=domain, mode=['tree'],
context=context, view_ids=view_ids,
views_preload=views_preload,
row_activate=self.sig_activate)
+ # TODO fix tree_state
self.view = self.screen.current_view
self.view.unset_editable()
sel = self.view.widget_tree.get_selection()