[nautilus/wip/antoniof/new-list-view-continuation: 22/28] view-model: Use GSortListModel internally




commit aaccb731213128f4282149f8d2f78f9813de5085
Author: António Fernandes <antoniof gnome org>
Date:   Wed Apr 6 00:56:57 2022 +0100

    view-model: Use GSortListModel internally
    
    This is a required step in order to use GtkTreeListModel later.
    
    GtkTreeListModel doesn't work well when its internal models get
    resorted: it assumes the items are gone, not reordered, causing
    the row objects to get destroyed and the view to lose track of
    things.
    
    This might not be as efficient, but we've got no other option
    other than implementing a custom tree list model...

 src/nautilus-view-model.c | 90 ++++++++++++++++++++---------------------------
 src/nautilus-view-model.h |  1 +
 2 files changed, 40 insertions(+), 51 deletions(-)
---
diff --git a/src/nautilus-view-model.c b/src/nautilus-view-model.c
index 55c6cf8b6..8cb5e2809 100644
--- a/src/nautilus-view-model.c
+++ b/src/nautilus-view-model.c
@@ -8,9 +8,8 @@ struct _NautilusViewModel
 
     GHashTable *map_files_to_model;
     GListStore *internal_model;
+    GtkSortListModel *sort_model;
     GtkMultiSelection *selection_model;
-    GtkSorter *sorter;
-    gulong sorter_changed_handler_id;
 };
 
 static GType
@@ -38,12 +37,12 @@ nautilus_view_model_get_item (GListModel *list,
 {
     NautilusViewModel *self = NAUTILUS_VIEW_MODEL (list);
 
-    if (self->internal_model == NULL)
+    if (self->sort_model == NULL)
     {
         return NULL;
     }
 
-    return g_list_model_get_item (G_LIST_MODEL (self->internal_model), position);
+    return g_list_model_get_item (G_LIST_MODEL (self->sort_model), position);
 }
 
 static void
@@ -135,16 +134,16 @@ dispose (GObject *object)
         self->selection_model = NULL;
     }
 
-    if (self->internal_model != NULL)
+    if (self->sort_model != NULL)
     {
-        g_signal_handlers_disconnect_by_func (self->internal_model,
+        g_signal_handlers_disconnect_by_func (self->sort_model,
                                               g_list_model_items_changed,
                                               self);
-        g_object_unref (self->internal_model);
-        self->internal_model = NULL;
+        g_object_unref (self->sort_model);
+        self->sort_model = NULL;
     }
 
-    g_clear_signal_handler (&self->sorter_changed_handler_id, self->sorter);
+    g_clear_object (&self->internal_model);
 
     G_OBJECT_CLASS (nautilus_view_model_parent_class)->dispose (object);
 }
@@ -157,7 +156,6 @@ finalize (GObject *object)
     G_OBJECT_CLASS (nautilus_view_model_parent_class)->finalize (object);
 
     g_hash_table_destroy (self->map_files_to_model);
-    g_clear_object (&self->sorter);
 }
 
 static void
@@ -214,10 +212,11 @@ constructed (GObject *object)
     G_OBJECT_CLASS (nautilus_view_model_parent_class)->constructed (object);
 
     self->internal_model = g_list_store_new (NAUTILUS_TYPE_VIEW_ITEM_MODEL);
-    self->selection_model = gtk_multi_selection_new (g_object_ref (G_LIST_MODEL (self->internal_model)));
+    self->sort_model = gtk_sort_list_model_new (g_object_ref (G_LIST_MODEL (self->internal_model)), NULL);
+    self->selection_model = gtk_multi_selection_new (g_object_ref (G_LIST_MODEL (self->sort_model)));
     self->map_files_to_model = g_hash_table_new (NULL, NULL);
 
-    g_signal_connect_swapped (self->internal_model, "items-changed",
+    g_signal_connect_swapped (self->sort_model, "items-changed",
                               G_CALLBACK (g_list_model_items_changed), self);
     g_signal_connect_swapped (self->selection_model, "selection-changed",
                               G_CALLBACK (gtk_selection_model_selection_changed), self);
@@ -247,28 +246,6 @@ nautilus_view_model_init (NautilusViewModel *self)
 {
 }
 
-static gint
-compare_data_func (gconstpointer a,
-                   gconstpointer b,
-                   gpointer      user_data)
-{
-    NautilusViewModel *self = NAUTILUS_VIEW_MODEL (user_data);
-
-    g_return_val_if_fail (self->sorter != NULL, GTK_ORDERING_EQUAL);
-
-    return gtk_sorter_compare (self->sorter, (gpointer) a, (gpointer) b);
-}
-
-static void
-on_sorter_changed (GtkSorter       *sorter,
-                   GtkSorterChange  change,
-                   gpointer         user_data)
-{
-    NautilusViewModel *self = NAUTILUS_VIEW_MODEL (user_data);
-
-    g_list_store_sort (self->internal_model, compare_data_func, self);
-}
-
 NautilusViewModel *
 nautilus_view_model_new ()
 {
@@ -278,21 +255,22 @@ nautilus_view_model_new ()
 GtkSorter *
 nautilus_view_model_get_sorter (NautilusViewModel *self)
 {
-    return self->sorter;
+    return gtk_sort_list_model_get_sorter (self->sort_model);
 }
 
 void
 nautilus_view_model_set_sorter (NautilusViewModel *self,
                                 GtkSorter         *sorter)
 {
-    g_clear_signal_handler (&self->sorter_changed_handler_id, self->sorter);
-    g_set_object (&self->sorter, sorter);
-    self->sorter_changed_handler_id = g_signal_connect (self->sorter,
-                                                        "changed",
-                                                        G_CALLBACK (on_sorter_changed),
-                                                        self);
-
-    g_list_store_sort (self->internal_model, compare_data_func, self);
+    gtk_sort_list_model_set_sorter (self->sort_model, sorter);
+}
+
+void
+nautilus_view_model_sort (NautilusViewModel *self)
+{
+    /* Hack: Reset the sorter to trigger ressorting. */
+    gtk_sort_list_model_set_sorter (self->sort_model,
+                                    gtk_sort_list_model_get_sorter (self->sort_model));
 }
 
 GQueue *
@@ -369,7 +347,7 @@ nautilus_view_model_add_item (NautilusViewModel     *self,
     g_hash_table_insert (self->map_files_to_model,
                          nautilus_view_item_model_get_file (item),
                          item);
-    g_list_store_insert_sorted (self->internal_model, item, compare_data_func, self);
+    g_list_store_append (self->internal_model, item);
 }
 
 void
@@ -395,19 +373,29 @@ nautilus_view_model_add_items (NautilusViewModel *self,
     g_list_store_splice (self->internal_model,
                          g_list_model_get_n_items (G_LIST_MODEL (self->internal_model)),
                          0, array, g_queue_get_length (items));
-
-    g_list_store_sort (self->internal_model, compare_data_func, self);
 }
 
 guint
 nautilus_view_model_get_index (NautilusViewModel     *self,
                                NautilusViewItemModel *item)
 {
-    guint i = G_MAXUINT;
-    gboolean found;
+    guint n_items;
+    guint i = 0;
+
+    n_items = g_list_model_get_n_items (G_LIST_MODEL (self->sort_model));
+    while (i < n_items)
+    {
+        g_autoptr (NautilusViewItemModel) item_i = NULL;
+
+        item_i = NAUTILUS_VIEW_ITEM_MODEL (g_list_model_get_item (G_LIST_MODEL (self->sort_model), i));
+        g_warn_if_fail (item_i != NULL);
 
-    found = g_list_store_find (self->internal_model, item, &i);
-    g_warn_if_fail (found);
+        if (item_i == item)
+        {
+            return i;
+        }
+        i++;
+    }
 
-    return i;
+    return G_MAXUINT;
 }
diff --git a/src/nautilus-view-model.h b/src/nautilus-view-model.h
index d76c3987d..11dd98164 100644
--- a/src/nautilus-view-model.h
+++ b/src/nautilus-view-model.h
@@ -15,6 +15,7 @@ NautilusViewModel * nautilus_view_model_new (void);
 GtkSorter *nautilus_view_model_get_sorter (NautilusViewModel *self);
 void nautilus_view_model_set_sorter (NautilusViewModel *self,
                                      GtkSorter         *sorter);
+void nautilus_view_model_sort (NautilusViewModel *self);
 NautilusViewItemModel * nautilus_view_model_get_item_from_file (NautilusViewModel *self,
                                                                 NautilusFile      *file);
 GQueue * nautilus_view_model_get_items_from_files (NautilusViewModel *self,


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