[gtk/wip/otte/listmodels: 15/18] filterlistmodel: Add ::item-type and ::n-items




commit fe66c726da7c4c7fdd1d7ca047078ddc645f2bbb
Author: Benjamin Otte <otte redhat com>
Date:   Sat Jun 11 07:05:27 2022 +0200

    filterlistmodel: Add ::item-type and ::n-items
    
    With tests!

 gtk/gtkfilterlistmodel.c                   | 69 +++++++++++++++++++++++++++---
 testsuite/gtk/filterlistmodel-exhaustive.c | 28 ++++++++++++
 testsuite/gtk/filterlistmodel.c            | 29 ++++++++-----
 3 files changed, 110 insertions(+), 16 deletions(-)
---
diff --git a/gtk/gtkfilterlistmodel.c b/gtk/gtkfilterlistmodel.c
index fdf9a4a41e..68978712e1 100644
--- a/gtk/gtkfilterlistmodel.c
+++ b/gtk/gtkfilterlistmodel.c
@@ -43,7 +43,9 @@ enum {
   PROP_0,
   PROP_FILTER,
   PROP_INCREMENTAL,
+  PROP_ITEM_TYPE,
   PROP_MODEL,
+  PROP_N_ITEMS,
   PROP_PENDING,
   NUM_PROPERTIES
 };
@@ -206,14 +208,18 @@ gtk_filter_list_model_emit_items_changed_for_changes (GtkFilterListModel *self,
   gtk_bitset_difference (changes, old);
   if (!gtk_bitset_is_empty (changes))
     {
-      guint min, max;
+      guint min, max, removed, added;
 
       min = gtk_bitset_get_minimum (changes);
       max = gtk_bitset_get_maximum (changes);
+      removed = gtk_bitset_get_size_in_range (old, min, max);
+      added = gtk_bitset_get_size_in_range (self->matches, min, max);
       g_list_model_items_changed (G_LIST_MODEL (self),
                                   min > 0 ? gtk_bitset_get_size_in_range (self->matches, 0, min - 1) : 0,
-                                  gtk_bitset_get_size_in_range (old, min, max),
-                                  gtk_bitset_get_size_in_range (self->matches, min, max));
+                                  removed,
+                                  added);
+      if (removed != added)
+        g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]);
     }
   gtk_bitset_unref (changes);
   gtk_bitset_unref (old);
@@ -286,6 +292,8 @@ gtk_filter_list_model_items_changed_cb (GListModel         *model,
 
     case GTK_FILTER_MATCH_ALL:
       g_list_model_items_changed (G_LIST_MODEL (self), position, removed, added);
+      if (removed != added)
+        g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]);
       return;
 
     case GTK_FILTER_MATCH_SOME:
@@ -316,6 +324,8 @@ gtk_filter_list_model_items_changed_cb (GListModel         *model,
     g_list_model_items_changed (G_LIST_MODEL (self),
                                 position > 0 ? gtk_bitset_get_size_in_range (self->matches, 0, position - 1) 
: 0,
                                 filter_removed, filter_added);
+  if (filter_removed != filter_added)
+    g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]);
 }
 
 static void
@@ -364,10 +374,18 @@ gtk_filter_list_model_get_property (GObject     *object,
       g_value_set_boolean (value, self->incremental);
       break;
 
+    case PROP_ITEM_TYPE:
+      g_value_set_gtype (value, gtk_filter_list_model_get_item_type (G_LIST_MODEL (self)));
+      break;
+
     case PROP_MODEL:
       g_value_set_object (value, self->model);
       break;
 
+    case PROP_N_ITEMS:
+      g_value_set_uint (value, gtk_filter_list_model_get_n_items (G_LIST_MODEL (self)));
+      break;
+
     case PROP_PENDING:
       g_value_set_uint (value, gtk_filter_list_model_get_pending (self));
       break;
@@ -415,7 +433,10 @@ gtk_filter_list_model_refilter (GtkFilterListModel *self,
         self->strictness = new_strictness;
         gtk_filter_list_model_stop_filtering (self);
         if (n_before > 0)
-          g_list_model_items_changed (G_LIST_MODEL (self), 0, n_before, 0);
+          {
+            g_list_model_items_changed (G_LIST_MODEL (self), 0, n_before, 0);
+            g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]);
+          }
       }
       break;
 
@@ -423,8 +444,17 @@ gtk_filter_list_model_refilter (GtkFilterListModel *self,
       switch (self->strictness)
         {
         case GTK_FILTER_MATCH_NONE:
-          self->strictness = new_strictness;
-          g_list_model_items_changed (G_LIST_MODEL (self), 0, 0, g_list_model_get_n_items (self->model));
+          {
+            guint n_items;
+
+            self->strictness = new_strictness;
+            n_items = g_list_model_get_n_items (self->model);
+            if (n_items > 0)
+              {
+                g_list_model_items_changed (G_LIST_MODEL (self), 0, 0, n_items);
+                g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]);
+              }
+          }
           break;
         case GTK_FILTER_MATCH_ALL:
           self->strictness = new_strictness;
@@ -460,6 +490,7 @@ gtk_filter_list_model_refilter (GtkFilterListModel *self,
 
                 g_clear_pointer (&self->matches, gtk_bitset_unref);
                 g_list_model_items_changed (G_LIST_MODEL (self), start, n_before - end - start, n_after - 
end - start);
+                g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]);
               }
           }
           break;
@@ -571,6 +602,18 @@ gtk_filter_list_model_class_init (GtkFilterListModelClass *class)
                             FALSE,
                             GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
+  /**
+   * GtkFilterListModel:item-type:
+   *
+   * The type of items. See [func@Gio.ListModel.get_item_type].
+   *
+   * Since: 4.8
+   **/
+  properties[PROP_ITEM_TYPE] =
+    g_param_spec_gtype ("item-type", NULL, NULL,
+                        G_TYPE_OBJECT,
+                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
   /**
    * GtkFilterListModel:model: (attributes org.gtk.Property.get=gtk_filter_list_model_get_model 
org.gtk.Property.set=gtk_filter_list_model_set_model)
    *
@@ -581,6 +624,18 @@ gtk_filter_list_model_class_init (GtkFilterListModelClass *class)
                            G_TYPE_LIST_MODEL,
                            GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
+  /**
+   * GtkFilterListModel:n-items:
+   *
+   * The number of items. See [func@Gio.ListModel.get_n_items].
+   *
+   * Since: 4.8
+   **/
+  properties[PROP_N_ITEMS] =
+    g_param_spec_uint ("n-items", NULL, NULL,
+                       0, G_MAXUINT, 0,
+                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
   /**
    * GtkFilterListModel:pending: (attributes org.gtk.Property.get=gtk_filter_list_model_get_pending)
    *
@@ -737,6 +792,8 @@ gtk_filter_list_model_set_model (GtkFilterListModel *self,
 
   if (removed > 0 || added > 0)
     g_list_model_items_changed (G_LIST_MODEL (self), 0, removed, added);
+  if (removed != added)
+    g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]);
 
   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODEL]);
 }
diff --git a/testsuite/gtk/filterlistmodel-exhaustive.c b/testsuite/gtk/filterlistmodel-exhaustive.c
index b7366f4fb6..084f1d301d 100644
--- a/testsuite/gtk/filterlistmodel-exhaustive.c
+++ b/testsuite/gtk/filterlistmodel-exhaustive.c
@@ -75,6 +75,9 @@ assert_items_changed_correctly (GListModel *model,
 {
   guint i, n_items;
 
+  //sanity check that we got all notifies
+  g_assert_cmpuint (g_list_model_get_n_items (compare), ==, GPOINTER_TO_UINT (g_object_get_data (G_OBJECT 
(compare), "last-notified-n-items")));
+
   //g_print ("%s => %u -%u +%u => %s\n", model_to_string (compare), position, removed, added, 
model_to_string (model));
 
   g_assert_cmpint (g_list_model_get_n_items (model), ==, g_list_model_get_n_items (compare) - removed + 
added);
@@ -127,6 +130,21 @@ assert_items_changed_correctly (GListModel *model,
     }
 }
 
+static void
+assert_n_items_notified_properly (GListModel *model,
+                                  GParamSpec *pspec,
+                                  GListModel *compare)
+{
+  g_assert_cmpuint (g_list_model_get_n_items (model), !=, GPOINTER_TO_UINT (g_object_get_data (G_OBJECT 
(compare), "last-notified-n-items")));
+
+  /* These should hve been updated in items-changed, which should have been emitted first */
+  g_assert_cmpuint (g_list_model_get_n_items (model), ==, g_list_model_get_n_items (compare));
+
+  g_object_set_data (G_OBJECT (compare),
+                     "last-notified-n-items",
+                     GUINT_TO_POINTER (g_list_model_get_n_items (model)));
+}
+
 static GtkFilterListModel *
 filter_list_model_new (GListModel *source,
                        GtkFilter  *filter)
@@ -154,6 +172,16 @@ filter_list_model_new (GListModel *source,
                          (GClosureNotify) g_object_unref,
                          0);
 
+  g_object_set_data (G_OBJECT (check),
+                     "last-notified-n-items",
+                     GUINT_TO_POINTER (g_list_model_get_n_items (G_LIST_MODEL (check))));
+  g_signal_connect_data (model,
+                         "notify::n-items",
+                         G_CALLBACK (assert_n_items_notified_properly), 
+                         g_object_ref (check),
+                         (GClosureNotify) g_object_unref,
+                         0);
+
   return model;
 }
 
diff --git a/testsuite/gtk/filterlistmodel.c b/testsuite/gtk/filterlistmodel.c
index cd109c2e0b..d35b73f74b 100644
--- a/testsuite/gtk/filterlistmodel.c
+++ b/testsuite/gtk/filterlistmodel.c
@@ -143,6 +143,14 @@ items_changed (GListModel *model,
     }
 }
 
+static void
+notify_n_items (GObject    *object,
+                GParamSpec *pspec,
+                GString    *changes)
+{
+  g_string_append_c (changes, '*');
+}
+
 static void
 free_changes (gpointer data)
 {
@@ -171,6 +179,7 @@ new_model (guint               size,
   changes = g_string_new ("");
   g_object_set_qdata_full (G_OBJECT(result), changes_quark, changes, free_changes);
   g_signal_connect (result, "items-changed", G_CALLBACK (items_changed), changes);
+  g_signal_connect (result, "notify::n-items", G_CALLBACK (notify_n_items), changes);
 
   return result;
 }
@@ -248,7 +257,7 @@ test_empty_set_filter (void)
   gtk_filter_list_model_set_filter (filter, custom);
   g_object_unref (custom);
   assert_model (filter, "1 2 3 4 5 6");
-  assert_changes (filter, "6-4");
+  assert_changes (filter, "6-4*");
   g_object_unref (filter);
 
   filter = new_model (10, NULL, NULL);
@@ -256,7 +265,7 @@ test_empty_set_filter (void)
   gtk_filter_list_model_set_filter (filter, custom);
   g_object_unref (custom);
   assert_model (filter, "");
-  assert_changes (filter, "0-10");
+  assert_changes (filter, "0-10*");
   g_object_unref (filter);
 
   filter = new_model (10, NULL, NULL);
@@ -272,7 +281,7 @@ test_empty_set_filter (void)
   gtk_filter_list_model_set_filter (filter, custom);
   g_object_unref (custom);
   assert_model (filter, "4 5 6 7 8 9 10");
-  assert_changes (filter, "0-3");
+  assert_changes (filter, "0-3*");
   g_object_unref (filter);
 
   filter = new_model (10, NULL, NULL);
@@ -280,7 +289,7 @@ test_empty_set_filter (void)
   gtk_filter_list_model_set_filter (filter, custom);
   g_object_unref (custom);
   assert_model (filter, "");
-  assert_changes (filter, "0-10");
+  assert_changes (filter, "0-10*");
   g_object_unref (filter);
 
   filter = new_model (10, NULL, NULL);
@@ -288,7 +297,7 @@ test_empty_set_filter (void)
   gtk_filter_list_model_set_filter (filter, custom);
   g_object_unref (custom);
   assert_model (filter, "3 4 5 6 7");
-  assert_changes (filter, "0-10+5");
+  assert_changes (filter, "0-10+5*");
   g_object_unref (filter);
 
   filter = new_model (10, NULL, NULL);
@@ -296,7 +305,7 @@ test_empty_set_filter (void)
   gtk_filter_list_model_set_filter (filter, custom);
   g_object_unref (custom);
   assert_model (filter, "1 2 8 9 10");
-  assert_changes (filter, "2-5");
+  assert_changes (filter, "2-5*");
   g_object_unref (filter);
 }
 
@@ -320,19 +329,19 @@ test_change_filter (void)
   gtk_filter_list_model_set_filter (filter, custom);
   g_object_unref (custom);
   assert_model (filter, "1 2 3 4 5 6");
-  assert_changes (filter, "3-2+3");
+  assert_changes (filter, "3-2+3*");
 
   custom = GTK_FILTER (gtk_custom_filter_new (is_smaller_than, GUINT_TO_POINTER (6), NULL));
   gtk_filter_list_model_set_filter (filter, custom);
   g_object_unref (custom);
   assert_model (filter, "1 2 3 4 5");
-  assert_changes (filter, "-5");
+  assert_changes (filter, "-5*");
 
   custom = GTK_FILTER (gtk_custom_filter_new (is_larger_than, GUINT_TO_POINTER (4), NULL));
   gtk_filter_list_model_set_filter (filter, custom);
   g_object_unref (custom);
   assert_model (filter, "5 6 7 8 9 10");
-  assert_changes (filter, "0-5+6");
+  assert_changes (filter, "0-5+6*");
 
   custom = GTK_FILTER (gtk_custom_filter_new (is_not_near, GUINT_TO_POINTER (2), NULL));
   gtk_filter_list_model_set_filter (filter, custom);
@@ -344,7 +353,7 @@ test_change_filter (void)
   gtk_filter_list_model_set_filter (filter, custom);
   g_object_unref (custom);
   assert_model (filter, "1 7 8 9 10");
-  assert_changes (filter, "0-2+1");
+  assert_changes (filter, "0-2+1*");
 
   g_object_unref (filter);
 }


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