[nautilus/wip/antoniof/new-list-view-continuation: 77/81] list-view-item-ui: Show spinner while loading subfolders




commit 8e6ad68b92c9cd292bd8819c24699337d400509a
Author: António Fernandes <antoniof gnome org>
Date:   Thu Apr 7 00:17:45 2022 +0100

    list-view-item-ui: Show spinner while loading subfolders
    
    The spinner is shown only after 1 second without the directory having
    finished loading, to avoid visual noise when directories loads quickly.

 src/nautilus-list-view.c               | 22 ++++++++++++++
 src/nautilus-name-cell.c               | 53 ++++++++++++++++++++++++++++++++++
 src/nautilus-view-item.c               | 27 +++++++++++++++++
 src/nautilus-view-item.h               |  2 ++
 src/resources/ui/nautilus-name-cell.ui |  8 +++++
 5 files changed, 112 insertions(+)
---
diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c
index 5e0244d1d..6fe04a84f 100644
--- a/src/nautilus-list-view.c
+++ b/src/nautilus-list-view.c
@@ -959,6 +959,18 @@ unload_file_timeout (gpointer data)
     return G_SOURCE_REMOVE;
 }
 
+static void
+on_subdirectory_done_loading (NautilusDirectory *directory,
+                              GtkTreeListRow    *row)
+{
+    NautilusViewItem *item;
+
+    g_signal_handlers_disconnect_by_func (directory, on_subdirectory_done_loading, row);
+
+    item = NAUTILUS_VIEW_ITEM (gtk_tree_list_row_get_item (row));
+    nautilus_view_item_set_loading (item, FALSE);
+}
+
 static void
 on_row_expanded_changed (GObject    *gobject,
                          GParamSpec *pspec,
@@ -985,9 +997,19 @@ on_row_expanded_changed (GObject    *gobject,
         {
             nautilus_files_view_add_subdirectory (NAUTILUS_FILES_VIEW (self), directory);
         }
+        if (!nautilus_directory_are_all_files_seen (directory))
+        {
+            nautilus_view_item_set_loading (item, TRUE);
+            g_signal_connect_object (directory,
+                                     "done-loading",
+                                     G_CALLBACK (on_subdirectory_done_loading),
+                                     row,
+                                     0);
+        }
     }
     else
     {
+        nautilus_view_item_set_loading (item, FALSE);
         g_timeout_add_seconds (COLLAPSE_TO_UNLOAD_DELAY,
                                unload_file_timeout,
                                unload_delay_data_new (self, item, directory));
diff --git a/src/nautilus-name-cell.c b/src/nautilus-name-cell.c
index c8cf109ce..d67357319 100644
--- a/src/nautilus-name-cell.c
+++ b/src/nautilus-name-cell.c
@@ -7,6 +7,8 @@
 #include "nautilus-name-cell.h"
 #include "nautilus-file-utilities.h"
 
+#define LOADING_TIMEOUT_SECONDS 1
+
 struct _NautilusNameCell
 {
     NautilusViewCell parent_instance;
@@ -18,6 +20,7 @@ struct _NautilusNameCell
 
     GtkWidget *expander;
     GtkWidget *fixed_height_box;
+    GtkWidget *spinner;
     GtkWidget *icon;
     GtkWidget *label;
     GtkWidget *emblems_box;
@@ -26,6 +29,7 @@ struct _NautilusNameCell
     GtkWidget *path;
 
     gboolean show_snippet;
+    guint loading_timeout_id;
 };
 
 G_DEFINE_TYPE (NautilusNameCell, nautilus_name_cell, NAUTILUS_TYPE_VIEW_CELL)
@@ -251,6 +255,52 @@ on_item_is_cut_changed (NautilusNameCell *self)
     }
 }
 
+static gboolean
+on_loading_timeout (gpointer user_data)
+{
+    NautilusNameCell *self = NAUTILUS_NAME_CELL (user_data);
+    gboolean is_loading;
+
+    g_object_get (nautilus_view_cell_get_item (NAUTILUS_VIEW_CELL (self)),
+                  "is-loading", &is_loading,
+                  NULL);
+    if (is_loading)
+    {
+        gtk_widget_show (self->spinner);
+        gtk_spinner_start (GTK_SPINNER (self->spinner));
+    }
+
+    return G_SOURCE_REMOVE;
+}
+
+static void
+on_item_is_loading_changed (GObject    *object,
+                            GParamSpec *pspec,
+                            gpointer    user_data)
+{
+    NautilusNameCell *self = NAUTILUS_NAME_CELL (user_data);
+    gboolean is_loading;
+
+    if (object != G_OBJECT (nautilus_view_cell_get_item (NAUTILUS_VIEW_CELL (self))))
+    {
+        return;
+    }
+
+    g_clear_handle_id (&self->loading_timeout_id, g_source_remove);
+    g_object_get (object, "is-loading", &is_loading, NULL);
+    if (is_loading)
+    {
+        self->loading_timeout_id = g_timeout_add_seconds (LOADING_TIMEOUT_SECONDS,
+                                                          G_SOURCE_FUNC (on_loading_timeout),
+                                                          self);
+    }
+    else
+    {
+        gtk_widget_hide (self->spinner);
+        gtk_spinner_stop (GTK_SPINNER (self->spinner));
+    }
+}
+
 static void
 nautilus_name_cell_init (NautilusNameCell *self)
 {
@@ -264,6 +314,8 @@ nautilus_name_cell_init (NautilusNameCell *self)
                                     (GCallback) on_item_drag_accept_changed, self);
     g_signal_group_connect_swapped (self->item_signal_group, "notify::is-cut",
                                     (GCallback) on_item_is_cut_changed, self);
+    g_signal_group_connect_swapped (self->item_signal_group, "notify::is-loading",
+                                    (GCallback) on_item_is_loading_changed, self);
     g_signal_group_connect_swapped (self->item_signal_group, "file-changed",
                                     (GCallback) on_file_changed, self);
     g_signal_connect_object (self->item_signal_group, "bind",
@@ -297,6 +349,7 @@ nautilus_name_cell_class_init (NautilusNameCellClass *klass)
 
     gtk_widget_class_bind_template_child (widget_class, NautilusNameCell, expander);
     gtk_widget_class_bind_template_child (widget_class, NautilusNameCell, fixed_height_box);
+    gtk_widget_class_bind_template_child (widget_class, NautilusNameCell, spinner);
     gtk_widget_class_bind_template_child (widget_class, NautilusNameCell, icon);
     gtk_widget_class_bind_template_child (widget_class, NautilusNameCell, label);
     gtk_widget_class_bind_template_child (widget_class, NautilusNameCell, emblems_box);
diff --git a/src/nautilus-view-item.c b/src/nautilus-view-item.c
index 84423fa2d..31c11e3fe 100644
--- a/src/nautilus-view-item.c
+++ b/src/nautilus-view-item.c
@@ -12,6 +12,7 @@ struct _NautilusViewItem
     guint icon_size;
     gboolean is_cut;
     gboolean drag_accept;
+    gboolean is_loading;
     NautilusFile *file;
     GtkWidget *item_ui;
 };
@@ -25,6 +26,7 @@ enum
     PROP_ICON_SIZE,
     PROP_IS_CUT,
     PROP_DRAG_ACCEPT,
+    PROP_IS_LOADING,
     PROP_ITEM_UI,
     N_PROPS
 };
@@ -93,6 +95,12 @@ nautilus_view_item_get_property (GObject    *object,
         }
         break;
 
+        case PROP_IS_LOADING:
+        {
+            g_value_set_boolean (value, self->is_loading);
+        }
+        break;
+
         case PROP_ITEM_UI:
         {
             g_value_set_object (value, self->item_ui);
@@ -140,6 +148,12 @@ nautilus_view_item_set_property (GObject      *object,
         }
         break;
 
+        case PROP_IS_LOADING:
+        {
+            self->is_loading = g_value_get_boolean (value);
+        }
+        break;
+
         case PROP_ITEM_UI:
         {
             g_set_object (&self->item_ui, g_value_get_object (value));
@@ -186,6 +200,10 @@ nautilus_view_item_class_init (NautilusViewItemClass *klass)
                                                  "", "",
                                                  NAUTILUS_TYPE_FILE,
                                                  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | 
G_PARAM_STATIC_STRINGS);
+    properties[PROP_IS_LOADING] = g_param_spec_boolean ("is-loading",
+                                                        "", "",
+                                                        FALSE,
+                                                        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
     properties[PROP_ITEM_UI] = g_param_spec_object ("item-ui",
                                                     "", "",
                                                     GTK_TYPE_WIDGET,
@@ -246,6 +264,15 @@ nautilus_view_item_set_drag_accept (NautilusViewItem *self,
     g_object_set (self, "drag-accept", drag_accept, NULL);
 }
 
+void
+nautilus_view_item_set_loading (NautilusViewItem *self,
+                                gboolean          loading)
+{
+    g_return_if_fail (NAUTILUS_IS_VIEW_ITEM (self));
+
+    g_object_set (self, "is-loading", loading, NULL);
+}
+
 NautilusFile *
 nautilus_view_item_get_file (NautilusViewItem *self)
 {
diff --git a/src/nautilus-view-item.h b/src/nautilus-view-item.h
index 9bdaff158..268b20929 100644
--- a/src/nautilus-view-item.h
+++ b/src/nautilus-view-item.h
@@ -28,6 +28,8 @@ void               nautilus_view_item_set_cut       (NautilusViewItem *self,
                                                      gboolean          is_cut);
 void               nautilus_view_item_set_drag_accept (NautilusViewItem *self,
                                                        gboolean          drag_accept);
+void               nautilus_view_item_set_loading   (NautilusViewItem *self,
+                                                     gboolean          is_loading);
 
 NautilusFile *     nautilus_view_item_get_file      (NautilusViewItem *self);
 
diff --git a/src/resources/ui/nautilus-name-cell.ui b/src/resources/ui/nautilus-name-cell.ui
index 65db3d4a6..cb259d8fc 100644
--- a/src/resources/ui/nautilus-name-cell.ui
+++ b/src/resources/ui/nautilus-name-cell.ui
@@ -11,6 +11,14 @@
             <property name="orientation">horizontal</property>
             <property name="halign">fill</property>
             <property name="valign">center</property>
+            <child>
+              <object class="GtkSpinner" id="spinner">
+                <property name="visible">False</property>
+                <property name="spinning">False</property>
+                <property name="halign">center</property>
+                <property name="valign">center</property>
+              </object>
+            </child>
             <child>
               <object class="GtkBox" id="fixed_height_box">
                 <property name="orientation">vertical</property>


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