filterlistmodel: Pass through sections-changed
authorMatthias Clasen <mclasen@redhat.com>
Tue, 23 May 2023 13:13:00 +0000 (09:13 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sat, 27 May 2023 21:27:19 +0000 (17:27 -0400)
If our underlying model emits sections-changed,
we need to pass it on.

Add a test for this too.

gtk/gtkfilterlistmodel.c
testsuite/gtk/filterlistmodel.c

index a41b19fa6e15964840021dab588c811b48639452..840115162db90be0cb236d46956407eb67dc14e2 100644 (file)
@@ -190,6 +190,39 @@ gtk_filter_list_model_get_section (GtkSectionModel *model,
   *out_end = *out_start + gtk_bitset_get_size_in_range (self->matches, start, end - 1);
 }
 
+static void
+gtk_filter_list_model_sections_changed_cb (GtkSectionModel *model,
+                                           unsigned int     position,
+                                           unsigned int     n_items,
+                                           gpointer         user_data)
+{
+  GtkFilterListModel *self = GTK_FILTER_LIST_MODEL (user_data);
+  unsigned int start, end;
+
+  switch (self->strictness)
+    {
+    case GTK_FILTER_MATCH_NONE:
+      return;
+
+    case GTK_FILTER_MATCH_ALL:
+      gtk_section_model_sections_changed (GTK_SECTION_MODEL (self), position, n_items);
+      break;
+
+    case GTK_FILTER_MATCH_SOME:
+      if (position > 0)
+        start = gtk_bitset_get_size_in_range (self->matches, 0, position - 1);
+      else
+        start = 0;
+      end = gtk_bitset_get_size_in_range (self->matches, 0, position + n_items - 1);
+      if (end - start > 0)
+        gtk_section_model_sections_changed (GTK_SECTION_MODEL (self), start, end - start);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+}
+
 static void
 gtk_filter_list_model_section_model_init (GtkSectionModelInterface *iface)
 {
@@ -465,6 +498,7 @@ gtk_filter_list_model_clear_model (GtkFilterListModel *self)
 
   gtk_filter_list_model_stop_filtering (self);
   g_signal_handlers_disconnect_by_func (self->model, gtk_filter_list_model_items_changed_cb, self);
+  g_signal_handlers_disconnect_by_func (self->model, gtk_filter_list_model_sections_changed_cb, self);
   g_clear_object (&self->model);
   if (self->matches)
     gtk_bitset_remove_all (self->matches);
@@ -829,6 +863,8 @@ gtk_filter_list_model_set_model (GtkFilterListModel *self,
     {
       self->model = g_object_ref (model);
       g_signal_connect (model, "items-changed", G_CALLBACK (gtk_filter_list_model_items_changed_cb), self);
+      if (GTK_IS_SECTION_MODEL (model))
+        g_signal_connect (model, "sections-changed", G_CALLBACK (gtk_filter_list_model_sections_changed_cb), self);
       if (removed == 0)
         {
           self->strictness = GTK_FILTER_MATCH_NONE;
index 9d4891031356c56a961b7aadb45e0f85fec1c6b4..22a49ab1bc42cb254ccd85a2db46213c120fdcff 100644 (file)
@@ -478,6 +478,17 @@ filter_func (gpointer item,
   return s[0] == s[1];
 }
 
+static void
+sections_changed (GtkSectionModel *model,
+                  unsigned int     start,
+                  unsigned int     end,
+                  gpointer         user_data)
+{
+  gboolean *got_it = user_data;
+
+  *got_it = TRUE;
+}
+
 static void
 test_sections (void)
 {
@@ -499,6 +510,7 @@ test_sections (void)
   guint s, e;
   GtkFilterListModel *filtered;
   GtkFilter *filter;
+  gboolean got_it = FALSE;
 
   list = gtk_string_list_new (strings);
   sorter = GTK_SORTER (gtk_string_sorter_new (gtk_property_expression_new (GTK_TYPE_STRING_OBJECT, NULL, "string")));
@@ -541,6 +553,10 @@ test_sections (void)
   g_assert_cmpint (s, ==, 3);
   g_assert_cmpint (e, ==, 4);
 
+  g_signal_connect (filtered, "sections-changed", G_CALLBACK (sections_changed), &got_it);
+  gtk_sort_list_model_set_section_sorter (GTK_SORT_LIST_MODEL (sorted), NULL);
+  g_assert_true (got_it);
+
   g_object_unref (filtered);
   g_object_unref (sorted);
 }