[gnome-boxes/implement-model-filtering: 2/2] collection, views: Implement item filtering on the model




commit 4d13b4fbb1bccb409cfd31c014c3612f716423fa
Author: Felipe Borges <felipeborges gnome org>
Date:   Wed Aug 10 11:41:53 2022 +0200

    collection, views: Implement item filtering on the model
    
    Using a model is incompatible with the filtering and sorting functions
    in GtkListBox and GtkFlowBox. When using a model, filtering and
    sorting should be implemented by the model.
    
    The Collection object now has an internal "items" GListStore that
    reflects the list of boxes available, and a "filtered_items" GListStore,
    which contains only the items we should display to the user (filtered
    by search terms).

 src/app-window.vala |  5 -----
 src/collection.vala | 35 ++++++++++++++++++++++-------------
 src/icon-view.vala  | 22 +---------------------
 src/list-view.vala  | 21 +--------------------
 src/searchbar.vala  |  2 +-
 5 files changed, 25 insertions(+), 60 deletions(-)
---
diff --git a/src/app-window.vala b/src/app-window.vala
index c9c2d780..5cc06773 100644
--- a/src/app-window.vala
+++ b/src/app-window.vala
@@ -333,11 +333,6 @@ public void select_item (CollectionItem item) {
             warning ("unknown item, fix your code");
     }
 
-    public void filter (string text) {
-        icon_view.filter.text = text;
-        list_view.filter.text = text;
-    }
-
     [GtkCallback]
     public bool on_key_pressed (Widget widget, Gdk.EventKey event) {
         var default_modifiers = Gtk.accelerator_get_default_mod_mask ();
diff --git a/src/collection.vala b/src/collection.vala
index 48a8fd71..e55b0995 100644
--- a/src/collection.vala
+++ b/src/collection.vala
@@ -30,7 +30,12 @@ public virtual int compare (CollectionItem other) {
     public signal void item_added (CollectionItem item);
     public signal void item_removed (CollectionItem item);
 
-    public GLib.ListStore items;
+    private GLib.ListStore items;
+    public GLib.ListStore filtered_items;
+    private CollectionFilter collection_filter = new CollectionFilter ();
+    private CompareDataFunc<CollectionItem> sort_func = ((item1, item2) => {
+        return item1.compare (item2);
+    });
 
     private GLib.List<CollectionItem> hidden_items;
 
@@ -42,6 +47,7 @@ public virtual int compare (CollectionItem other) {
 
     construct {
         items = new GLib.ListStore (typeof (CollectionItem));
+        filtered_items = new GLib.ListStore (typeof (CollectionItem));
         hidden_items = new GLib.List<CollectionItem> ();
     }
 
@@ -82,16 +88,8 @@ public void add_item (CollectionItem item) {
         }
 
         item.set_state (window.ui_state);
-
-        items.insert_sorted (item, (item1, item2) => {
-            if (item1 == null || item2 == null)
-                return 0;
-
-            var collection_item1 = item1 as CollectionItem;
-            var collection_item2 = item2 as CollectionItem;
-
-            return collection_item1.compare (collection_item2);
-        });
+        items.insert_sorted (item, sort_func);
+        filtered_items.insert_sorted (item, sort_func);
 
         item_added (item);
     }
@@ -101,6 +99,8 @@ public void remove_item (CollectionItem item) {
         for (int i = 0 ; i < length ; i++) {
            if (get_item (i) == item) {
                 items.remove (i);
+                filtered_items.remove (i);
+
                 item_removed (item);
 
                 break;
@@ -112,6 +112,17 @@ public void foreach_item (CollectionForeachFunc foreach_func) {
         for (int i = 0 ; i < length ; i++)
             foreach_func (get_item (i));
     }
+
+    public void filter (string search_term) {
+        filtered_items.remove_all ();
+
+        collection_filter.text = search_term;
+        foreach_item ((item) => {
+            if (collection_filter.filter (item)) {
+                filtered_items.insert_sorted (item, sort_func);
+            }
+        });
+    }
 }
 
 private class Boxes.CollectionFilter: GLib.Object {
@@ -138,5 +149,3 @@ public bool filter (CollectionItem item) {
         return true;
     }
 }
-
-private delegate bool Boxes.CollectionFilterFunc (Boxes.CollectionItem item);
diff --git a/src/icon-view.vala b/src/icon-view.vala
index dcaad597..f20b25ea 100644
--- a/src/icon-view.vala
+++ b/src/icon-view.vala
@@ -2,8 +2,6 @@
 
 [GtkTemplate (ui = "/org/gnome/Boxes/ui/icon-view.ui")]
 private class Boxes.IconView: Gtk.ScrolledWindow {
-    public CollectionFilter filter { get; protected set; }
-
     [GtkChild]
     private unowned Gtk.FlowBox flowbox;
 
@@ -11,11 +9,6 @@
     private Boxes.ActionsPopover context_popover;
 
     construct {
-        filter = new CollectionFilter ();
-        filter.notify["text"].connect (() => {
-            flowbox.invalidate_filter ();
-        });
-
         setup_flowbox ();
     }
 
@@ -26,7 +19,7 @@ public void setup_ui (AppWindow window) {
     }
 
     private void setup_flowbox () {
-        flowbox.bind_model (App.app.collection.items, (item) => {
+        flowbox.bind_model (App.app.collection.filtered_items, (item) => {
             var child = new Gtk.FlowBoxChild ();
             child.halign = Gtk.Align.START;
             var box = new IconViewChild (item as CollectionItem);
@@ -37,8 +30,6 @@ private void setup_flowbox () {
 
             return child;
         });
-
-        flowbox.set_filter_func (model_filter);
     }
 
     private CollectionItem? get_item_for_child (Gtk.FlowBoxChild child) {
@@ -49,17 +40,6 @@ private CollectionItem? get_item_for_child (Gtk.FlowBoxChild child) {
         return view.item;
     }
 
-    private bool model_filter (Gtk.FlowBoxChild child) {
-        if (child  == null)
-            return false;
-
-        var item = get_item_for_child (child);
-        if (item  == null)
-            return false;
-
-        return filter.filter (item as CollectionItem);
-    }
-
     [GtkCallback]
     private void on_child_activated (Gtk.FlowBoxChild child) {
         var item = get_item_for_child (child);
diff --git a/src/list-view.vala b/src/list-view.vala
index 7c0c7805..8640c504 100644
--- a/src/list-view.vala
+++ b/src/list-view.vala
@@ -2,8 +2,6 @@
 
 [GtkTemplate (ui = "/org/gnome/Boxes/ui/list-view.ui")]
 private class Boxes.ListView: Gtk.ScrolledWindow {
-    public CollectionFilter filter { get; protected set; }
-
     [GtkChild]
     private unowned Gtk.ListBox list_box;
 
@@ -11,10 +9,6 @@
     private Boxes.ActionsPopover context_popover;
 
     construct {
-        filter = new CollectionFilter ();
-        filter.notify["text"].connect (() => {
-            list_box.invalidate_filter ();
-        });
         setup_list_box ();
     }
 
@@ -25,7 +19,7 @@ public void setup_ui (AppWindow window) {
     }
 
     private void setup_list_box () {
-        list_box.bind_model (App.app.collection.items, (item) => {
+        list_box.bind_model (App.app.collection.filtered_items, (item) => {
             var box_row = new Gtk.ListBoxRow ();
             var view_row = new ListViewRow (item as CollectionItem);
             box_row.add (view_row);
@@ -39,7 +33,6 @@ private void setup_list_box () {
 
             return box_row;
         });
-        list_box.set_filter_func (model_filter);
     }
 
     private CollectionItem? get_item_for_row (Gtk.ListBoxRow box_row) {
@@ -50,18 +43,6 @@ private CollectionItem? get_item_for_row (Gtk.ListBoxRow box_row) {
         return view.item;
     }
 
-    private bool model_filter (Gtk.ListBoxRow box_row) {
-        var view = box_row.get_child () as ListViewRow;
-        if (view  == null)
-            return false;
-
-        var item = view.item;
-        if (item  == null)
-            return false;
-
-        return filter.filter (item as CollectionItem);
-    }
-
     [GtkCallback]
     private void on_row_activated (Gtk.ListBoxRow row) {
         var item = get_item_for_row (row);
diff --git a/src/searchbar.vala b/src/searchbar.vala
index 02b92eb2..e2828c87 100644
--- a/src/searchbar.vala
+++ b/src/searchbar.vala
@@ -29,7 +29,7 @@ public void setup_ui (AppWindow window) {
 
     [GtkCallback]
     private void on_search_changed () {
-        window.filter (text);
+        App.app.collection.filter (entry.text);
     }
 
     [GtkCallback]


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]