Manage selection tree state
review823002
This commit is contained in:
1 parent
982654446a
commit
7b4c2e97b5
8 files changed
+80
-38
No files matched your search
+1
-1
@@ -57,7 +57,7 @@ class ConfigManager(object):
|
||||
'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],
|
||||
|
||||
+4
-4
@@ -610,15 +610,15 @@ class Main(object):
|
||||
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:
|
||||
|
||||
@@ -8,8 +8,8 @@ from tryton.gui.window.win_form import WinForm
|
||||
class Attachment(WinForm):
|
||||
"Attachment window"
|
||||
|
||||
def __init__(self, model_name, record_id, callback=None):
|
||||
self.resource = '%s,%s' % (model_name, record_id)
|
||||
def __init__(self, record, callback=None):
|
||||
self.resource = '%s,%s' % (record.model_name, record.id)
|
||||
self.attachment_callback = callback
|
||||
screen = Screen('ir.attachment', domain=[
|
||||
('resource', '=', self.resource),
|
||||
@@ -17,7 +17,7 @@ class Attachment(WinForm):
|
||||
'resource': self.resource,
|
||||
}, exclude_field='resource')
|
||||
screen.search_filter()
|
||||
screen.parent = True
|
||||
screen.parent = record
|
||||
super(Attachment, self).__init__(screen, self.callback,
|
||||
view_type='tree')
|
||||
|
||||
|
||||
@@ -201,10 +201,10 @@ class Form(SignalEvent, TabContent):
|
||||
return self.screen.id_get()
|
||||
|
||||
def sig_attach(self, widget=None):
|
||||
record_id = self.id_get()
|
||||
if record_id is False or record_id < 0:
|
||||
record = self.screen.current_record
|
||||
if not record or record.id < 0:
|
||||
return
|
||||
Attachment(self.model, record_id,
|
||||
Attachment(record,
|
||||
lambda: self.update_attachment_count(reload=True))
|
||||
|
||||
def update_attachment_count(self, reload=False):
|
||||
|
||||
@@ -14,6 +14,7 @@ import urllib
|
||||
import urlparse
|
||||
import xml.dom.minidom
|
||||
import gettext
|
||||
import logging
|
||||
|
||||
from tryton.gui.window.view_form.model.group import Group
|
||||
from tryton.gui.window.view_form.model.record import Record
|
||||
@@ -88,8 +89,9 @@ class Screen(SignalEvent):
|
||||
self.fields_view_tree = None
|
||||
self.order = order
|
||||
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[:]
|
||||
@@ -611,29 +613,39 @@ class Screen(SignalEvent):
|
||||
|
||||
def set_tree_state(self):
|
||||
view = self.current_view
|
||||
if (not CONFIG['client.save_tree_expanded_state']
|
||||
or not self.current_view
|
||||
or self.current_view.view_type != 'tree'
|
||||
or not self.current_view.children_field
|
||||
if (not CONFIG['client.save_tree_state']
|
||||
or not view
|
||||
or view.view_type != 'tree'
|
||||
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:
|
||||
logging.getLogger(__name__).warn(
|
||||
_('Unable to get view tree state'))
|
||||
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, store=True):
|
||||
if not CONFIG['client.save_tree_expanded_state']:
|
||||
if not CONFIG['client.save_tree_state']:
|
||||
return
|
||||
for view in self.views:
|
||||
if view.view_type == 'form':
|
||||
@@ -644,17 +656,21 @@ class Screen(SignalEvent):
|
||||
elif (view.view_type == 'tree' and view.children_field):
|
||||
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)
|
||||
if store:
|
||||
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,
|
||||
view.children_field, json_paths,
|
||||
RPCExecute('model', 'ir.ui.view_tree_state', 'set',
|
||||
self.model_name, json_domain, view.children_field,
|
||||
json_paths, json_selected_path,
|
||||
process_exception=False)
|
||||
except (TrytonServerError, TrytonServerUnavailable):
|
||||
pass
|
||||
logging.getLogger(__name__).warn(
|
||||
_('Unable to set view tree state'))
|
||||
|
||||
def get_tree_domain(self, parent):
|
||||
if parent:
|
||||
@@ -665,7 +681,8 @@ class Screen(SignalEvent):
|
||||
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:
|
||||
|
||||
@@ -750,8 +750,7 @@ class ViewList(ParserView):
|
||||
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
|
||||
@@ -862,7 +861,11 @@ class ViewList(ParserView):
|
||||
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):
|
||||
@@ -896,6 +899,33 @@ class ViewList(ParserView):
|
||||
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
|
||||
|
||||
@@ -108,7 +108,6 @@ class ParserTree(ParserInterface):
|
||||
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 @@ class ParserTree(ParserInterface):
|
||||
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):
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ class WinSearch(NoModal):
|
||||
row_activate=self.sig_activate)
|
||||
self.view = self.screen.current_view
|
||||
self.view.unset_editable()
|
||||
# Prevent to set tree_state
|
||||
self.screen.tree_states_done.add(id(self.view))
|
||||
sel = self.view.widget_tree.get_selection()
|
||||
|
||||
if not sel_multi:
|
||||
|
||||
Reference in new issue
Block a user