From 660425c56858e266d200513170d187e31d25c7af Mon Sep 17 00:00:00 2001 From: Nicolas Evrard Date: Sun, 11 Dec 2022 18:18:23 +0100 Subject: [PATCH 1/2] Allow list-form in mixed-widget --- tryton/gui/window/view_form/screen/screen.py | 3 ++- tryton/gui/window/view_form/view/form_gtk/one2many.py | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index c1e6b2f45a..d15766f502 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -535,7 +535,8 @@ def go_previous(): return True def _sync_group(self): - if not self._multiview_form or self.current_view.view_type != 'tree': + if (not self._multiview_form + or self.current_view.view_type not in {'tree', 'list-form'}): return if self.current_record is None: return diff --git a/tryton/gui/window/view_form/view/form_gtk/one2many.py b/tryton/gui/window/view_form/view/form_gtk/one2many.py index e39a58e80f..7560d80d9b 100644 --- a/tryton/gui/window/view_form/view/form_gtk/one2many.py +++ b/tryton/gui/window/view_form/view/form_gtk/one2many.py @@ -182,9 +182,10 @@ def __init__(self, view, attrs): self.screen._multiview_form = view self.screen._multiview_group = self.attrs['group'] wgroup = view.widget_groups.setdefault(self.attrs['group'], []) - if self.screen.current_view.view_type == 'tree': + if self.screen.current_view.view_type in {'tree', 'list-form'}: if (wgroup - and wgroup[0].screen.current_view.view_type == 'tree'): + and wgroup[0].screen.current_view.view_type in { + 'tree', 'list-form'}): raise ValueError("Wrong multiview definition") wgroup.insert(0, self) else: From 1563724af25d8b7b3183635fd558d0326732c771 Mon Sep 17 00:00:00 2001 From: Nicolas Evrard Date: Thu, 19 Jan 2023 11:29:43 +0100 Subject: [PATCH 2/2] Support set_state and record validation on list-form --- tryton/gui/window/view_form/screen/screen.py | 8 ++- tryton/gui/window/view_form/view/list_form.py | 52 ++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index d15766f502..823ba142ec 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -908,7 +908,7 @@ def set_tree_state(self): view = self.current_view if not view: return - if view.view_type not in ('tree', 'form'): + if view.view_type not in ('tree', 'form', 'list-form'): return if id(view) in self.tree_states_done: return @@ -947,6 +947,8 @@ def set_tree_state(self): if view.view_type == 'tree': view.expand_nodes(expanded_nodes) view.select_nodes(selected_nodes) + elif view.view_type == 'list-form': + view.select_nodes(selected_nodes) else: if selected_nodes: record = None @@ -1003,6 +1005,10 @@ def save_tree_state(self, store=True): except Exception: logger.warn( _('Unable to set view tree state'), exc_info=True) + elif view.view_type == 'list-form': + selected_paths = view.get_selected_paths() + self.tree_states[parent][view.children_field] = ( + [], selected_paths) def get_tree_domain(self, parent): if parent: diff --git a/tryton/gui/window/view_form/view/list_form.py b/tryton/gui/window/view_form/view/list_form.py index 0403c9e31f..34893642ec 100644 --- a/tryton/gui/window/view_form/view/list_form.py +++ b/tryton/gui/window/view_form/view/list_form.py @@ -1,6 +1,6 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -from gi.repository import Gio, GObject, Gtk +from gi.repository import Gio, GLib, GObject, Gtk from tryton.common import common @@ -72,6 +72,7 @@ def __init__(self, view_id, screen, xml): self.form_xml = xml self.listbox = Gtk.ListBox.new() self.listbox.connect('row-selected', self._row_selected) + self.listbox.connect('selected-rows-changed', self._selection_changed) self.listbox.props.activate_on_single_click = False self.listbox.set_selection_mode(Gtk.SelectionMode.MULTIPLE) self.widget = Gtk.ScrolledWindow.new() @@ -84,6 +85,8 @@ def display(self, force=False): self._view_forms = [] self._model = ListBoxModel(self.group) self.listbox.bind_model(self._model, self._create_form) + if self.record: + self.set_cursor() for idx, view_form in enumerate(self._view_forms): view_form.display() @@ -123,6 +126,53 @@ def selected_records(self): return [ self._model.get_item(r.get_index()).record for r in selected_rows] + def get_selected_paths(self): + return [r.id for r in self.selected_records] + + def select_nodes(self, nodes): + if not nodes: + return + self.listbox.unselect_all() + for idx, view_form in enumerate(self._view_forms): + if view_form.record.id in nodes: + row = self.listbox.get_row_at_index(idx) + if not row or not row.get_realized(): + continue + self.listbox.select_row(row) + + def _selection_changed(self, listbox): + previous_record = self.record + if previous_record and previous_record not in previous_record.group: + previous_record = None + + selected_records = self.selected_records + if selected_records: + self.record = selected_records[0] + else: + self.record = None + + def go_previous(): + self.record = previous_record + self.set_cursor() + + def save(): + if not previous_record.destroyed: + if not previous_record.save(): + go_previous() + + def pre_validate(): + if not previous_record.detroyed: + if not previous_record.pre_validate(): + go_previous() + + if not self.screen.parent and previous_record != self.record: + if not previous_record.validate(self.get_fields()): + go_previous() + return True + GLib.idle_add(save) + elif self.screen.pre_validate and previous_record != self.record: + GLib.idle_add(pre_validate) + def select_form(self, listbox_form): index = self._view_forms.index(listbox_form) self.listbox.unselect_all()