From 04e067a1c2df3866a809fef5b8f62fd9c68a99fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 17 Dec 2020 00:22:19 +0100 Subject: [PATCH] Add interactive search on tree view It uses a simple search by word on all visible cell of each row. The standard GTK shortcut is +F, the search box shortcut is updated to ++F. issue4511 review320371002 --- CHANGELOG | 1 + tryton/gui/main.py | 3 ++- tryton/gui/window/view_form/view/list.py | 24 +++++++++++++++++-- .../window/view_form/view/list_gtk/widget.py | 3 +++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index ce5bbbbe38..81db105190 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add interactive search on tree view * Unify PYSON string format Version 5.8.0 - 2020-11-02 diff --git a/tryton/gui/main.py b/tryton/gui/main.py index 94f7239db6..79169a47dc 100644 --- a/tryton/gui/main.py +++ b/tryton/gui/main.py @@ -197,7 +197,8 @@ class Main(Gtk.Application): '/Form/Email', Gdk.KEY_E, Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.SHIFT_MASK) Gtk.AccelMap.add_entry( - '/Form/Search', Gdk.KEY_F, Gdk.ModifierType.CONTROL_MASK) + '/Form/Search', Gdk.KEY_F, + Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.SHIFT_MASK) Gtk.AccelMap.load(os.path.join(get_config_dir(), 'accel.map')) diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py index 879bc948e9..7d9dbd2e8c 100644 --- a/tryton/gui/window/view_form/view/list.py +++ b/tryton/gui/window/view_form/view/list.py @@ -496,6 +496,7 @@ class ViewTree(View): self.sum_box.show() self.widget.pack_start( self.sum_box, expand=False, fill=False, padding=0) + self.treeview.set_search_equal_func(self.search_equal_func) self.display() @@ -505,6 +506,22 @@ class ViewTree(View): if c.name == column.name].index(column) return self.widgets[column.name][idx] + def search_equal_func(self, model, column, key, iter_): + key = key.lower() + record = model.get_value(iter_, 0) + for field_name in self.get_fields(visible_only=True): + field = record[field_name] + field.state_set(record, states=('invisible',)) + if not field.get_state_attrs(record).get('invisible', False): + for widget in self.widgets[field_name]: + text = widget.get_textual_value(record).lower() + # Simple search by word + while text: + if text.startswith(key): + return False + text = ' '.join(text.split()[1:]) + return True + def sort_model(self, column): up = common.IconFactory.get_pixbuf('tryton-arrow-up') down = common.IconFactory.get_pixbuf('tryton-arrow-down') @@ -615,8 +632,9 @@ class ViewTree(View): def editable(self): return self._editable and not self.screen.readonly - def get_fields(self): - return [col.name for col in self.treeview.get_columns() if col.name] + def get_fields(self, visible_only=False): + return [col.name for col in self.treeview.get_columns() + if col.name and (not visible_only or col.get_visible())] def get_buttons(self): return [b for b in self.state_widgets @@ -1024,6 +1042,8 @@ class ViewTree(View): selection = self.treeview.get_selection() path = current_record.get_index_path(model.group) selection.select_path(path) + # The search column must be set each time the model is changed + self.treeview.set_search_column(0) if not current_record: selection = self.treeview.get_selection() selection.unselect_all() diff --git a/tryton/gui/window/view_form/view/list_gtk/widget.py b/tryton/gui/window/view_form/view/list_gtk/widget.py index aeb3f0ccc4..ce5afec95a 100644 --- a/tryton/gui/window/view_form/view/list_gtk/widget.py +++ b/tryton/gui/window/view_form/view/list_gtk/widget.py @@ -415,6 +415,9 @@ class Boolean(GenericText): self.view.treeview.set_cursor(path) return True + def get_textual_value(self, record): + return str(super().get_textual_value(record)) + class URL(Char):