[Xfce4-commits] <thunar:master> Add busy indication in shortcuts pane.

Nick Schermer noreply at xfce.org
Sat Oct 13 16:12:28 CEST 2012


Updating branch refs/heads/master
         to 28783086cff64b50f1e321165a85ea0e849f7dae (commit)
       from a2e30106f3c7242d83b1496aa0d902fbb172a51e (commit)

commit 28783086cff64b50f1e321165a85ea0e849f7dae
Author: Nick Schermer <nick at xfce.org>
Date:   Sun Oct 7 20:57:32 2012 +0200

    Add busy indication in shortcuts pane.

 thunar/thunar-shortcuts-model.c |  126 +++++++++++++++++++++++++++++++++++++++
 thunar/thunar-shortcuts-model.h |    6 ++
 thunar/thunar-shortcuts-view.c  |   50 ++++++++++++++--
 3 files changed, 176 insertions(+), 6 deletions(-)

diff --git a/thunar/thunar-shortcuts-model.c b/thunar/thunar-shortcuts-model.c
index 68f6ce7..84fdc30 100644
--- a/thunar/thunar-shortcuts-model.c
+++ b/thunar/thunar-shortcuts-model.c
@@ -43,6 +43,9 @@
 #include <thunar/thunar-device-monitor.h>
 #include <thunar/thunar-private.h>
 
+#define SPINNER_CYCLE_DURATION 1000
+#define SPINNER_NUM_STEPS      12
+
 
 
 #define THUNAR_SHORTCUT(obj) ((ThunarShortcut *) (obj))
@@ -146,6 +149,8 @@ struct _ThunarShortcutsModel
 
   GFileMonitor        *monitor;
   guint                load_idle_id;
+
+  guint busy_timeout_id;
 };
 
 struct _ThunarShortcut
@@ -158,6 +163,9 @@ struct _ThunarShortcut
   GIcon               *gicon;
   gint                 sort_id;
 
+  guint                busy : 1;
+  guint                busy_pule;
+
   GFile               *location;
   ThunarFile          *file;
   ThunarDevice        *device;
@@ -392,6 +400,10 @@ thunar_shortcuts_model_finalize (GObject *object)
 
   _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model));
 
+  /* stop the busy timeout */
+  if (model->busy_timeout_id != 0)
+    g_source_remove (model->busy_timeout_id);
+
   /* stop bookmark load idle */
   if (model->load_idle_id != 0)
     g_source_remove (model->load_idle_id);
@@ -469,6 +481,12 @@ thunar_shortcuts_model_get_column_type (GtkTreeModel *tree_model,
 
     case THUNAR_SHORTCUTS_MODEL_COLUMN_GROUP:
       return G_TYPE_UINT;
+
+    case THUNAR_SHORTCUTS_MODEL_COLUMN_BUSY:
+      return G_TYPE_BOOLEAN;
+
+    case THUNAR_SHORTCUTS_MODEL_COLUMN_BUSY_PULSE:
+      return G_TYPE_UINT;
     }
 
   _thunar_assert_not_reached ();
@@ -605,6 +623,16 @@ thunar_shortcuts_model_get_value (GtkTreeModel *tree_model,
       g_value_set_uint (value, shortcut->group);
       break;
 
+    case THUNAR_SHORTCUTS_MODEL_COLUMN_BUSY:
+      g_value_init (value, G_TYPE_BOOLEAN);
+      g_value_set_boolean (value, shortcut->busy);
+      break;
+
+    case THUNAR_SHORTCUTS_MODEL_COLUMN_BUSY_PULSE:
+      g_value_init (value, G_TYPE_UINT);
+      g_value_set_uint (value, shortcut->busy_pule);
+      break;
+
     default:
       _thunar_assert_not_reached ();
     }
@@ -1306,6 +1334,55 @@ thunar_shortcut_free (ThunarShortcut       *shortcut,
 
 
 
+static gboolean
+thunar_shortcuts_model_busy_timeout (gpointer data)
+{
+  ThunarShortcutsModel *model = THUNAR_SHORTCUTS_MODEL (data);
+  gboolean              keep_running = FALSE;
+  ThunarShortcut       *shortcut;
+  GtkTreePath          *path;
+  guint                 idx;
+  GtkTreeIter           iter;
+  GList                *lp;
+
+  _thunar_return_val_if_fail (THUNAR_IS_SHORTCUTS_MODEL (data), FALSE);
+
+  for (lp = model->shortcuts, idx = 0; lp != NULL; lp = lp->next, idx++)
+    {
+      shortcut = lp->data;
+      if (!shortcut->busy)
+        continue;
+
+      /* loop the pulse of the shortcut */
+      shortcut->busy_pule++;
+      if (shortcut->busy_pule >= SPINNER_NUM_STEPS)
+        shortcut->busy_pule = 0;
+
+      /* generate an iterator for the path */
+      GTK_TREE_ITER_INIT (iter, model->stamp, lp);
+
+      /* notify the views about the change */
+      path = gtk_tree_path_new_from_indices (idx, -1);
+      gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
+      gtk_tree_path_free (path);
+
+      /* keep the timeout running */
+      keep_running = TRUE;
+    }
+
+  return keep_running;
+}
+
+
+
+static void
+thunar_shortcuts_model_busy_timeout_destroyed (gpointer data)
+{
+  THUNAR_SHORTCUTS_MODEL (data)->busy_timeout_id = 0;
+}
+
+
+
 /**
  * thunar_shortcuts_model_get_default:
  *
@@ -1701,4 +1778,53 @@ thunar_shortcuts_model_rename (ThunarShortcutsModel *model,
 
 
 
+void
+thunar_shortcuts_model_set_busy (ThunarShortcutsModel *model,
+                                 ThunarDevice         *device,
+                                 gboolean              busy)
+{
+  ThunarShortcut *shortcut;
+  GList          *lp;
+  guint           idx;
+  GtkTreeIter     iter;
+  GtkTreePath    *path;
 
+  _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model));
+  _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
+
+  /* get the device */
+  for (lp = model->shortcuts, idx = 0; lp != NULL; lp = lp->next, idx++)
+    if (THUNAR_SHORTCUT (lp->data)->device == device)
+      break;
+
+  if (lp == NULL)
+    return;
+
+  shortcut = lp->data;
+  _thunar_assert (shortcut->device == device);
+
+  if (G_LIKELY (shortcut->busy != busy))
+    {
+      shortcut->busy = busy;
+
+      if (busy && model->busy_timeout_id == 0)
+        {
+          /* start the global cycle timeout */
+          model->busy_timeout_id =
+            gdk_threads_add_timeout_full (G_PRIORITY_DEFAULT,
+                                          SPINNER_CYCLE_DURATION / SPINNER_NUM_STEPS,
+                                          thunar_shortcuts_model_busy_timeout, model,
+                                          thunar_shortcuts_model_busy_timeout_destroyed);
+        }
+      else if (!busy)
+        {
+          /* generate an iterator for the path */
+          GTK_TREE_ITER_INIT (iter, model->stamp, lp);
+
+          /* notify the views about the change */
+          path = gtk_tree_path_new_from_indices (idx, -1);
+          gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
+          gtk_tree_path_free (path);
+        }
+    }
+}
diff --git a/thunar/thunar-shortcuts-model.h b/thunar/thunar-shortcuts-model.h
index b5d94f6..5932ad9 100644
--- a/thunar/thunar-shortcuts-model.h
+++ b/thunar/thunar-shortcuts-model.h
@@ -21,6 +21,7 @@
 #define __THUNAR_SHORTCUTS_MODEL_H__
 
 #include <thunar/thunar-file.h>
+#include <thunar/thunar-device.h>
 
 G_BEGIN_DECLS;
 
@@ -61,6 +62,8 @@ typedef enum
   THUNAR_SHORTCUTS_MODEL_COLUMN_MUTABLE,
   THUNAR_SHORTCUTS_MODEL_COLUMN_CAN_EJECT,
   THUNAR_SHORTCUTS_MODEL_COLUMN_GROUP,
+  THUNAR_SHORTCUTS_MODEL_COLUMN_BUSY,
+  THUNAR_SHORTCUTS_MODEL_COLUMN_BUSY_PULSE,
   THUNAR_SHORTCUTS_MODEL_N_COLUMNS,
 } ThunarShortcutsModelColumn;
 
@@ -104,6 +107,9 @@ void                   thunar_shortcuts_model_remove        (ThunarShortcutsMode
 void                   thunar_shortcuts_model_rename        (ThunarShortcutsModel *model,
                                                              GtkTreeIter          *iter,
                                                              const gchar          *name);
+void                   thunar_shortcuts_model_set_busy      (ThunarShortcutsModel *model,
+                                                             ThunarDevice         *device,
+                                                             gboolean              busy);
 
 G_END_DECLS;
 
diff --git a/thunar/thunar-shortcuts-view.c b/thunar/thunar-shortcuts-view.c
index 3e3b985..03badea 100644
--- a/thunar/thunar-shortcuts-view.c
+++ b/thunar/thunar-shortcuts-view.c
@@ -307,8 +307,6 @@ thunar_shortcuts_view_init (ThunarShortcutsView *view)
                                        "visible", THUNAR_SHORTCUTS_MODEL_COLUMN_NOT_HEADER,
                                        NULL);
 
-
-
   /* sync the "emblems" property of the icon renderer with the "shortcuts-icon-emblems" preference
    * and the "size" property of the renderer with the "shortcuts-icon-size" preference.
    */
@@ -327,6 +325,15 @@ thunar_shortcuts_view_init (ThunarShortcutsView *view)
                                        "visible", THUNAR_SHORTCUTS_MODEL_COLUMN_NOT_HEADER,
                                        NULL);
 
+  /* spinner to indicate (un)mount/eject delay */
+  renderer = gtk_cell_renderer_spinner_new ();
+  gtk_tree_view_column_pack_start (column, renderer, FALSE);
+  gtk_tree_view_column_set_attributes (column, renderer,
+                                       "visible", THUNAR_SHORTCUTS_MODEL_COLUMN_BUSY,
+                                       "active", THUNAR_SHORTCUTS_MODEL_COLUMN_BUSY,
+                                       "pulse", THUNAR_SHORTCUTS_MODEL_COLUMN_BUSY_PULSE,
+                                       NULL);
+
   /* allocate icon renderer for the eject symbol */
   renderer = gtk_cell_renderer_pixbuf_new ();
   g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, "icon-name", "media-eject", NULL);
@@ -335,7 +342,6 @@ thunar_shortcuts_view_init (ThunarShortcutsView *view)
                                        "visible", THUNAR_SHORTCUTS_MODEL_COLUMN_CAN_EJECT,
                                        NULL);
 
-
   /* enable drag support for the shortcuts view (actually used to support reordering) */
   gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (view), GDK_BUTTON1_MASK, drag_targets,
                                           G_N_ELEMENTS (drag_targets), GDK_ACTION_MOVE);
@@ -1414,8 +1420,9 @@ thunar_shortcuts_view_poke_device_finish (ThunarBrowser *browser,
                                           GError        *error,
                                           gpointer       user_data)
 {
-  gboolean new_window = GPOINTER_TO_UINT (user_data);
-  gchar   *device_name;
+  gboolean      new_window = GPOINTER_TO_UINT (user_data);
+  gchar        *device_name;
+  GtkTreeModel *model;
 
   _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (browser));
   _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
@@ -1433,6 +1440,10 @@ thunar_shortcuts_view_poke_device_finish (ThunarBrowser *browser,
                                  _("Failed to mount \"%s\""), device_name);
       g_free (device_name);
     }
+
+  /* stop the spinner */
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (browser));
+  thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (model), device, FALSE);
 }
 
 
@@ -1468,6 +1479,9 @@ thunar_shortcuts_view_open (ThunarShortcutsView *view,
 
       if (G_LIKELY (device != NULL))
         {
+          /* start the spinner */
+          thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (model), device, TRUE);
+
           thunar_browser_poke_device (THUNAR_BROWSER (view), device, view,
                                       thunar_shortcuts_view_poke_device_finish,
                                       GUINT_TO_POINTER (new_window));
@@ -1529,6 +1543,7 @@ thunar_shortcuts_view_eject_finish (ThunarDevice *device,
 {
   ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (user_data);
   gchar               *device_name;
+  GtkTreeModel        *model;
 
   _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
   _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view));
@@ -1542,6 +1557,10 @@ thunar_shortcuts_view_eject_finish (ThunarDevice *device,
       g_free (device_name);
     }
 
+  /* stop the spinner */
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
+  thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (model), device, FALSE);
+
   g_object_unref (view);
 }
 
@@ -1571,6 +1590,9 @@ thunar_shortcuts_view_eject (ThunarShortcutsView *view)
       window = gtk_widget_get_toplevel (GTK_WIDGET (view));
       mount_operation = gtk_mount_operation_new (GTK_WINDOW (window));
 
+      /* start the spinner */
+      thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (model), device, TRUE);
+
       /* try to unmount */
       thunar_device_eject (device,
                            mount_operation,
@@ -1591,7 +1613,8 @@ thunar_shortcuts_view_poke_device_mount_finish (ThunarBrowser *browser,
                                                 GError        *error,
                                                 gpointer       ignored)
 {
-  gchar *device_name;
+  gchar        *device_name;
+  GtkTreeModel *model;
 
   _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (browser));
   _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
@@ -1603,6 +1626,10 @@ thunar_shortcuts_view_poke_device_mount_finish (ThunarBrowser *browser,
                                  _("Failed to mount \"%s\""), device_name);
       g_free (device_name);
     }
+
+  /* stop the spinner */
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (browser));
+  thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (model), device, FALSE);
 }
 
 
@@ -1633,6 +1660,9 @@ thunar_shortcuts_view_mount (ThunarShortcutsView *view)
 
       if (G_LIKELY (device != NULL))
         {
+          /* start the spinner */
+          thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (model), device, TRUE);
+
           thunar_browser_poke_device (THUNAR_BROWSER (view), device, view,
                                       thunar_shortcuts_view_poke_device_mount_finish,
                                       NULL);
@@ -1650,6 +1680,7 @@ thunar_shortcuts_view_unmount_finish (ThunarDevice *device,
 {
   ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (user_data);
   gchar               *device_name;
+  GtkTreeModel        *model;
 
   _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
   _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view));
@@ -1663,6 +1694,10 @@ thunar_shortcuts_view_unmount_finish (ThunarDevice *device,
       g_free (device_name);
     }
 
+  /* stop the spinner */
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
+  thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (model), device, FALSE);
+
   g_object_unref (view);
 }
 
@@ -1692,6 +1727,9 @@ thunar_shortcuts_view_unmount (ThunarShortcutsView *view)
       window = gtk_widget_get_toplevel (GTK_WIDGET (view));
       mount_operation = gtk_mount_operation_new (GTK_WINDOW (window));
 
+      /* start the spinner */
+      thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (model), device, TRUE);
+
       /* try to unmount */
       thunar_device_unmount (device,
                              mount_operation,


More information about the Xfce4-commits mailing list