[gnome-disk-utility] Delay sensitivity during job updates



commit 72c5fee61aec7d18664c7c3a4e404dd00ce37ae6
Author: Kai Lüke <kailueke riseup net>
Date:   Mon Aug 14 23:23:22 2017 +0200

    Delay sensitivity during job updates
    
    If a series of jobs is executed the
    action buttons should not flicker.
    To achive that a delay for getting
    sensitive has been introduced.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=732565

 src/disks/gduwindow.c |  134 ++++++++++++++++++++++++++++++++++---------------
 1 files changed, 94 insertions(+), 40 deletions(-)
---
diff --git a/src/disks/gduwindow.c b/src/disks/gduwindow.c
index fa8ed0d..186e0d9 100644
--- a/src/disks/gduwindow.c
+++ b/src/disks/gduwindow.c
@@ -40,6 +40,8 @@
 #include "gduresizedialog.h"
 #include "gdulocaljob.h"
 
+#define JOB_SENSITIVITY_DELAY_MS 300
+
 struct _GduWindow
 {
   GtkApplicationWindow parent_instance;
@@ -54,6 +56,7 @@ struct _GduWindow
   UDisksObject *current_object;
   gboolean has_drive_job;
   gboolean has_volume_job;
+  guint delay_job_update_id;
 
   GtkWidget *volume_grid;
 
@@ -281,7 +284,7 @@ typedef struct
 
 /* ---------------------------------------------------------------------------------------------------- */
 
-static void update_all (GduWindow *window);
+static void update_all (GduWindow *window, gboolean is_delayed_job_update);
 
 static void on_volume_grid_changed (GduVolumeGrid  *grid,
                                     gpointer        user_data);
@@ -509,6 +512,7 @@ static gboolean
 select_object (GduWindow    *window,
                UDisksObject *object)
 {
+  gboolean is_delayed_job_update = FALSE;
   gboolean ret = FALSE;
   GtkTreeIter iter;
 
@@ -538,9 +542,15 @@ select_object (GduWindow    *window,
       if (window->current_object != NULL)
         g_object_unref (window->current_object);
       window->current_object = object != NULL ? g_object_ref (object) : NULL;
+      if (window->delay_job_update_id != 0)
+        {
+          g_source_remove (window->delay_job_update_id);
+          window->delay_job_update_id = 0;
+          is_delayed_job_update = TRUE;
+        }
     }
 
-  update_all (window);
+  update_all (window, is_delayed_job_update);
 
  out:
   return ret;
@@ -976,7 +986,7 @@ power_state_cell_func (GtkTreeViewColumn *column,
     visible = TRUE;
 
   gtk_cell_renderer_set_visible (renderer, visible);
-  update_all (window);
+  update_all (window, FALSE);
 }
 
 /* TODO: load from .ui file */
@@ -1074,6 +1084,7 @@ gdu_window_constructed (GObject *object)
 
   window->has_drive_job = FALSE;
   window->has_volume_job = FALSE;
+  window->delay_job_update_id = 0;
 
   window->header = create_header (window);
   if (!in_desktop ("Unity"))
@@ -1419,7 +1430,7 @@ gdu_window_constructed (GObject *object)
 
   ensure_something_selected (window);
   gtk_widget_grab_focus (window->device_tree_treeview);
-  update_all (window);
+  update_all (window, FALSE);
 
   /* attach the generic menu to the toplevel window for correct placement */
   gtk_menu_attach_to_widget (GTK_MENU (window->generic_menu),
@@ -1722,7 +1733,7 @@ block_compare_on_preferred (UDisksObject *a,
 
 /* ---------------------------------------------------------------------------------------------------- */
 
-static void update_device_page (GduWindow *window, ShowFlags *show_flags);
+static void update_device_page (GduWindow *window, ShowFlags *show_flags, gboolean is_delayed_job_update);
 
 /* Keep in sync with tabs in disks.ui file */
 typedef enum
@@ -1733,7 +1744,7 @@ typedef enum
 } DetailsPage;
 
 static void
-update_all (GduWindow *window)
+update_all (GduWindow *window, gboolean is_delayed_job_update)
 {
   ShowFlags show_flags = {0};
   DetailsPage page = DETAILS_PAGE_NOT_IMPLEMENTED;
@@ -1769,7 +1780,7 @@ update_all (GduWindow *window)
       break;
 
     case DETAILS_PAGE_DEVICE:
-      update_device_page (window, &show_flags);
+      update_device_page (window, &show_flags, is_delayed_job_update);
       break;
 
     default:
@@ -1784,7 +1795,7 @@ on_client_changed (UDisksClient   *client,
 {
   GduWindow *window = GDU_WINDOW (user_data);
   //g_debug ("on_client_changed");
-  update_all (window);
+  update_all (window, FALSE);
 }
 
 static void
@@ -1792,8 +1803,16 @@ on_volume_grid_changed (GduVolumeGrid  *grid,
                         gpointer        user_data)
 {
   GduWindow *window = GDU_WINDOW (user_data);
+  gboolean is_delayed_job_update = FALSE;
   //g_debug ("on_volume_grid_changed");
-  update_all (window);
+  if (window->delay_job_update_id != 0)
+    {
+      g_source_remove (window->delay_job_update_id);
+      window->delay_job_update_id = 0;
+      is_delayed_job_update = TRUE;
+    }
+
+  update_all (window, is_delayed_job_update);
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -1903,10 +1922,22 @@ get_job_progress_text (GduWindow *window,
 
 /* ---------------------------------------------------------------------------------------------------- */
 
+static gboolean
+delayed_job_update (gpointer user_data)
+{
+  GduWindow *window = GDU_WINDOW (user_data);
+
+  window->delay_job_update_id = 0;
+  update_all (window, TRUE);
+
+  return G_SOURCE_REMOVE;
+}
+
 static void
 update_jobs (GduWindow *window,
              GList     *jobs,
-             gboolean   is_volume)
+             gboolean   is_volume,
+             gboolean   is_delayed_job_update)
 {
   GtkWidget *label = window->devtab_drive_job_label;
   GtkWidget *grid = window->devtab_drive_job_grid;
@@ -1916,6 +1947,7 @@ update_jobs (GduWindow *window,
   GtkWidget *cancel_button = window->devtab_drive_job_cancel_button;
   gboolean drive_sensitivity;
   gboolean selected_volume_sensitivity;
+  gboolean gets_sensitive;
 
   if (is_volume)
     {
@@ -1928,13 +1960,27 @@ update_jobs (GduWindow *window,
     }
 
   drive_sensitivity = !gdu_application_has_running_job (window->application, window->current_object);
-  gtk_widget_set_sensitive (window->devtab_drive_generic_button, drive_sensitivity);
-  gtk_widget_set_sensitive (window->devtab_drive_eject_button, drive_sensitivity);
-  gtk_widget_set_sensitive (window->devtab_drive_power_off_button, drive_sensitivity);
-  gtk_widget_set_sensitive (window->devtab_drive_loop_detach_button, drive_sensitivity);
-
   selected_volume_sensitivity = (!window->has_volume_job && !window->has_drive_job);
-  gtk_widget_set_sensitive (window->devtab_grid_toolbar, selected_volume_sensitivity);
+  gets_sensitive = (drive_sensitivity && !gtk_widget_get_sensitive (window->devtab_drive_generic_button))
+                   || (selected_volume_sensitivity && !gtk_widget_get_sensitive 
(window->devtab_grid_toolbar));
+
+  /* delay for some milliseconds if change to sensitive or while a delay is pending */
+  if (window->delay_job_update_id > 0 || (gets_sensitive && !is_delayed_job_update))
+    {
+      if (window->delay_job_update_id != 0)
+        g_source_remove (window->delay_job_update_id);
+
+      window->delay_job_update_id = g_timeout_add (JOB_SENSITIVITY_DELAY_MS, delayed_job_update, window);
+    }
+  else
+    {
+      gtk_widget_set_sensitive (window->devtab_drive_generic_button, drive_sensitivity);
+      gtk_widget_set_sensitive (window->devtab_drive_eject_button, drive_sensitivity);
+      gtk_widget_set_sensitive (window->devtab_drive_power_off_button, drive_sensitivity);
+      gtk_widget_set_sensitive (window->devtab_drive_loop_detach_button, drive_sensitivity);
+
+      gtk_widget_set_sensitive (window->devtab_grid_toolbar, selected_volume_sensitivity);
+    }
 
   if (jobs == NULL)
     {
@@ -2005,21 +2051,23 @@ update_jobs (GduWindow *window,
 
 static void
 update_drive_jobs (GduWindow *window,
-                   GList     *jobs)
+                   GList     *jobs,
+                   gboolean   is_delayed_job_update)
 {
   window->has_volume_job = FALSE; /* comes before update_volume_jobs */
   window->has_drive_job = (jobs != NULL);
-  update_jobs (window, jobs, FALSE);
+  update_jobs (window, jobs, FALSE, is_delayed_job_update);
 }
 
 static void
 update_volume_jobs (GduWindow    *window,
                     GList        *jobs,
-                    UDisksObject *origin_object)
+                    UDisksObject *origin_object,
+                    gboolean      is_delayed_job_update)
 {
   /* in contrast to variable 'jobs' this call includes jobs on contained objects */
   window->has_volume_job = gdu_application_has_running_job (window->application, origin_object);
-  update_jobs (window, jobs, TRUE);
+  update_jobs (window, jobs, TRUE, is_delayed_job_update);
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -2028,7 +2076,8 @@ static void
 update_generic_drive_bits (GduWindow      *window,
                            UDisksBlock    *block,          /* should be the whole disk */
                            GList          *jobs,           /* jobs not specific to @block */
-                           ShowFlags      *show_flags)
+                           ShowFlags      *show_flags,
+                           gboolean        is_delayed_job_update)
 {
   if (block != NULL)
     {
@@ -2085,12 +2134,12 @@ update_generic_drive_bits (GduWindow      *window,
       UDisksObject *block_object = (UDisksObject *) g_dbus_interface_get_object (G_DBUS_INTERFACE (block));
       jobs = udisks_client_get_jobs_for_object (window->client, block_object);
       jobs = g_list_concat (jobs, gdu_application_get_local_jobs_for_object (window->application, 
block_object));
-      update_drive_jobs (window, jobs);
+      update_drive_jobs (window, jobs, is_delayed_job_update);
       g_list_free_full (jobs, g_object_unref);
     }
   else
     {
-      update_drive_jobs (window, jobs);
+      update_drive_jobs (window, jobs, is_delayed_job_update);
     }
 }
 
@@ -2100,7 +2149,8 @@ static void
 update_device_page_for_drive (GduWindow      *window,
                               UDisksObject   *object,
                               UDisksDrive    *drive,
-                              ShowFlags      *show_flags)
+                              ShowFlags      *show_flags,
+                              gboolean        is_delayed_job_update)
 {
   gchar *s;
   GList *blocks;
@@ -2129,7 +2179,7 @@ update_device_page_for_drive (GduWindow      *window,
 
   jobs = udisks_client_get_jobs_for_object (window->client, object);
   jobs = g_list_concat (jobs, gdu_application_get_local_jobs_for_object (window->application, object));
-  update_generic_drive_bits (window, block, jobs, show_flags);
+  update_generic_drive_bits (window, block, jobs, show_flags, is_delayed_job_update);
 
   gdu_volume_grid_set_no_media_string (GDU_VOLUME_GRID (window->volume_grid),
                                        _("No Media"));
@@ -2371,7 +2421,8 @@ update_device_page_for_loop (GduWindow      *window,
                              UDisksObject   *object,
                              UDisksBlock    *block,
                              UDisksLoop     *loop,
-                             ShowFlags      *show_flags)
+                             ShowFlags      *show_flags,
+                             gboolean        is_delayed_job_update)
 {
   UDisksObjectInfo *info = NULL;
   gchar *s = NULL;
@@ -2397,7 +2448,7 @@ update_device_page_for_loop (GduWindow      *window,
 
   gtk_widget_show (window->devtab_drive_generic_button);
 
-  update_generic_drive_bits (window, block, NULL, show_flags);
+  update_generic_drive_bits (window, block, NULL, show_flags, is_delayed_job_update);
 
   /* -------------------------------------------------- */
   /* 'Auto-clear' and 'Backing File' fields */
@@ -2435,7 +2486,8 @@ static void
 update_device_page_for_fake_block (GduWindow      *window,
                                    UDisksObject   *object,
                                    UDisksBlock    *block,
-                                   ShowFlags      *show_flags)
+                                   ShowFlags      *show_flags,
+                                   gboolean        is_delayed_job_update)
 {
   UDisksObjectInfo *info = NULL;
   gchar *device_desc = NULL;
@@ -2460,7 +2512,7 @@ update_device_page_for_fake_block (GduWindow      *window,
 
   gtk_widget_show (window->devtab_drive_generic_button);
 
-  update_generic_drive_bits (window, block, NULL, show_flags);
+  update_generic_drive_bits (window, block, NULL, show_flags, is_delayed_job_update);
 
   /* cleanup */
   g_clear_object (&info);
@@ -2511,7 +2563,8 @@ update_device_page_for_block (GduWindow          *window,
                               UDisksObject       *object,
                               UDisksBlock        *block,
                               guint64             size,
-                              ShowFlags          *show_flags)
+                              ShowFlags          *show_flags,
+                              gboolean            is_delayed_job_update)
 {
   const gchar *usage;
   const gchar *type;
@@ -2825,7 +2878,7 @@ update_device_page_for_block (GduWindow          *window,
       jobs = udisks_client_get_jobs_for_object (window->client, object);
       jobs = g_list_concat (jobs, gdu_application_get_local_jobs_for_object (window->application, object));
     }
-  update_volume_jobs (window, jobs, object);
+  update_volume_jobs (window, jobs, object, is_delayed_job_update);
   g_list_foreach (jobs, (GFunc) g_object_unref, NULL);
   g_list_free (jobs);
   g_clear_object (&partition_table);
@@ -2967,7 +3020,8 @@ maybe_hide (GtkWidget *widget,
 
 static void
 update_device_page (GduWindow      *window,
-                    ShowFlags      *show_flags)
+                    ShowFlags      *show_flags,
+                    gboolean        is_delayed_job_update)
 {
   UDisksObject *object;
   GduVolumeGridElementType type;
@@ -3006,11 +3060,11 @@ update_device_page (GduWindow      *window,
     show_flags->drive_buttons |= SHOW_FLAGS_DRIVE_BUTTONS_LOOP_DETACH;
 
   if (drive != NULL)
-    update_device_page_for_drive (window, object, drive, show_flags);
+    update_device_page_for_drive (window, object, drive, show_flags, is_delayed_job_update);
   else if (loop != NULL)
-    update_device_page_for_loop (window, object, block, loop, show_flags);
+    update_device_page_for_loop (window, object, block, loop, show_flags, is_delayed_job_update);
   else
-    update_device_page_for_fake_block (window, object, block, show_flags);
+    update_device_page_for_fake_block (window, object, block, show_flags, is_delayed_job_update);
 
   type = gdu_volume_grid_get_selected_type (GDU_VOLUME_GRID (window->volume_grid));
   size = gdu_volume_grid_get_selected_size (GDU_VOLUME_GRID (window->volume_grid));
@@ -3018,7 +3072,7 @@ update_device_page (GduWindow      *window,
   if (type == GDU_VOLUME_GRID_ELEMENT_TYPE_CONTAINER)
     {
       if (block != NULL)
-        update_device_page_for_block (window, object, block, size, show_flags);
+        update_device_page_for_block (window, object, block, size, show_flags, is_delayed_job_update);
     }
   else
     {
@@ -3035,11 +3089,11 @@ update_device_page (GduWindow      *window,
               break;
 
             case GDU_VOLUME_GRID_ELEMENT_TYPE_DEVICE:
-              update_device_page_for_block (window, object, block, size, show_flags);
+              update_device_page_for_block (window, object, block, size, show_flags, is_delayed_job_update);
               break;
 
             case GDU_VOLUME_GRID_ELEMENT_TYPE_NO_MEDIA:
-              update_device_page_for_block (window, object, block, size, show_flags);
+              update_device_page_for_block (window, object, block, size, show_flags, is_delayed_job_update);
               update_device_page_for_no_media (window, object, block, show_flags);
               break;
 
@@ -3803,7 +3857,7 @@ on_generic_tool_button_clicked (GtkToolButton *button, gpointer user_data)
 {
   GduWindow *window = GDU_WINDOW (user_data);
 
-  update_all (window);
+  update_all (window, FALSE);
 
   gtk_menu_popup_at_widget (GTK_MENU (window->generic_menu),
                             window->toolbutton_generic_menu,
@@ -4086,7 +4140,7 @@ loop_set_autoclear_cb (UDisksLoop      *loop,
   GError *error;
 
   /* in case of error, make sure the GtkSwitch:active corresponds to UDisksLoop:autoclear */
-  update_all (window);
+  update_all (window, FALSE);
 
   error = NULL;
   if (!udisks_loop_call_set_autoclear_finish (loop,


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