[Xfce4-commits] <thunar:master> Use a timeout/idle to request thumbnails in ThunarStandardView.

Jannis Pohlmann noreply at xfce.org
Mon Feb 14 14:10:02 CET 2011


Updating branch refs/heads/master
         to 834e6455488ccfb505127ba175e5366e1c652691 (commit)
       from f19df728cf8798152b175dd61467ea1633663660 (commit)

commit 834e6455488ccfb505127ba175e5366e1c652691
Author: Jannis Pohlmann <jannis at xfce.org>
Date:   Mon Feb 7 15:12:29 2011 +0100

    Use a timeout/idle to request thumbnails in ThunarStandardView.
    
    This is the second part of redesigning how thumbnails are requested in
    Thunar. Each ThunarStandardView now has a ThunerThumbnailer object.
    On scroll and resize events and whenever a new directory has finished
    loading, ThunarStandardView now schedules a timeout or idle handler
    (depending on the situation) to request thumbnails for all visible items
    of the view.
    
    This timeout/idle handler is rescheduled whenever the user starts
    or continues scrolling or resizing. This avoids sending requests while
    the user is scrolling and its important to not have D-Bus interfere with
    the Thunar main loop. We now have a much more responsive thumbnailing
    and scrolling experience!
    
    Requests are also dropped by each view when a directory is closed/left.
    This means that we no longer generate thumbnails the user is not
    interested in any more.
    
    This commit also uses the proper D-Bus method for cancelling thumbnail
    requests (it's called "Dequeue", not "Unqueue").
    
    The properties dialog is updated to match changes in the
    ThunarThumbnailer API.

 thunar/thunar-properties-dialog.c  |   60 ++++----
 thunar/thunar-standard-view.c      |  258 ++++++++++++++++++++++++++++++++++--
 thunar/thunar-thumbnailer-dbus.xml |    2 +-
 thunar/thunar-thumbnailer.c        |  191 ++++-----------------------
 thunar/thunar-thumbnailer.h        |   14 +-
 5 files changed, 307 insertions(+), 218 deletions(-)

diff --git a/thunar/thunar-properties-dialog.c b/thunar/thunar-properties-dialog.c
index 2633950..f52c20b 100644
--- a/thunar/thunar-properties-dialog.c
+++ b/thunar/thunar-properties-dialog.c
@@ -108,34 +108,34 @@ struct _ThunarPropertiesDialogClass
 
 struct _ThunarPropertiesDialog
 {
-  ThunarAbstractDialog     __parent__;
-
-  ThunarxProviderFactory  *provider_factory;
-  GList                   *provider_pages;
-
-  ThunarPreferences       *preferences;
-
-  ThunarFile              *file;
-
-  ThunarThumbnailer       *thumbnailer;
-  ThunarThumbnailerRequest thumbnail_request;
-
-  GtkWidget               *notebook;
-  GtkWidget               *icon_button;
-  GtkWidget               *icon_image;
-  GtkWidget               *name_entry;
-  GtkWidget               *kind_ebox;
-  GtkWidget               *kind_label;
-  GtkWidget               *openwith_chooser;
-  GtkWidget               *link_label;
-  GtkWidget               *origin_label;
-  GtkWidget               *deleted_label;
-  GtkWidget               *modified_label;
-  GtkWidget               *accessed_label;
-  GtkWidget               *freespace_label;
-  GtkWidget               *volume_image;
-  GtkWidget               *volume_label;
-  GtkWidget               *permissions_chooser;
+  ThunarAbstractDialog    __parent__;
+
+  ThunarxProviderFactory *provider_factory;
+  GList                  *provider_pages;
+
+  ThunarPreferences      *preferences;
+
+  ThunarFile             *file;
+
+  ThunarThumbnailer      *thumbnailer;
+  guint                   thumbnail_request;
+
+  GtkWidget              *notebook;
+  GtkWidget              *icon_button;
+  GtkWidget              *icon_image;
+  GtkWidget              *name_entry;
+  GtkWidget              *kind_ebox;
+  GtkWidget              *kind_label;
+  GtkWidget              *openwith_chooser;
+  GtkWidget              *link_label;
+  GtkWidget              *origin_label;
+  GtkWidget              *deleted_label;
+  GtkWidget              *modified_label;
+  GtkWidget              *accessed_label;
+  GtkWidget              *freespace_label;
+  GtkWidget              *volume_image;
+  GtkWidget              *volume_label;
+  GtkWidget              *permissions_chooser;
 };
 
 
@@ -526,7 +526,7 @@ thunar_properties_dialog_finalize (GObject *object)
   /* cancel any pending thumbnailer requests */
   if (dialog->thumbnail_request > 0)
     {
-      thunar_thumbnailer_unqueue (dialog->thumbnailer, dialog->thumbnail_request);
+      thunar_thumbnailer_dequeue (dialog->thumbnailer, dialog->thumbnail_request);
       dialog->thumbnail_request = 0;
     }
 
@@ -835,7 +835,7 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
   /* cancel any pending thumbnail requests */
   if (dialog->thumbnail_request > 0)
     {
-      thunar_thumbnailer_unqueue (dialog->thumbnailer, dialog->thumbnail_request);
+      thunar_thumbnailer_dequeue (dialog->thumbnailer, dialog->thumbnail_request);
       dialog->thumbnail_request = 0;
     }
 
diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c
index f671f05..6686052 100644
--- a/thunar/thunar-standard-view.c
+++ b/thunar/thunar-standard-view.c
@@ -1,21 +1,22 @@
-/* $Id$ */
+/* vi:set et ai sw=2 sts=2 ts=2: */
 /*-
  * Copyright (c) 2005-2006 Benedikt Meurer <benny at xfce.org>
- * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2009-2011 Jannis Pohlmann <jannis at xfce.org>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * This program is free software; you can redistribute it and/or 
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of 
+ * the License, or (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA  02111-1307  USA
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write to the Free 
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -49,6 +50,7 @@
 #include <thunar/thunar-standard-view-ui.h>
 #include <thunar/thunar-templates-action.h>
 #include <thunar/thunar-text-renderer.h>
+#include <thunar/thunar-thumbnailer.h>
 
 #if defined(GDK_WINDOWING_X11)
 #include <gdk/gdkx.h>
@@ -260,6 +262,14 @@ static gboolean             thunar_standard_view_drag_scroll_timer          (gpo
 static void                 thunar_standard_view_drag_scroll_timer_destroy  (gpointer                  user_data);
 static gboolean             thunar_standard_view_drag_timer                 (gpointer                  user_data);
 static void                 thunar_standard_view_drag_timer_destroy         (gpointer                  user_data);
+static void                 thunar_standard_view_cancel_thumbnailing        (ThunarStandardView       *standard_view);
+static void                 thunar_standard_view_schedule_thumbnail_timeout (ThunarStandardView       *standard_view);
+static void                 thunar_standard_view_schedule_thumbnail_idle    (ThunarStandardView       *standard_view);
+static gboolean             thunar_standard_view_request_thumbnails         (ThunarStandardView       *standard_view);
+static void                 thunar_standard_view_scrolled                   (GtkAdjustment            *adjustment,
+                                                                             ThunarStandardView       *standard_view);
+static void                 thunar_standard_view_size_allocate              (ThunarStandardView       *standard_view,
+                                                                             GtkAllocation            *allocation);
 
 
 
@@ -326,6 +336,12 @@ struct _ThunarStandardViewPrivate
   /* selected_files support */
   GList                  *selected_files;
 
+  /* support for generating thumbnails */
+  ThunarThumbnailer      *thumbnailer;
+  guint                   thumbnail_request;
+  guint                   thumbnail_source_id;
+  gboolean                thumbnailing_scheduled;
+
   /* Tree path for restoring the selection after selecting and 
    * deleting an item */
   GtkTreePath            *selection_before_delete;
@@ -531,6 +547,10 @@ thunar_standard_view_init (ThunarStandardView *standard_view)
   /* grab a reference on the provider factory */
   standard_view->priv->provider_factory = thunarx_provider_factory_get_default ();
 
+  /* create a thumbnailer */
+  standard_view->priv->thumbnailer = thunar_thumbnailer_new ();
+  standard_view->priv->thumbnailing_scheduled = FALSE;
+
   /* initialize the scrolled window */
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (standard_view),
                                   GTK_POLICY_AUTOMATIC,
@@ -596,6 +616,10 @@ thunar_standard_view_init (ThunarStandardView *standard_view)
    * files in our model changes.
    */
   g_signal_connect_swapped (G_OBJECT (standard_view->model), "notify::num-files", G_CALLBACK (thunar_standard_view_update_statusbar_text), standard_view);
+
+  /* connect to size allocation signals for generating thumbnail requests */
+  g_signal_connect_after (G_OBJECT (standard_view), "size-allocate", 
+                          G_CALLBACK (thunar_standard_view_size_allocate), NULL);
 }
 
 
@@ -607,6 +631,7 @@ thunar_standard_view_constructor (GType                  type,
 {
   ThunarStandardView *standard_view;
   ThunarZoomLevel     zoom_level;
+  GtkAdjustment      *adjustment;
   ThunarColumn        sort_column;
   GtkSortType         sort_order;
   GtkWidget          *view;
@@ -667,6 +692,14 @@ thunar_standard_view_constructor (GType                  type,
   g_signal_connect (G_OBJECT (view), "drag-data-delete", G_CALLBACK (thunar_standard_view_drag_data_delete), object);
   g_signal_connect (G_OBJECT (view), "drag-end", G_CALLBACK (thunar_standard_view_drag_end), object);
 
+  /* connect to scroll events for generating thumbnail requests */
+  adjustment = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (standard_view));
+  g_signal_connect (adjustment, "value-changed",
+                    G_CALLBACK (thunar_standard_view_scrolled), object);
+  adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (standard_view));
+  g_signal_connect (adjustment, "value-changed",
+                    G_CALLBACK (thunar_standard_view_scrolled), object);
+
   /* done, we have a working object */
   return object;
 }
@@ -678,6 +711,9 @@ thunar_standard_view_dispose (GObject *object)
 {
   ThunarStandardView *standard_view = THUNAR_STANDARD_VIEW (object);
 
+  /* cancel pending thumbnail sources and requests */
+  thunar_standard_view_cancel_thumbnailing (standard_view);
+
   /* unregister the "loading" binding */
   if (G_UNLIKELY (standard_view->loading_binding != NULL))
     exo_binding_unbind (standard_view->loading_binding);
@@ -709,6 +745,9 @@ thunar_standard_view_finalize (GObject *object)
   _thunar_assert (standard_view->ui_manager == NULL);
   _thunar_assert (standard_view->clipboard == NULL);
 
+  /* release the thumbnailer */
+  g_object_unref (standard_view->priv->thumbnailer);
+
   /* release the scroll_to_file reference (if any) */
   if (G_UNLIKELY (standard_view->priv->scroll_to_file != NULL))
     g_object_unref (G_OBJECT (standard_view->priv->scroll_to_file));
@@ -1128,6 +1167,9 @@ thunar_standard_view_set_current_directory (ThunarNavigator *navigator,
   _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
   _thunar_return_if_fail (current_directory == NULL || THUNAR_IS_FILE (current_directory));
 
+  /* cancel any pending thumbnail sources and requests */
+  thunar_standard_view_cancel_thumbnailing (standard_view);
+
   /* disconnect any previous "loading" binding */
   if (G_LIKELY (standard_view->loading_binding != NULL))
     exo_binding_unbind (standard_view->loading_binding);
@@ -1189,6 +1231,9 @@ thunar_standard_view_set_current_directory (ThunarNavigator *navigator,
   /* update the "Restore" action */
   gtk_action_set_visible (standard_view->priv->action_restore, trashed);
 
+  /* schedule a thumbnail timeout */
+  thunar_standard_view_schedule_thumbnail_timeout (standard_view);
+
   /* notify all listeners about the new/old current directory */
   g_object_notify (G_OBJECT (standard_view), "current-directory");
 }
@@ -1266,6 +1311,17 @@ thunar_standard_view_set_loading (ThunarStandardView *standard_view,
       thunar_file_list_free (selected_files);
     }
 
+  /* check if we're done loading and a thumbnail timeout or idle was requested */
+  if (!loading && standard_view->priv->thumbnailing_scheduled)
+    {
+      /* we've just finished loading. it will probably the user some time to
+       * understand the contents of the folder before he will start interacting
+       * with the view. so here we can safely schedule an idle function instead
+       * of a timeout */
+      thunar_standard_view_schedule_thumbnail_idle (standard_view);
+      standard_view->priv->thumbnailing_scheduled = FALSE;
+    }
+
   /* notify listeners */
   g_object_freeze_notify (G_OBJECT (standard_view));
   g_object_notify (G_OBJECT (standard_view), "loading");
@@ -3240,6 +3296,182 @@ thunar_standard_view_drag_timer_destroy (gpointer user_data)
 
 
 
+static void
+thunar_standard_view_cancel_thumbnailing (ThunarStandardView *standard_view)
+{
+  _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
+
+  /* check if we have a pending thumbnail timeout/idle handler */
+  if (standard_view->priv->thumbnail_source_id > 0)
+    {
+      /* cancel this handler */
+      g_source_remove (standard_view->priv->thumbnail_source_id);
+      standard_view->priv->thumbnail_source_id = 0;
+    }
+
+  /* check if we have a pending thumbnail request */
+  if (standard_view->priv->thumbnail_request > 0)
+    {
+      /* cancel the request */
+      thunar_thumbnailer_dequeue (standard_view->priv->thumbnailer,
+                                  standard_view->priv->thumbnail_request);
+      standard_view->priv->thumbnail_request = 0;
+    }
+}
+
+
+
+static void
+thunar_standard_view_schedule_thumbnail_timeout (ThunarStandardView *standard_view)
+{
+  _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
+  
+  /* delay creating the idle until the view has finished loading.
+   * this is done because we only can tell the visible range reliably after
+   * all items have been added and we've perhaps scrolled to the file remember
+   * the last time */
+  if (thunar_view_get_loading (THUNAR_VIEW (standard_view)))
+    {
+      standard_view->priv->thumbnailing_scheduled = TRUE;
+      return;
+    }
+
+  /* cancel any pending thumbnail sources and requests */
+  thunar_standard_view_cancel_thumbnailing (standard_view);
+
+  /* schedule the timeout handler */
+  standard_view->priv->thumbnail_source_id = 
+    g_timeout_add (250, (GSourceFunc) thunar_standard_view_request_thumbnails, 
+                   standard_view);
+}
+
+
+
+static void
+thunar_standard_view_schedule_thumbnail_idle (ThunarStandardView *standard_view)
+{
+  _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
+  
+  /* delay creating the idle until the view has finished loading.
+   * this is done because we only can tell the visible range reliably after
+   * all items have been added, layouting has finished and we've perhaps 
+   * scrolled to the file remembered the last time */
+  if (thunar_view_get_loading (THUNAR_VIEW (standard_view)))
+    {
+      standard_view->priv->thumbnailing_scheduled = TRUE;
+      return;
+    }
+
+  /* cancel any pending thumbnail sources or requests */
+  thunar_standard_view_cancel_thumbnailing (standard_view);
+
+  /* schedule the timeout or idle handler */
+  standard_view->priv->thumbnail_source_id = 
+    g_idle_add ((GSourceFunc) thunar_standard_view_request_thumbnails, standard_view);
+}
+
+
+
+static gboolean
+thunar_standard_view_request_thumbnails (ThunarStandardView *standard_view)
+{
+  GtkTreePath *start_path;
+  GtkTreePath *end_path;
+  GtkTreePath *path;
+  GtkTreeIter  iter;
+  ThunarFile  *file;
+  gboolean     valid_iter;
+  GList       *visible_files = NULL;
+
+  _thunar_return_val_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view), FALSE);
+
+  /* reschedule the source if we're still loading the folder */
+  if (thunar_view_get_loading (THUNAR_VIEW (standard_view)))
+    {
+      g_debug ("weird, this should never happen");
+      return TRUE;
+    }
+
+  /* compute visible item range */
+  if ((*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->get_visible_range) (standard_view,
+                                                                            &start_path,
+                                                                            &end_path))
+    {
+      /* iterate over the range to collect all files */
+      valid_iter = gtk_tree_model_get_iter (GTK_TREE_MODEL (standard_view->model),
+                                            &iter, start_path);
+
+      while (valid_iter)
+        {
+          /* prepend the file to the visible items list */
+          file = thunar_list_model_get_file (standard_view->model, &iter);
+          visible_files = g_list_prepend (visible_files, file);
+
+          /* check if we've reached the end of the visible range */
+          path = gtk_tree_model_get_path (GTK_TREE_MODEL (standard_view->model), &iter);
+          if (gtk_tree_path_compare (path, end_path) != 0)
+            {
+              /* try to compute the next visible item */
+              valid_iter = 
+                gtk_tree_model_iter_next (GTK_TREE_MODEL (standard_view->model), &iter);
+            }
+          else
+            {
+              /* we have reached the end, terminate the loop */
+              valid_iter = FALSE;
+            }
+
+          /* release the tree path */
+          gtk_tree_path_free (path);
+        }
+
+      /* queue a thumbnail request */
+      thunar_thumbnailer_queue_files (standard_view->priv->thumbnailer, visible_files,
+                                      &standard_view->priv->thumbnail_request);
+
+      /* release the file list */
+      g_list_foreach (visible_files, (GFunc) g_object_unref, NULL);
+      g_list_free (visible_files);
+
+      /* release the start and end path */
+      gtk_tree_path_free (start_path);
+      gtk_tree_path_free (end_path);
+    }
+
+  return FALSE;
+}
+
+
+
+static void
+thunar_standard_view_scrolled (GtkAdjustment      *adjustment,
+                               ThunarStandardView *standard_view)
+{
+  _thunar_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+  _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
+
+  /* ignore adjustment changes when the view is still loading */
+  if (thunar_view_get_loading (THUNAR_VIEW (standard_view)))
+    return;
+
+  /* reschedule a thumbnail request timeout */
+  thunar_standard_view_schedule_thumbnail_timeout (standard_view);
+}
+
+
+
+static void
+thunar_standard_view_size_allocate (ThunarStandardView *standard_view,
+                                    GtkAllocation      *allocation)
+{
+  _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
+
+  /* reschedule a thumbnail request timeout */
+  thunar_standard_view_schedule_thumbnail_timeout (standard_view);
+}
+
+
+
 /**
  * thunar_standard_view_context_menu:
  * @standard_view : a #ThunarStandardView instance.
diff --git a/thunar/thunar-thumbnailer-dbus.xml b/thunar/thunar-thumbnailer-dbus.xml
index e6b39f7..d0d2ada 100644
--- a/thunar/thunar-thumbnailer-dbus.xml
+++ b/thunar/thunar-thumbnailer-dbus.xml
@@ -11,7 +11,7 @@
       <arg type="u" name="handle" direction="out" />
     </method>
 
-    <method name="Unqueue">
+    <method name="Dequeue">
       <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
       <arg type="u" name="handle" direction="in" />
     </method>
diff --git a/thunar/thunar-thumbnailer.c b/thunar/thunar-thumbnailer.c
index 337bb8a..296f256 100644
--- a/thunar/thunar-thumbnailer.c
+++ b/thunar/thunar-thumbnailer.c
@@ -49,36 +49,19 @@
  *
  * When a request call is sent out, an internal request ID is created and 
  * associated with the corresponding DBusGProxyCall via the request_call_mapping hash 
- * table. It also remembers the URIs for the internal request ID in the 
- * request_uris_mapping hash table. 
+ * table. 
  *
  * The D-Bus reply handler then checks if there was an delivery error or
  * not. If the request method was sent successfully, the handle returned by the
  * D-Bus thumbnailer is associated bidirectionally with the internal request ID via 
- * the request_handle_mapping and handle_request_mappings. If the request could
- * not be sent at all, the URIs array is dropped from request_uris_mapping. In 
- * both cases, the association of the internal request ID with the DBusGProxyCall
- * is removed from request_call_mapping.
+ * the request_handle_mapping and handle_request_mappings. In both cases, the 
+ * association of the internal request ID with the DBusGProxyCall is removed from 
+ * request_call_mapping.
  *
- * These hash tables play a major role in the Started, Finished, Error and Ready
+ * These hash tables play a major role in the Finished, Error and Ready
  * signal handlers.
  *
  *
- * Started
- * =======
- *
- * When a Started signal is emitted by the D-Bus thumbnailer, ThunarThumbnailer
- * receives the handle and looks up the corresponding internal request ID. If
- * it exists (which it should), it schedules an idle function to handle the
- * signal in the application's main loop. 
- *
- * The idle function then looks up the URIs array for the request ID from the
- * request_uris_mapping. For each of these URIs the corresponding ThunarFile
- * is looked up from the file cache (which represents files currently being
- * used somewhere in the UI), and if the ThunarFile exists in the cache it's
- * thumb state is set to _LOADING (unless it's already marked as _READY).
- *
- *
  * Ready / Error
  * =============
  *
@@ -92,7 +75,7 @@
  *
  * The Finished signal handler looks up the internal request ID based on
  * the D-Bus thumbnailer handle. It then drops all corresponding information
- * from handle_request_mapping, request_handle_mapping and request_uris_mapping.
+ * from handle_request_mapping and request_handle_mapping.
  */
 
 
@@ -133,15 +116,11 @@ static void                   thunar_thumbnailer_thumbnailer_ready      (DBusGPr
                                                                          guint32                handle,
                                                                          const gchar          **uris,
                                                                          ThunarThumbnailer     *thumbnailer);
-static void                   thunar_thumbnailer_thumbnailer_started    (DBusGProxy            *proxy,
-                                                                         guint                  handle,
-                                                                         ThunarThumbnailer     *thumbnailer);
 static guint                  thunar_thumbnailer_queue_async            (ThunarThumbnailer     *thumbnailer,
                                                                          gchar                **uris,
                                                                          const gchar          **mime_hints);
 static gboolean               thunar_thumbnailer_error_idle             (gpointer               user_data);
 static gboolean               thunar_thumbnailer_ready_idle             (gpointer               user_data);
-static gboolean               thunar_thumbnailer_started_idle           (gpointer               user_data);
 static void                   thunar_thumbnailer_call_free              (ThunarThumbnailerCall *call);
 static void                   thunar_thumbnailer_idle_free              (gpointer               data);
 #endif
@@ -170,9 +149,6 @@ struct _ThunarThumbnailer
   /* hash table to map ThunarThumbnailer requests to DBusGProxyCalls */
   GHashTable *request_call_mapping;
 
-  /* hash table to map ThunarThumbnailer requests to URI arrays */
-  GHashTable *request_uris_mapping;
-
   GMutex     *lock;
 
   /* cached arrays of URI schemes and MIME types for which thumbnails 
@@ -181,7 +157,7 @@ struct _ThunarThumbnailer
   gchar     **supported_types;
 
   /* last ThunarThumbnailer request ID */
-  ThunarThumbnailerRequest last_request;
+  guint       last_request;
 
   /* IDs of idle functions */
   GList      *idles;
@@ -263,9 +239,6 @@ thunar_thumbnailer_init (ThunarThumbnailer *thumbnailer)
         g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
       thumbnailer->request_call_mapping = 
         g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
-      thumbnailer->request_uris_mapping =
-        g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, 
-                               (GDestroyNotify) g_strfreev);
     }
 
   /* release the D-Bus connection if we have one */
@@ -309,16 +282,15 @@ thunar_thumbnailer_finalize (GObject *object)
       g_hash_table_unref (thumbnailer->request_call_mapping);
 
 #if 0 
-      /* unqueue all pending requests */
+      /* dequeue all pending requests */
       list = g_hash_table_get_keys (thumbnailer->handle_request_mapping);
       for (lp = list; lp != NULL; lp = lp->next)
-        thunar_thumbnailer_unqueue_internal (thumbnailer, GPOINTER_TO_UINT (lp->data));
+        thunar_thumbnailer_dequeue_internal (thumbnailer, GPOINTER_TO_UINT (lp->data));
       g_list_free (list);
 #endif
 
       g_hash_table_unref (thumbnailer->handle_request_mapping);
       g_hash_table_unref (thumbnailer->request_handle_mapping);
-      g_hash_table_unref (thumbnailer->request_uris_mapping);
 
       /* disconnect from the thumbnailer proxy */
       g_signal_handlers_disconnect_matched (thumbnailer->thumbnailer_proxy,
@@ -398,9 +370,6 @@ thunar_thumbnailer_init_thumbnailer_proxy (ThunarThumbnailer *thumbnailer,
   dbus_g_proxy_connect_signal (thumbnailer->thumbnailer_proxy, "Ready",
                                G_CALLBACK (thunar_thumbnailer_thumbnailer_ready), 
                                thumbnailer, NULL);
-  dbus_g_proxy_connect_signal (thumbnailer->thumbnailer_proxy, "Started", 
-                               G_CALLBACK (thunar_thumbnailer_thumbnailer_started), 
-                               thumbnailer, NULL);
 }
 
 
@@ -528,7 +497,6 @@ thunar_thumbnailer_thumbnailer_finished (DBusGProxy        *proxy,
       /* the request is finished, drop all the information about it */
       g_hash_table_remove (thumbnailer->handle_request_mapping, request);
       g_hash_table_remove (thumbnailer->request_handle_mapping, request);
-      g_hash_table_remove (thumbnailer->request_uris_mapping, request);
     }
 }
 
@@ -569,44 +537,6 @@ thunar_thumbnailer_thumbnailer_ready (DBusGProxy        *proxy,
 
 
 static void
-thunar_thumbnailer_thumbnailer_started (DBusGProxy        *proxy,
-                                        guint              handle,
-                                        ThunarThumbnailer *thumbnailer)
-{
-  ThunarThumbnailerIdle *idle;
-  gpointer               request;
-
-  _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy));
-  _thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer));
-
-  /* look up the request for this D-Bus service handle */
-  request = g_hash_table_lookup (thumbnailer->handle_request_mapping, 
-                                 GUINT_TO_POINTER (handle));
-
-  /* check if we have a request for this handle */
-  if (request != NULL)
-    {
-      /* allocate a new idle struct */
-      idle = g_slice_new0 (ThunarThumbnailerIdle);
-      idle->type = THUNAR_THUMBNAILER_IDLE_STARTED;
-      idle->thumbnailer = g_object_ref (thumbnailer);
-
-      /* remember the request because we need it in the idle function */
-      idle->data.request = request;
-
-      /* remember the idle struct because we might have to remove it in finalize() */
-      thumbnailer->idles = g_list_prepend (thumbnailer->idles, idle);
-
-      /* call the started idle function when we have the time */
-      idle->id = g_idle_add_full (G_PRIORITY_LOW,
-                                  thunar_thumbnailer_started_idle, idle, 
-                                  thunar_thumbnailer_idle_free);
-    }
-}
-
-
-
-static void
 thunar_thumbnailer_queue_async_reply (DBusGProxy *proxy,
                                       guint       handle,
                                       GError     *error,
@@ -614,9 +544,6 @@ thunar_thumbnailer_queue_async_reply (DBusGProxy *proxy,
 {
   ThunarThumbnailerCall *call = user_data;
   ThunarThumbnailer     *thumbnailer = THUNAR_THUMBNAILER (call->thumbnailer);
-#ifndef NDEBUG
-  gchar                **uris;
-#endif
 
   _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy));
   _thunar_return_if_fail (call != NULL);
@@ -624,20 +551,7 @@ thunar_thumbnailer_queue_async_reply (DBusGProxy *proxy,
 
   g_mutex_lock (thumbnailer->lock);
 
-  if (error != NULL)
-    {
-#ifndef NDEBUG
-      /* get the URIs array for this request */
-      uris = g_hash_table_lookup (thumbnailer->request_uris_mapping, call->request);
-
-      /* the array should always exist, otherwise there's a bug in the program */
-      _thunar_assert (uris != NULL);
-#endif
-
-      /* the request is "finished", forget about its URIs */
-      g_hash_table_remove (thumbnailer->request_uris_mapping, call->request);
-    }
-  else
+  if (error == NULL)
     {
       /* remember that this request and D-Bus handle belong together */
       g_hash_table_insert (thumbnailer->request_handle_mapping,
@@ -686,9 +600,6 @@ thunar_thumbnailer_queue_async (ThunarThumbnailer *thumbnailer,
   thumbnailer_call->request = request;
   thumbnailer_call->thumbnailer = g_object_ref (thumbnailer);
 
-  /* remember the URIs for this request */
-  g_hash_table_insert (thumbnailer->request_uris_mapping, request, uris);
-
   /* queue thumbnails for the given URIs asynchronously */
   call = thunar_thumbnailer_proxy_queue_async (thumbnailer->thumbnailer_proxy,
                                                (const gchar **)uris, mime_hints, 
@@ -783,54 +694,6 @@ thunar_thumbnailer_ready_idle (gpointer user_data)
 
 
 
-static gboolean
-thunar_thumbnailer_started_idle (gpointer user_data)
-{
-  ThunarThumbnailerIdle *idle = user_data;
-  const gchar          **uris;
-  ThunarFile            *file;
-  GFile                 *gfile;
-  guint                  n;
-
-  _thunar_return_val_if_fail (idle != NULL, FALSE);
-  _thunar_return_val_if_fail (idle->type == THUNAR_THUMBNAILER_IDLE_STARTED, FALSE);
-
-  g_mutex_lock (idle->thumbnailer->lock);
-
-  /* look up the URIs that belong to this request */
-  uris = g_hash_table_lookup (idle->thumbnailer->request_uris_mapping, 
-                              idle->data.request);
-
-  /* iterate over all URIs if there are any */
-  for (n = 0; uris != NULL && uris[n] != NULL; ++n)
-    {
-      /* look up the corresponding ThunarFile from the cache */
-      gfile = g_file_new_for_uri (uris[n]);
-      file = thunar_file_cache_lookup (gfile);
-      g_object_unref (gfile);
-
-      /* check if we have a file in the cache */
-      if (file != NULL)
-        {
-          /* set the thumbnail state to loading unless we already have a thumbnail.
-           * This is to prevent race conditions with the other idle functions */
-          if (thunar_file_get_thumb_state (file) != THUNAR_FILE_THUMB_STATE_READY)
-            thunar_file_set_thumb_state (file, THUNAR_FILE_THUMB_STATE_LOADING);
-        }
-    }
-  
-
-  /* remove the idle struct */
-  idle->thumbnailer->idles = g_list_remove (idle->thumbnailer->idles, idle);
-
-  g_mutex_unlock (idle->thumbnailer->lock);
-
-  /* remove the idle source, which also destroys the idle struct */
-  return FALSE;
-}
-
-
-
 static void
 thunar_thumbnailer_call_free (ThunarThumbnailerCall *call)
 {
@@ -889,9 +752,9 @@ thunar_thumbnailer_new (void)
 
 
 gboolean
-thunar_thumbnailer_queue_file (ThunarThumbnailer        *thumbnailer,
-                               ThunarFile               *file,
-                               ThunarThumbnailerRequest *request)
+thunar_thumbnailer_queue_file (ThunarThumbnailer *thumbnailer,
+                               ThunarFile        *file,
+                               guint             *request)
 {
   GList files;
 
@@ -910,9 +773,9 @@ thunar_thumbnailer_queue_file (ThunarThumbnailer        *thumbnailer,
 
 
 gboolean
-thunar_thumbnailer_queue_files (ThunarThumbnailer        *thumbnailer,
-                                GList                    *files,
-                                ThunarThumbnailerRequest *request)
+thunar_thumbnailer_queue_files (ThunarThumbnailer *thumbnailer,
+                                GList             *files,
+                                guint             *request)
 {
   const gchar **mime_hints;
   gboolean      success = FALSE;
@@ -963,6 +826,9 @@ thunar_thumbnailer_queue_files (ThunarThumbnailer        *thumbnailer,
       /* fill URI and MIME hint arrays with items from the wait queue */
       for (lp = g_list_last (supported_files), n = 0; lp != NULL; lp = lp->prev, ++n)
         {
+          /* set the thumbnail state to loading */
+          thunar_file_set_thumb_state (lp->data, THUNAR_FILE_THUMB_STATE_LOADING);
+
           /* save URI and MIME hint in the arrays */
           uris[n] = thunar_file_dup_uri (lp->data);
           mime_hints[n] = thunar_file_get_content_type (lp->data);
@@ -976,15 +842,9 @@ thunar_thumbnailer_queue_files (ThunarThumbnailer        *thumbnailer,
 
       /* queue a thumbnail request for the URIs from the wait queue */
       if (request != NULL)
-        {
-          *request = thunar_thumbnailer_queue_async (thumbnailer, uris, 
-                                                     (const gchar **)mime_hints);
-        }
+        *request = thunar_thumbnailer_queue_async (thumbnailer, uris, mime_hints);
       else
-        {
-          thunar_thumbnailer_queue_async (thumbnailer, uris,
-                                          (const gchar **)mime_hints);
-        }
+        thunar_thumbnailer_queue_async (thumbnailer, uris, mime_hints);
 
       g_mutex_unlock (thumbnailer->lock);
 
@@ -1004,8 +864,8 @@ thunar_thumbnailer_queue_files (ThunarThumbnailer        *thumbnailer,
 
 
 void
-thunar_thumbnailer_unqueue (ThunarThumbnailer       *thumbnailer,
-                            ThunarThumbnailerRequest request)
+thunar_thumbnailer_dequeue (ThunarThumbnailer *thumbnailer,
+                            guint              request)
 {
 #ifdef HAVE_DBUS
   gpointer request_ptr;
@@ -1028,14 +888,13 @@ thunar_thumbnailer_unqueue (ThunarThumbnailer       *thumbnailer,
       handle = g_hash_table_lookup (thumbnailer->request_handle_mapping, request_ptr);
       if (GPOINTER_TO_UINT (handle) > 0)
         {
-          /* unqueue the request */
-          thunar_thumbnailer_proxy_unqueue (thumbnailer->thumbnailer_proxy, 
+          /* Dequeue the request */
+          thunar_thumbnailer_proxy_dequeue (thumbnailer->thumbnailer_proxy, 
                                             GPOINTER_TO_UINT (handle), NULL);
 
           /* drop all the request information */
           g_hash_table_remove (thumbnailer->handle_request_mapping, handle);
           g_hash_table_remove (thumbnailer->request_handle_mapping, request_ptr);
-          g_hash_table_remove (thumbnailer->request_uris_mapping, request_ptr);
         }
     }
 
diff --git a/thunar/thunar-thumbnailer.h b/thunar/thunar-thumbnailer.h
index c9744b9..81caf83 100644
--- a/thunar/thunar-thumbnailer.h
+++ b/thunar/thunar-thumbnailer.h
@@ -23,9 +23,7 @@
 
 #include <thunar/thunar-file.h>
 
-G_BEGIN_DECLS;
-
-typedef guint ThunarThumbnailerRequest;
+G_BEGIN_DECLS
 
 typedef struct _ThunarThumbnailerClass ThunarThumbnailerClass;
 typedef struct _ThunarThumbnailer      ThunarThumbnailer;
@@ -43,13 +41,13 @@ ThunarThumbnailer *thunar_thumbnailer_new             (void) G_GNUC_MALLOC;
 
 gboolean           thunar_thumbnailer_queue_file      (ThunarThumbnailer        *thumbnailer,
                                                        ThunarFile               *file,
-                                                       ThunarThumbnailerRequest *request);
+                                                       guint                    *request);
 gboolean           thunar_thumbnailer_queue_files     (ThunarThumbnailer        *thumbnailer,
                                                        GList                    *files,
-                                                       ThunarThumbnailerRequest *request);
-void               thunar_thumbnailer_unqueue         (ThunarThumbnailer        *thumbnailer,
-                                                       ThunarThumbnailerRequest  request);
+                                                       guint                    *request);
+void               thunar_thumbnailer_dequeue         (ThunarThumbnailer        *thumbnailer,
+                                                       guint                     request);
 
-G_END_DECLS;
+G_END_DECLS
 
 #endif /* !__THUNAR_THUMBNAILER_H__ */



More information about the Xfce4-commits mailing list