[Xfce4-commits] r30018 - in thunar/branches/migration-to-gio: . thunar
Jannis Pohlmann
jannis at xfce.org
Mon Jun 15 00:58:18 CEST 2009
Author: jannis
Date: 2009-06-14 22:58:18 +0000 (Sun, 14 Jun 2009)
New Revision: 30018
Modified:
thunar/branches/migration-to-gio/ChangeLog
thunar/branches/migration-to-gio/thunar/thunar-icon-factory.c
thunar/branches/migration-to-gio/thunar/thunar-image.c
thunar/branches/migration-to-gio/thunar/thunar-list-model.c
thunar/branches/migration-to-gio/thunar/thunar-thumbnailer.c
thunar/branches/migration-to-gio/thunar/thunar-thumbnailer.h
Log:
* thunar/thunar-icon-factory.c: Rewrite the file icon loading process
once again, this time based on the also rewritten ThunarThumbnailer.
We first assume no thumbnail exists and use the default icon for the
MIME type. At the same time we request a thumbnail. Once the
thumbnailer has started processing the request, we change to a
loading icon. Once thumbnailer has the thumbnail ready, we change
to the thumbnail. If there's an error with the thumbnail, we
fall back to the default icon.
* thunar/thunar-image.c: Simplify this one. It now always requests the
icon from the icon factory and uses ThunarFileMonitor to watch the
file for changes. After each change it requests the icon from the
factory again. It's probably a good idea to use the thumbnailer
directly, so this will change in the future.
* thunar/thunar-list-model.c: Don't request thumbnails for the entire
content of new folders. Instead, just let the icon renderers do
their job. In the future, the model should at least unqueue all
requests for the old folder when the folder changes.
* thunar/thunar-thumbnailer.{c,h}: Rewrite the class entirely. It does
asynchronous D-Bus calls now and uses idle sources for updating the
thumbnail state of the ThunarFiles for which it requests the
thumbnails. It doesn't emit any signals anymore. In the future,
there should be a method to cancel all requests made by a component
for a certain base URI, so that we can cancel all pending requests
when leaving a folder.
Modified: thunar/branches/migration-to-gio/ChangeLog
===================================================================
--- thunar/branches/migration-to-gio/ChangeLog 2009-06-14 22:58:11 UTC (rev 30017)
+++ thunar/branches/migration-to-gio/ChangeLog 2009-06-14 22:58:18 UTC (rev 30018)
@@ -1,3 +1,30 @@
+2009-06-15 Jannis Pohlmann <jannis at xfce.org>
+
+ * thunar/thunar-icon-factory.c: Rewrite the file icon loading process
+ once again, this time based on the also rewritten ThunarThumbnailer.
+ We first assume no thumbnail exists and use the default icon for the
+ MIME type. At the same time we request a thumbnail. Once the
+ thumbnailer has started processing the request, we change to a
+ loading icon. Once thumbnailer has the thumbnail ready, we change
+ to the thumbnail. If there's an error with the thumbnail, we
+ fall back to the default icon.
+ * thunar/thunar-image.c: Simplify this one. It now always requests the
+ icon from the icon factory and uses ThunarFileMonitor to watch the
+ file for changes. After each change it requests the icon from the
+ factory again. It's probably a good idea to use the thumbnailer
+ directly, so this will change in the future.
+ * thunar/thunar-list-model.c: Don't request thumbnails for the entire
+ content of new folders. Instead, just let the icon renderers do
+ their job. In the future, the model should at least unqueue all
+ requests for the old folder when the folder changes.
+ * thunar/thunar-thumbnailer.{c,h}: Rewrite the class entirely. It does
+ asynchronous D-Bus calls now and uses idle sources for updating the
+ thumbnail state of the ThunarFiles for which it requests the
+ thumbnails. It doesn't emit any signals anymore. In the future,
+ there should be a method to cancel all requests made by a component
+ for a certain base URI, so that we can cancel all pending requests
+ when leaving a folder.
+
2009-06-14 Jannis Pohlmann <jannis at xfce.org>
* thunar/thunar-file.{c,h}: Emit a ThunarFileMonitor "file-changed"
Modified: thunar/branches/migration-to-gio/thunar/thunar-icon-factory.c
===================================================================
--- thunar/branches/migration-to-gio/thunar/thunar-icon-factory.c 2009-06-14 22:58:11 UTC (rev 30017)
+++ thunar/branches/migration-to-gio/thunar/thunar-icon-factory.c 2009-06-14 22:58:18 UTC (rev 30018)
@@ -38,6 +38,7 @@
#include <thunar/thunar-preferences.h>
#include <thunar/thunar-private.h>
#include <thunar/thunar-thumbnail-frame.h>
+#include <thunar/thunar-thumbnailer.h>
@@ -107,6 +108,7 @@
GObject __parent__;
ThunarVfsThumbFactory *thumbnail_factory;
+ ThunarThumbnailer *thumbnailer;
ThunarPreferences *preferences;
@@ -243,6 +245,9 @@
factory->thumbnail_factory = thunar_vfs_thumb_factory_new ((THUNAR_THUMBNAIL_SIZE > 128)
? THUNAR_VFS_THUMB_SIZE_LARGE
: THUNAR_VFS_THUMB_SIZE_NORMAL);
+
+ /* create a new thumbnailer */
+ factory->thumbnailer = thunar_thumbnailer_new ();
}
@@ -284,6 +289,9 @@
/* disconnect from the thumbnail factory */
g_object_unref (G_OBJECT (factory->thumbnail_factory));
+ /* release the thumbnailer */
+ g_object_unref (G_OBJECT (factory->thumbnailer));
+
/* remove the "changed" emission hook from the GtkIconTheme class */
g_signal_remove_emission_hook (g_signal_lookup ("changed", GTK_TYPE_ICON_THEME), factory->changed_hook_id);
@@ -913,23 +921,13 @@
ThunarFileIconState icon_state,
gint icon_size)
{
- GInputStream *stream;
- GtkIconInfo *icon_info;
-#if 0
- TumblerFileInfo *info;
- const gchar *content_type;
-#endif
- const gchar *thumbnail_path;
- GdkPixbuf *icon = NULL;
- GIcon *gicon;
-#if 0
- gchar **uris;
- gchar **types;
-#endif
- gchar *icon_name;
-#if 0
- gchar *uri;
-#endif
+ ThunarFileThumbState thumb_state;
+ GInputStream *stream;
+ GtkIconInfo *icon_info;
+ const gchar *thumbnail_path;
+ GdkPixbuf *icon = NULL;
+ GIcon *gicon;
+ gchar *icon_name;
_thunar_return_val_if_fail (THUNAR_IS_ICON_FACTORY (factory), NULL);
_thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
@@ -949,50 +947,90 @@
/* check if thumbnails are enabled and we can display a thumbnail for the item */
if (G_LIKELY (factory->show_thumbnails && thunar_file_is_regular (file)))
{
- gicon = thunar_file_get_preview_icon (file);
+ /* determine the thumbnail state of the file */
+ thumb_state = thunar_file_get_thumb_state (file);
- if (gicon != NULL)
+ if (thumb_state == THUNAR_FILE_THUMB_STATE_UNKNOWN)
{
- if (G_IS_THEMED_ICON (gicon))
+ /* we don't know the state yet so request a new thumbnail */
+ thunar_thumbnailer_queue_file (factory->thumbnailer, file);
+ }
+ else if (thumb_state == THUNAR_FILE_THUMB_STATE_LOADING)
+ {
+ /* we're in the process of creating a thumbnail so use a loading icon */
+ icon = thunar_icon_factory_lookup_icon (factory, "gnome-fs-loading-icon",
+ icon_size, FALSE);
+
+ if (icon != NULL)
+ return icon;
+ }
+ else if (thumb_state == THUNAR_FILE_THUMB_STATE_READY)
+ {
+ /* thumbnail is ready, but try the preview icon first */
+ gicon = thunar_file_get_preview_icon (file);
+
+ /* check if we have a preview icon */
+ if (gicon != NULL)
{
- icon_info = gtk_icon_theme_lookup_by_gicon (factory->icon_theme,
- gicon, icon_size,
- GTK_ICON_LOOKUP_USE_BUILTIN);
+ if (G_IS_THEMED_ICON (gicon))
+ {
+ /* we have a themed preview icon, look it up using the icon theme */
+ icon_info =
+ gtk_icon_theme_lookup_by_gicon (factory->icon_theme,
+ gicon, icon_size,
+ GTK_ICON_LOOKUP_USE_BUILTIN);
- if (icon_info != NULL)
+ /* check if the lookup succeeded */
+ if (icon_info != NULL)
+ {
+ /* try to load the pixbuf from the icon info */
+ icon = gtk_icon_info_load_icon (icon_info, NULL);
+ gtk_icon_info_free (icon_info);
+ }
+ }
+ else if (G_IS_LOADABLE_ICON (gicon))
{
- icon = gtk_icon_info_load_icon (icon_info, NULL);
- gtk_icon_info_free (icon_info);
+ /* we have a loadable icon, try to open it for reading */
+ stream = g_loadable_icon_load (G_LOADABLE_ICON (icon), icon_size,
+ NULL, NULL, NULL);
+
+ /* check if we have a valid input stream */
+ if (stream != NULL)
+ {
+ /* load the pixbuf from the stream */
+ icon = gdk_pixbuf_new_from_stream (stream, NULL, NULL);
+
+ /* destroy the stream */
+ g_object_unref (stream);
+ }
}
+
+ /* release the preview icon */
+ g_object_unref (gicon);
+
+ /* return the icon if we have one */
+ if (icon != NULL)
+ return icon;
}
- else if (G_IS_LOADABLE_ICON (gicon))
+ else
{
- stream = g_loadable_icon_load (G_LOADABLE_ICON (icon), icon_size, NULL,
- NULL, NULL);
+ /* we have no preview icon but the thumbnail should be ready. determine
+ * the filename of the thumbnail */
+ thumbnail_path = thunar_file_get_thumbnail_path (file);
- if (stream != NULL)
+ /* check if we have a valid path */
+ if (thumbnail_path != NULL)
{
- icon = gdk_pixbuf_new_from_stream (stream, NULL, NULL);
- g_object_unref (stream);
+ /* try to load the thumbnail */
+ icon = thunar_icon_factory_load_from_file (factory, thumbnail_path,
+ icon_size);
+
+ /* return the thumbnail if it could be loaded */
+ if (icon != NULL)
+ return icon;
}
}
-
- g_object_unref (gicon);
-
- if (icon != NULL)
- return icon;
}
- else
- {
- thumbnail_path = thunar_file_get_thumbnail_path (file);
- if (thumbnail_path != NULL)
- {
- icon = thunar_icon_factory_load_from_file (factory, thumbnail_path,
- icon_size);
- if (icon != NULL)
- return icon;
- }
- }
}
/* lookup the icon name for the icon in the given state and load the icon */
Modified: thunar/branches/migration-to-gio/thunar/thunar-image.c
===================================================================
--- thunar/branches/migration-to-gio/thunar/thunar-image.c 2009-06-14 22:58:11 UTC (rev 30017)
+++ thunar/branches/migration-to-gio/thunar/thunar-image.c 2009-06-14 22:58:18 UTC (rev 30018)
@@ -26,10 +26,10 @@
#include <glib-object.h>
#include <thunar/thunar-application.h>
+#include <thunar/thunar-file-monitor.h>
#include <thunar/thunar-image.h>
#include <thunar/thunar-icon-factory.h>
#include <thunar/thunar-private.h>
-#include <thunar/thunar-thumbnailer.h>
@@ -55,19 +55,9 @@
guint prop_id,
const GValue *value,
GParamSpec *pspec);
-static void thunar_image_file_changed (ThunarImage *image);
-static void thunar_image_thumbnailer_error (ThunarThumbnailer *thumbnailer,
- guint handle,
- const gchar **uris,
- gint code,
- const gchar *message,
+static void thunar_image_file_changed (ThunarFileMonitor *monitor,
+ ThunarFile *file,
ThunarImage *image);
-static void thunar_image_thumbnailer_finished (ThunarThumbnailer *thumbnailer,
- guint handle,
- ThunarImage *image);
-static void thunar_image_thumbnailer_started (ThunarThumbnailer *thumbnailer,
- guint handle,
- ThunarImage *image);
@@ -85,9 +75,8 @@
struct _ThunarImagePrivate
{
- ThunarThumbnailer *thumbnailer;
+ ThunarFileMonitor *monitor;
ThunarFile *file;
- guint thumbnailer_handle;
};
@@ -124,9 +113,9 @@
image->priv = THUNAR_IMAGE_GET_PRIVATE (image);
image->priv->file = NULL;
- g_signal_connect (image, "notify::file", G_CALLBACK (thunar_image_file_changed), NULL);
-
- image->priv->thumbnailer = thunar_thumbnailer_new ();
+ image->priv->monitor = thunar_file_monitor_get_default ();
+ g_signal_connect (image->priv->monitor, "file-changed",
+ G_CALLBACK (thunar_image_file_changed), image);
}
@@ -136,10 +125,12 @@
{
ThunarImage *image = THUNAR_IMAGE (object);
+ g_signal_handlers_disconnect_by_func (image->priv->monitor,
+ thunar_image_file_changed, image);
+ g_object_unref (image->priv->monitor);
+
thunar_image_set_file (image, NULL);
- g_object_unref (image->priv->thumbnailer);
-
(*G_OBJECT_CLASS (thunar_image_parent_class)->finalize) (object);
}
@@ -188,7 +179,7 @@
static void
-thunar_image_file_changed (ThunarImage *image)
+thunar_image_update (ThunarImage *image)
{
ThunarIconFactory *icon_factory;
GtkIconTheme *icon_theme;
@@ -196,79 +187,9 @@
GdkScreen *screen;
_thunar_return_if_fail (THUNAR_IS_IMAGE (image));
-
- if (image->priv->thumbnailer_handle != 0)
- {
- thunar_thumbnailer_unqueue (image->priv->thumbnailer,
- image->priv->thumbnailer_handle);
-
- image->priv->thumbnailer_handle = 0;
-
- g_signal_handlers_disconnect_matched (image->priv->thumbnailer,
- G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
- image);
- }
-
- gtk_image_set_from_pixbuf (GTK_IMAGE (image), NULL);
-
- if (image->priv->file != NULL)
- {
- g_signal_connect (image->priv->thumbnailer, "error",
- G_CALLBACK (thunar_image_thumbnailer_error), image);
- g_signal_connect (image->priv->thumbnailer, "finished",
- G_CALLBACK (thunar_image_thumbnailer_finished), image);
- g_signal_connect (image->priv->thumbnailer, "started",
- G_CALLBACK (thunar_image_thumbnailer_started), image);
-
- if (!thunar_thumbnailer_queue_file (image->priv->thumbnailer, image->priv->file,
- &image->priv->thumbnailer_handle))
- {
- g_signal_handlers_disconnect_matched (image->priv->thumbnailer,
- G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
- image);
- }
- screen = gtk_widget_get_screen (GTK_WIDGET (image));
- icon_theme = gtk_icon_theme_get_for_screen (screen);
- icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme);
-
- icon = thunar_icon_factory_load_file_icon (icon_factory, image->priv->file,
- THUNAR_FILE_ICON_STATE_DEFAULT, 48);
-
- gtk_image_set_from_pixbuf (GTK_IMAGE (image), icon);
-
- g_object_unref (icon_factory);
- }
-}
-
-
-
-static void
-thunar_image_thumbnailer_error (ThunarThumbnailer *thumbnailer,
- guint handle,
- const gchar **uris,
- gint code,
- const gchar *message,
- ThunarImage *image)
-{
- ThunarIconFactory *icon_factory;
- GtkIconTheme *icon_theme;
- GdkPixbuf *icon;
- GdkScreen *screen;
-
- _thunar_return_if_fail (THUNAR_IS_IMAGE (image));
-
- if (image->priv->thumbnailer_handle != handle)
- return;
-
- image->priv->thumbnailer_handle = 0;
-
- if (image->priv->file == NULL)
+ if (THUNAR_IS_FILE (image->priv->file))
{
- gtk_image_set_from_pixbuf (GTK_IMAGE (image), NULL);
- }
- else
- {
screen = gtk_widget_get_screen (GTK_WIDGET (image));
icon_theme = gtk_icon_theme_get_for_screen (screen);
icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme);
@@ -285,86 +206,20 @@
static void
-thunar_image_thumbnailer_finished (ThunarThumbnailer *thumbnailer,
- guint handle,
- ThunarImage *image)
+thunar_image_file_changed (ThunarFileMonitor *monitor,
+ ThunarFile *file,
+ ThunarImage *image)
{
- ThunarIconFactory *icon_factory;
- GtkIconTheme *icon_theme;
- GdkPixbuf *icon;
- GdkScreen *screen;
-
+ _thunar_return_if_fail (THUNAR_IS_FILE_MONITOR (monitor));
+ _thunar_return_if_fail (THUNAR_IS_FILE (file));
_thunar_return_if_fail (THUNAR_IS_IMAGE (image));
- if (image->priv->thumbnailer_handle != handle)
- return;
-
- image->priv->thumbnailer_handle = 0;
-
- g_signal_handlers_disconnect_matched (image->priv->thumbnailer,
- G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
- image);
-
- if (image->priv->file == NULL)
- {
- gtk_image_set_from_pixbuf (GTK_IMAGE (image), NULL);
- }
- else
- {
- /* TODO we only need to reload if the thumbnail was regenerated */
- thunar_file_changed (image->priv->file);
-
- screen = gtk_widget_get_screen (GTK_WIDGET (image));
- icon_theme = gtk_icon_theme_get_for_screen (screen);
- icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme);
-
- icon = thunar_icon_factory_load_file_icon (icon_factory, image->priv->file,
- THUNAR_FILE_ICON_STATE_DEFAULT, 48);
-
- gtk_image_set_from_pixbuf (GTK_IMAGE (image), icon);
-
- g_object_unref (icon_factory);
- }
+ if (file == image->priv->file)
+ thunar_image_update (image);
}
-static void
-thunar_image_thumbnailer_started (ThunarThumbnailer *thumbnailer,
- guint handle,
- ThunarImage *image)
-{
- ThunarIconFactory *icon_factory;
- GtkIconTheme *icon_theme;
- GdkPixbuf *icon;
- GdkScreen *screen;
-
- _thunar_return_if_fail (THUNAR_IS_IMAGE (image));
-
- if (image->priv->thumbnailer_handle != handle)
- return;
-
- if (image->priv->file == NULL)
- {
- gtk_image_set_from_pixbuf (GTK_IMAGE (image), NULL);
- }
- else
- {
- screen = gtk_widget_get_screen (GTK_WIDGET (image));
- icon_theme = gtk_icon_theme_get_for_screen (screen);
- icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme);
-
- icon = thunar_icon_factory_load_icon (icon_factory, "gnome-fs-loading-icon", 48,
- NULL, FALSE);
-
- gtk_image_set_from_pixbuf (GTK_IMAGE (image), icon);
-
- g_object_unref (icon_factory);
- }
-}
-
-
-
GtkWidget *
thunar_image_new (void)
{
@@ -392,5 +247,7 @@
else
image->priv->file = NULL;
+ thunar_image_update (image);
+
g_object_notify (G_OBJECT (image), "file");
}
Modified: thunar/branches/migration-to-gio/thunar/thunar-list-model.c
===================================================================
--- thunar/branches/migration-to-gio/thunar/thunar-list-model.c 2009-06-14 22:58:11 UTC (rev 30017)
+++ thunar/branches/migration-to-gio/thunar/thunar-list-model.c 2009-06-14 22:58:18 UTC (rev 30018)
@@ -34,7 +34,6 @@
#include <thunar/thunar-gobject-extensions.h>
#include <thunar/thunar-list-model.h>
#include <thunar/thunar-private.h>
-#include <thunar/thunar-thumbnailer.h>
#include <thunar/thunar-user.h>
@@ -191,21 +190,6 @@
static gint sort_by_type (const ThunarFile *a,
const ThunarFile *b,
gboolean case_sensitive);
-static void thunar_list_model_thumbnailer_error (ThunarThumbnailer *thumbnailer,
- guint request,
- const gchar **uris,
- gint code,
- const gchar *message,
- ThunarListModel *store);
-static void thunar_list_model_thumbnailer_finished (ThunarThumbnailer *thumbnailer,
- guint request,
- ThunarListModel *store);
-static void thunar_list_model_thumbnailer_ready (ThunarThumbnailer *thumbnailer,
- const gchar **uris,
- ThunarListModel *store);
-static void thunar_list_model_thumbnailer_started (ThunarThumbnailer *thumbnailer,
- guint request,
- ThunarListModel *store);
@@ -255,10 +239,6 @@
gint (*sort_func) (const ThunarFile *a,
const ThunarFile *b,
gboolean case_sensitive);
-
- ThunarThumbnailer *thumbnailer;
- GHashTable *thumbnailer_files;
- GList *thumbnailer_requests;
};
struct _SortTuple
@@ -502,20 +482,6 @@
store->file_monitor = thunar_file_monitor_get_default ();
g_signal_connect (G_OBJECT (store->file_monitor), "file-changed",
G_CALLBACK (thunar_list_model_file_changed), store);
-
- store->thumbnailer_files = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, NULL);
- store->thumbnailer_requests = NULL;
-
- store->thumbnailer = thunar_thumbnailer_new ();
- g_signal_connect (store->thumbnailer, "error",
- G_CALLBACK (thunar_list_model_thumbnailer_error), store);
- g_signal_connect (store->thumbnailer, "finished",
- G_CALLBACK (thunar_list_model_thumbnailer_finished), store);
- g_signal_connect (store->thumbnailer, "ready",
- G_CALLBACK (thunar_list_model_thumbnailer_ready), store);
- g_signal_connect (store->thumbnailer, "started",
- G_CALLBACK (thunar_list_model_thumbnailer_started), store);
}
@@ -524,20 +490,7 @@
thunar_list_model_finalize (GObject *object)
{
ThunarListModel *store = THUNAR_LIST_MODEL (object);
- GList *lp;
- /* unqueue all pending thumbnailer requests */
- for (lp = store->thumbnailer_requests; lp != NULL; lp = lp->next)
- thunar_thumbnailer_unqueue (store->thumbnailer, GPOINTER_TO_UINT (lp->data));
-
- /* destroy the URI to thumbnailer request mapping */
- g_hash_table_unref (store->thumbnailer_files);
-
- /* release the reference on the thumbnailer */
- g_signal_handlers_disconnect_matched (store->thumbnailer, G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, store);
- g_object_unref (store->thumbnailer);
-
/* unlink from the folder (if any) */
thunar_list_model_set_folder (store, NULL);
@@ -1339,8 +1292,6 @@
ThunarFile *file;
GSList *prev = NULL;
GSList *row;
- GList *lp;
- guint request;
gint *indices;
gint index = 0;
@@ -1352,19 +1303,6 @@
path = gtk_tree_path_new_from_indices (0, -1);
indices = gtk_tree_path_get_indices (path);
- if (thunar_thumbnailer_queue_files (store->thumbnailer, files, &request))
- {
- for (lp = files; lp != NULL; lp = lp->next)
- {
- g_hash_table_insert (store->thumbnailer_files,
- thunar_file_dup_uri (lp->data),
- GUINT_TO_POINTER (request));
- }
-
- store->thumbnailer_requests = g_list_prepend (store->thumbnailer_requests,
- GUINT_TO_POINTER (request));
- }
-
/* process all added files */
for (; files != NULL; files = files->next)
{
@@ -1680,82 +1618,6 @@
-static void
-thunar_list_model_thumbnailer_error (ThunarThumbnailer *thumbnailer,
- guint request,
- const gchar **uris,
- gint code,
- const gchar *message,
- ThunarListModel *store)
-{
- guint n;
-
- _thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer));
- _thunar_return_if_fail (uris != NULL);
- _thunar_return_if_fail (message != NULL);
- _thunar_return_if_fail (THUNAR_IS_LIST_MODEL (store));
-
- for (n = 0; uris[n] != NULL; ++n)
- g_hash_table_remove (store->thumbnailer_files, uris[n]);
-}
-
-
-
-static void
-thunar_list_model_thumbnailer_finished (ThunarThumbnailer *thumbnailer,
- guint request,
- ThunarListModel *store)
-{
- _thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer));
- _thunar_return_if_fail (THUNAR_IS_LIST_MODEL (store));
-
- store->thumbnailer_requests = g_list_remove_all (store->thumbnailer_requests,
- GUINT_TO_POINTER (request));
-}
-
-
-
-static void
-thunar_list_model_thumbnailer_ready (ThunarThumbnailer *thumbnailer,
- const gchar **uris,
- ThunarListModel *store)
-{
- ThunarFile *file;
- GFile *gfile;
- guint n;
-
- _thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer));
- _thunar_return_if_fail (uris != NULL);
- _thunar_return_if_fail (THUNAR_IS_LIST_MODEL (store));
-
- for (n = 0; uris[n] != NULL; ++n)
- {
- if (g_hash_table_lookup (store->thumbnailer_files, uris[n]) != NULL)
- {
- gfile = g_file_new_for_uri (uris[n]);
- file = thunar_file_cache_lookup (gfile);
- g_object_unref (gfile);
-
- if (file != NULL)
- thunar_file_changed (file);
-
- g_hash_table_remove (store->thumbnailer_files, uris[n]);
- }
- }
-}
-
-
-
-static void
-thunar_list_model_thumbnailer_started (ThunarThumbnailer *thumbnailer,
- guint request,
- ThunarListModel *store)
-{
- /* TODO Set the status of the corresponding ThunarFile's to LOADING */
-}
-
-
-
/**
* thunar_list_model_new:
*
@@ -1929,11 +1791,6 @@
if (G_UNLIKELY (store->folder == folder))
return;
- g_hash_table_remove_all (store->thumbnailer_files);
-
- for (lp = store->thumbnailer_requests; lp != NULL; lp = lp->next)
- thunar_thumbnailer_unqueue (store->thumbnailer, GPOINTER_TO_UINT (lp->data));
-
/* unlink from the previously active folder (if any) */
if (G_LIKELY (store->folder != NULL))
{
Modified: thunar/branches/migration-to-gio/thunar/thunar-thumbnailer.c
===================================================================
--- thunar/branches/migration-to-gio/thunar/thunar-thumbnailer.c 2009-06-14 22:58:11 UTC (rev 30017)
+++ thunar/branches/migration-to-gio/thunar/thunar-thumbnailer.c 2009-06-14 22:58:18 UTC (rev 30018)
@@ -33,41 +33,53 @@
-/* signal identifiers */
-enum
+typedef enum
{
- SIGNAL_ERROR,
- SIGNAL_FINISHED,
- SIGNAL_READY,
- SIGNAL_STARTED,
- LAST_SIGNAL,
-};
+ THUNAR_THUMBNAILER_IDLE_ERROR,
+ THUNAR_THUMBNAILER_IDLE_READY,
+ THUNAR_THUMBNAILER_IDLE_STARTED,
+} ThunarThumbnailerIdleType;
-static void thunar_thumbnailer_init_thumbnailer_proxy (ThunarThumbnailer *thumbnailer,
- DBusGConnection *connection);
-static void thunar_thumbnailer_init_manager_proxy (ThunarThumbnailer *thumbnailer,
- DBusGConnection *connection);
-static void thunar_thumbnailer_finalize (GObject *object);
-static void thunar_thumbnailer_thumbnailer_error (DBusGProxy *proxy,
- guint handle,
- const gchar **uris,
- gint code,
- const gchar *message,
- ThunarThumbnailer *thumbnailer);
-static void thunar_thumbnailer_thumbnailer_finished (DBusGProxy *proxy,
- guint handle,
- ThunarThumbnailer *thumbnailer);
-static void thunar_thumbnailer_thumbnailer_ready (DBusGProxy *proxy,
- const gchar **uris,
- ThunarThumbnailer *thumbnailer);
-static void thunar_thumbnailer_thumbnailer_started (DBusGProxy *proxy,
- guint handle,
- ThunarThumbnailer *thumbnailer);
+typedef struct _ThunarThumbnailerCall ThunarThumbnailerCall;
+typedef struct _ThunarThumbnailerIdle ThunarThumbnailerIdle;
+static void thunar_thumbnailer_init_thumbnailer_proxy (ThunarThumbnailer *thumbnailer,
+ DBusGConnection *connection);
+static void thunar_thumbnailer_init_manager_proxy (ThunarThumbnailer *thumbnailer,
+ DBusGConnection *connection);
+static void thunar_thumbnailer_finalize (GObject *object);
+static gboolean thunar_thumbnailer_file_is_supported (ThunarThumbnailer *thumbnailer,
+ ThunarFile *file);
+static void thunar_thumbnailer_thumbnailer_finished (DBusGProxy *proxy,
+ guint handle,
+ ThunarThumbnailer *thumbnailer);
+static void thunar_thumbnailer_thumbnailer_error (DBusGProxy *proxy,
+ guint handle,
+ const gchar **uris,
+ gint code,
+ const gchar *message,
+ ThunarThumbnailer *thumbnailer);
+static void thunar_thumbnailer_thumbnailer_ready (DBusGProxy *proxy,
+ const gchar **uris,
+ ThunarThumbnailer *thumbnailer);
+static void thunar_thumbnailer_thumbnailer_started (DBusGProxy *proxy,
+ guint handle,
+ ThunarThumbnailer *thumbnailer);
+static gpointer thunar_thumbnailer_queue_async (ThunarThumbnailer *thumbnailer,
+ const 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);
+
+
+
struct _ThunarThumbnailerClass
{
GObjectClass __parent__;
@@ -77,20 +89,58 @@
{
GObject __parent__;
+ /* proxies to communicate with D-Bus services */
DBusGProxy *manager_proxy;
DBusGProxy *thumbnailer_proxy;
+ /* hash table to map D-Bus service handles to ThunarThumbnailer requests */
+ GHashTable *handle_request_mapping;
+
+ /* hash table to map ThunarThumbnailer requests to D-Bus service handles */
+ GHashTable *request_handle_mapping;
+
+ /* 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 array of MIME types for which thumbnails can be generated */
gchar **supported_types;
+
+ /* last ThunarThumbnailer request ID */
+ gpointer last_request;
+
+ /* IDs of idle functions */
+ GList *idles;
};
+struct _ThunarThumbnailerCall
+{
+ ThunarThumbnailer *thumbnailer;
+ gpointer request;
+};
+struct _ThunarThumbnailerIdle
+{
+ ThunarThumbnailerIdleType type;
+ ThunarThumbnailer *thumbnailer;
+ guint id;
+ union
+ {
+ char **uris;
+ gpointer request;
+ } data;
+};
+
+
+
static DBusGProxy *thunar_thumbnailer_manager_proxy;
static DBusGProxy *thunar_thumbnailer_proxy;
static DBusGProxy *thunar_manager_proxy;
-static guint thumbnailer_signals[LAST_SIGNAL];
@@ -105,54 +155,6 @@
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = thunar_thumbnailer_finalize;
-
- /* TODO this should actually be VOID:UINT,POINTER,INT,STRING */
- thumbnailer_signals[SIGNAL_ERROR] =
- g_signal_new ("error",
- THUNAR_TYPE_THUMBNAILER,
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- _thunar_marshal_VOID__UINT_POINTER_UINT_STRING,
- G_TYPE_NONE,
- 1,
- G_TYPE_UINT,
- G_TYPE_STRV,
- G_TYPE_UINT,
- G_TYPE_STRING);
-
- thumbnailer_signals[SIGNAL_FINISHED] =
- g_signal_new ("finished",
- THUNAR_TYPE_THUMBNAILER,
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT,
- G_TYPE_NONE,
- 1,
- G_TYPE_UINT);
-
- thumbnailer_signals[SIGNAL_READY] =
- g_signal_new ("ready",
- THUNAR_TYPE_THUMBNAILER,
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE,
- 1,
- G_TYPE_STRV);
-
- thumbnailer_signals[SIGNAL_STARTED] =
- g_signal_new ("started",
- THUNAR_TYPE_THUMBNAILER,
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT,
- G_TYPE_NONE,
- 1,
- G_TYPE_UINT);
}
@@ -163,14 +165,33 @@
DBusGConnection *connection;
thumbnailer->lock = g_mutex_new ();
-
thumbnailer->supported_types = NULL;
+ thumbnailer->last_request = GUINT_TO_POINTER (0);
+ thumbnailer->idles = NULL;
+ /* try to connect to D-Bus */
connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
+ /* initialize the proxies */
thunar_thumbnailer_init_thumbnailer_proxy (thumbnailer, connection);
thunar_thumbnailer_init_manager_proxy (thumbnailer, connection);
+ /* check if we have a thumbnailer proxy */
+ if (thumbnailer->thumbnailer_proxy != NULL)
+ {
+ /* we do, set up the hash tables */
+ thumbnailer->request_handle_mapping =
+ g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+ thumbnailer->handle_request_mapping =
+ 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 */
if (connection != NULL)
dbus_g_connection_unref (connection);
}
@@ -181,20 +202,24 @@
thunar_thumbnailer_init_thumbnailer_proxy (ThunarThumbnailer *thumbnailer,
DBusGConnection *connection)
{
+ /* we can't have a proxy without a D-Bus connection */
if (connection == NULL)
{
thumbnailer->thumbnailer_proxy = NULL;
return;
}
+ /* create the thumbnailer proxy shared by all ThunarThumbnailers on demand */
if (thunar_thumbnailer_proxy == NULL)
{
+ /* create the shared thumbnailer proxy */
thunar_thumbnailer_proxy =
dbus_g_proxy_new_for_name (connection,
"org.freedesktop.thumbnails.Thumbnailer",
"/org/freedesktop/thumbnails/Thumbnailer",
"org.freedesktop.thumbnails.Thumbnailer");
+ /* make sure to set it to NULL when the last reference is dropped */
g_object_add_weak_pointer (G_OBJECT (thunar_thumbnailer_proxy),
(gpointer) &thunar_thumbnailer_proxy);
@@ -249,20 +274,24 @@
thunar_thumbnailer_init_manager_proxy (ThunarThumbnailer *thumbnailer,
DBusGConnection *connection)
{
+ /* we cannot have a proxy without a D-Bus connection */
if (connection == NULL)
{
thumbnailer->manager_proxy = NULL;
return;
}
+ /* create the manager proxy shared by all ThunarThumbnailers on demand */
if (thunar_manager_proxy == NULL)
{
+ /* create the shared manager proxy */
thunar_thumbnailer_manager_proxy =
dbus_g_proxy_new_for_name (connection,
"org.freedesktop.thumbnails.Manager",
"/org/freedesktop/thumbnails/Manager",
"org.freedesktop.thumbnails.Manager");
+ /* make sure to set it to NULL when the last reference is dropped */
g_object_add_weak_pointer (G_OBJECT (thunar_thumbnailer_manager_proxy),
(gpointer) &thunar_thumbnailer_manager_proxy);
@@ -279,20 +308,67 @@
static void
thunar_thumbnailer_finalize (GObject *object)
{
- ThunarThumbnailer *thumbnailer = THUNAR_THUMBNAILER (object);
+ ThunarThumbnailerIdle *idle;
+ ThunarThumbnailer *thumbnailer = THUNAR_THUMBNAILER (object);
+ GList *list;
+ GList *lp;
/* acquire the thumbnailer lock */
g_mutex_lock (thumbnailer->lock);
- /* release the thumbnail factory */
+ /* abort all pending idle functions */
+ for (lp = thumbnailer->idles; lp != NULL; lp = lp->next)
+ {
+ idle = lp->data;
+ g_source_remove (idle->id);
+ }
+
+ /* free the idle list */
+ g_list_free (thumbnailer->idles);
+
+ if (thumbnailer->manager_proxy != NULL)
+ {
+ /* disconnect from the manager proxy */
+ g_signal_handlers_disconnect_matched (thumbnailer->manager_proxy,
+ G_SIGNAL_MATCH_DATA, 0, 0,
+ NULL, NULL, thumbnailer);
+
+ /* release the manager proxy */
+ g_object_unref (thumbnailer->manager_proxy);
+ }
+
if (thumbnailer->thumbnailer_proxy != NULL)
{
+ /* cancel all pending D-Bus calls */
+ list = g_hash_table_get_values (thumbnailer->request_call_mapping);
+ for (lp = list; lp != NULL; lp = lp->next)
+ dbus_g_proxy_cancel_call (thumbnailer->thumbnailer_proxy, lp->data);
+ g_list_free (list);
+
+ g_hash_table_unref (thumbnailer->request_call_mapping);
+
+#if 0
+ /* unqueue 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));
+ 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,
G_SIGNAL_MATCH_DATA, 0, 0,
NULL, NULL, thumbnailer);
+
+ /* release the thumbnailer proxy */
g_object_unref (thumbnailer->thumbnailer_proxy);
}
+ /* free the cached MIME types array */
g_strfreev (thumbnailer->supported_types);
/* release the thumbnailer lock */
@@ -306,6 +382,61 @@
+static gboolean
+thunar_thumbnailer_file_is_supported (ThunarThumbnailer *thumbnailer,
+ ThunarFile *file)
+{
+ const gchar *content_type;
+ gboolean supported = FALSE;
+ guint n;
+
+ _thunar_return_val_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer), FALSE);
+ _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
+
+ /* acquire the thumbnailer lock */
+ g_mutex_lock (thumbnailer->lock);
+
+ /* just assume all types are supported if we don't have a manager */
+ if (thumbnailer->manager_proxy == NULL)
+ {
+ /* release the thumbnailer lock */
+ g_mutex_unlock (thumbnailer->lock);
+ return TRUE;
+ }
+
+ /* request the supported types on demand */
+ if (thumbnailer->supported_types == NULL)
+ {
+ /* request the supported types from the manager D-Bus service. We only do
+ * this once, so using a non-async call should be ok */
+ thunar_thumbnailer_manager_proxy_get_supported (thumbnailer->manager_proxy,
+ &thumbnailer->supported_types,
+ NULL);
+ }
+
+ /* check if we have supported types now */
+ if (thumbnailer->supported_types != NULL)
+ {
+ /* determine the content type of the passed file */
+ content_type = thunar_file_get_content_type (file);
+
+ /* go through all the types */
+ for (n = 0; !supported && thumbnailer->supported_types[n] != NULL; ++n)
+ {
+ /* check if the type of the file is a subtype of the supported type */
+ if (g_content_type_is_a (content_type, thumbnailer->supported_types[n]))
+ supported = TRUE;
+ }
+ }
+
+ /* release the thumbnailer lock */
+ g_mutex_unlock (thumbnailer->lock);
+
+ return supported;
+}
+
+
+
static void
thunar_thumbnailer_thumbnailer_error (DBusGProxy *proxy,
guint handle,
@@ -314,15 +445,35 @@
const gchar *message,
ThunarThumbnailer *thumbnailer)
{
+ ThunarThumbnailerIdle *idle;
+ gpointer request;
+
_thunar_return_if_fail (DBUS_IS_G_PROXY (proxy));
- _thunar_return_if_fail (uris != NULL);
- _thunar_return_if_fail (message != NULL);
_thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer));
-
- g_debug ("error");
- g_signal_emit (thumbnailer, thumbnailer_signals[SIGNAL_ERROR], 0,
- handle, uris, code, message);
+ /* look up the request ID 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 = _thunar_slice_new0 (ThunarThumbnailerIdle);
+ idle->type = THUNAR_THUMBNAILER_IDLE_ERROR;
+ idle->thumbnailer = g_object_ref (thumbnailer);
+
+ /* copy the URIs because we need them in the idle function */
+ idle->data.uris = g_strdupv ((gchar **)uris);
+
+ /* remember the idle struct because we might have to remove it in finalize() */
+ thumbnailer->idles = g_list_prepend (thumbnailer->idles, idle);
+
+ /* call the error idle function when we have the time */
+ idle->id = g_idle_add_full (G_PRIORITY_LOW,
+ thunar_thumbnailer_error_idle, idle,
+ thunar_thumbnailer_idle_free);
+ }
}
@@ -332,10 +483,23 @@
guint handle,
ThunarThumbnailer *thumbnailer)
{
+ gpointer request;
+
_thunar_return_if_fail (DBUS_IS_G_PROXY (proxy));
_thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer));
- g_signal_emit (thumbnailer, thumbnailer_signals[SIGNAL_FINISHED], 0, handle);
+ /* look up the request ID 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)
+ {
+ /* 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);
+ }
}
@@ -345,11 +509,30 @@
const gchar **uris,
ThunarThumbnailer *thumbnailer)
{
+ ThunarThumbnailerIdle *idle;
+
_thunar_return_if_fail (DBUS_IS_G_PROXY (proxy));
- _thunar_return_if_fail (uris != NULL);
_thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer));
-
- g_signal_emit (thumbnailer, thumbnailer_signals[SIGNAL_READY], 0, uris);
+
+ /* check if we have any ready URIs */
+ if (uris != NULL)
+ {
+ /* allocate a new idle struct */
+ idle = _thunar_slice_new0 (ThunarThumbnailerIdle);
+ idle->type = THUNAR_THUMBNAILER_IDLE_READY;
+ idle->thumbnailer = g_object_ref (thumbnailer);
+
+ /* copy the URI array because we need it in the idle function */
+ idle->data.uris = g_strdupv ((gchar **)uris);
+
+ /* remember the idle struct because we might have to remove it in finalize() */
+ thumbnailer->idles = g_list_prepend (thumbnailer->idles, idle);
+
+ /* call the ready idle function when we have the time */
+ idle->id = g_idle_add_full (G_PRIORITY_LOW,
+ thunar_thumbnailer_ready_idle, idle,
+ thunar_thumbnailer_idle_free);
+ }
}
@@ -359,14 +542,293 @@
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));
- g_signal_emit (thumbnailer, thumbnailer_signals[SIGNAL_STARTED], 0, handle);
+ /* 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 = _thunar_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,
+ gpointer user_data)
+{
+ ThunarThumbnailerCall *call = user_data;
+ ThunarThumbnailer *thumbnailer = THUNAR_THUMBNAILER (call->thumbnailer);
+ gchar **uris;
+
+ _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy));
+ _thunar_return_if_fail (call != NULL);
+ _thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer));
+
+ g_mutex_lock (thumbnailer->lock);
+
+ if (error != NULL)
+ {
+ /* 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);
+
+ /* the request is "finished", forget about its URIs */
+ g_hash_table_remove (thumbnailer->request_uris_mapping, call->request);
+ }
+ else
+ {
+ /* remember that this request and D-Bus handle belong together */
+ g_hash_table_insert (thumbnailer->request_handle_mapping,
+ call->request, GUINT_TO_POINTER (handle));
+ g_hash_table_insert (thumbnailer->handle_request_mapping,
+ GUINT_TO_POINTER (handle), call->request);
+ }
+
+ /* the queue call is finished, we can forget about its proxy call */
+ g_hash_table_remove (thumbnailer->request_call_mapping, call->request);
+
+ thunar_thumbnailer_call_free (call);
+
+ g_mutex_unlock (thumbnailer->lock);
+}
+
+
+
+static gpointer
+thunar_thumbnailer_queue_async (ThunarThumbnailer *thumbnailer,
+ const gchar **uris,
+ const gchar **mime_hints)
+{
+ ThunarThumbnailerCall *thumbnailer_call;
+ DBusGProxyCall *call;
+ gpointer request;
+ guint request_no;
+
+ _thunar_return_val_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer), 0);
+ _thunar_return_val_if_fail (uris != NULL, 0);
+ _thunar_return_val_if_fail (mime_hints != NULL, 0);
+ _thunar_return_val_if_fail (DBUS_IS_G_PROXY (thumbnailer->thumbnailer_proxy), 0);
+
+ /* compute the next request ID, making sure it's never 0 */
+ request_no = GPOINTER_TO_UINT (thumbnailer->last_request) + 1;
+ request_no = MAX (request_no, 1);
+
+ /* remember the ID for the next request */
+ thumbnailer->last_request = GUINT_TO_POINTER (request_no);
+
+ /* use the new request ID for this request */
+ request = thumbnailer->last_request;
+
+ /* allocate a new call struct for the async D-Bus call */
+ thumbnailer_call = _thunar_slice_new0 (ThunarThumbnailerCall);
+ thumbnailer_call->request = request;
+ thumbnailer_call->thumbnailer = g_object_ref (thumbnailer);
+
+ /* queue thumbnails for the given URIs asynchronously */
+ call = thunar_thumbnailer_proxy_queue_async (thumbnailer->thumbnailer_proxy,
+ uris, mime_hints, 0,
+ thunar_thumbnailer_queue_async_reply,
+ thumbnailer_call);
+
+ /* remember to which request the call struct belongs */
+ g_hash_table_insert (thumbnailer->request_call_mapping, request, call);
+
+ /* return the request ID used for this request */
+ return request;
+}
+
+
+
+static gboolean
+thunar_thumbnailer_error_idle (gpointer user_data)
+{
+ ThunarThumbnailerIdle *idle = user_data;
+ ThunarFile *file;
+ GFile *gfile;
+ guint n;
+
+ _thunar_return_val_if_fail (idle != NULL, FALSE);
+ _thunar_return_val_if_fail (idle->type == THUNAR_THUMBNAILER_IDLE_ERROR, FALSE);
+
+ /* iterate over all failed URIs */
+ for (n = 0; idle->data.uris != NULL && idle->data.uris[n] != NULL; ++n)
+ {
+ /* look up the corresponding ThunarFile from the cache */
+ gfile = g_file_new_for_uri (idle->data.uris[n]);
+ file = thunar_file_cache_lookup (gfile);
+ g_object_unref (gfile);
+
+ /* check if we have a file for this URI in the cache */
+ if (file != NULL)
+ {
+ /* set thumbnail state to none unless the thumbnail has already been created.
+ * 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_NONE);
+ }
+ }
+
+ /* remove the idle struct */
+ g_mutex_lock (idle->thumbnailer->lock);
+ 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 gboolean
+thunar_thumbnailer_ready_idle (gpointer user_data)
+{
+ ThunarThumbnailerIdle *idle = user_data;
+ ThunarFile *file;
+ GFile *gfile;
+ guint n;
+
+ _thunar_return_val_if_fail (idle != NULL, FALSE);
+ _thunar_return_val_if_fail (idle->type == THUNAR_THUMBNAILER_IDLE_READY, FALSE);
+
+ /* iterate over all failed URIs */
+ for (n = 0; idle->data.uris != NULL && idle->data.uris[n] != NULL; ++n)
+ {
+ /* look up the corresponding ThunarFile from the cache */
+ gfile = g_file_new_for_uri (idle->data.uris[n]);
+ file = thunar_file_cache_lookup (gfile);
+ g_object_unref (gfile);
+
+ /* check if we have a file for this URI in the cache */
+ if (file != NULL)
+ {
+ /* set thumbnail state to ready - we now have a thumbnail */
+ thunar_file_set_thumb_state (file, THUNAR_FILE_THUMB_STATE_READY);
+ }
+ }
+
+ /* remove the idle struct */
+ g_mutex_lock (idle->thumbnailer->lock);
+ 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 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)
+{
+ _thunar_return_if_fail (call != NULL);
+
+ /* drop the thumbnailer reference */
+ g_object_unref (call->thumbnailer);
+
+ /* free the struct */
+ _thunar_slice_free (ThunarThumbnailerCall, call);
+}
+
+
+
+static void
+thunar_thumbnailer_idle_free (gpointer data)
+{
+ ThunarThumbnailerIdle *idle = data;
+
+ _thunar_return_if_fail (idle != NULL);
+
+ /* free the URI array if necessary */
+ if (idle->type == THUNAR_THUMBNAILER_IDLE_READY
+ || idle->type == THUNAR_THUMBNAILER_IDLE_ERROR)
+ {
+ g_strfreev (idle->data.uris);
+ }
+
+ /* drop the thumbnailer reference */
+ g_object_unref (idle->thumbnailer);
+
+ /* free the struct */
+ _thunar_slice_free (ThunarThumbnailerIdle, idle);
+}
+
+
+
/**
* thunar_thumbnailer_new:
*
@@ -388,63 +850,39 @@
gboolean
thunar_thumbnailer_queue_file (ThunarThumbnailer *thumbnailer,
- ThunarFile *file,
- guint *handle)
+ ThunarFile *file)
{
- const gchar *mime_hints[2] = { NULL, NULL };
- gboolean supported = FALSE;
- gboolean success = FALSE;
- gchar *uris[2] = { NULL, NULL };
+ GList files;
_thunar_return_val_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer), FALSE);
_thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
- _thunar_return_val_if_fail (handle != NULL, FALSE);
- /* acquire the thumbnailer lock */
- g_mutex_lock (thumbnailer->lock);
+ /* fake a file list */
+ files.data = file;
+ files.next = NULL;
+ files.prev = NULL;
- if (thumbnailer->thumbnailer_proxy != NULL)
- {
- g_mutex_unlock (thumbnailer->lock);
- supported = thunar_thumbnailer_file_is_supported (thumbnailer, file);
- g_mutex_lock (thumbnailer->lock);
-
- if (supported)
- {
- uris[0] = thunar_file_dup_uri (file);
- mime_hints[0] = thunar_file_get_content_type (file);
-
- success =thunar_thumbnailer_proxy_queue (thumbnailer->thumbnailer_proxy,
- (const gchar **)uris,
- mime_hints, 0, handle, NULL);
-
- g_free (uris[0]);
- }
- }
-
- /* release the thumbnailer lock */
- g_mutex_unlock (thumbnailer->lock);
-
- return success;
+ /* queue a thumbnail request for the file */
+ return thunar_thumbnailer_queue_files (thumbnailer, &files);
}
gboolean
thunar_thumbnailer_queue_files (ThunarThumbnailer *thumbnailer,
- GList *files,
- guint *handle)
+ GList *files)
{
const gchar **mime_hints;
gboolean success = FALSE;
+ gpointer request;
GList *lp;
GList *supported_files = NULL;
gchar **uris;
+ guint n_supported = 0;
guint n;
_thunar_return_val_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer), FALSE);
_thunar_return_val_if_fail (files != NULL, FALSE);
- _thunar_return_val_if_fail (handle != NULL, FALSE);
/* acquire the thumbnailer lock */
g_mutex_lock (thumbnailer->lock);
@@ -453,34 +891,50 @@
{
g_mutex_unlock (thumbnailer->lock);
+ /* collect all supported files from the list */
for (lp = g_list_last (files); lp != NULL; lp = lp->prev)
if (thunar_thumbnailer_file_is_supported (thumbnailer, lp->data))
- supported_files = g_list_prepend (supported_files, lp->data);
+ {
+ supported_files = g_list_prepend (supported_files, lp->data);
+ n_supported += 1;
+ }
g_mutex_lock (thumbnailer->lock);
+ /* check if we have any supported files */
if (supported_files != NULL)
{
- uris = g_new0 (gchar *, g_list_length (supported_files) + 1);
- mime_hints = g_new0 (const gchar *, g_list_length (supported_files) + 1);
+ /* allocate arrays for URIs and mime hints */
+ uris = g_new0 (gchar *, n_supported + 1);
+ mime_hints = g_new0 (const gchar *, n_supported + 1);
+ /* fill arrays with data from the supported files */
for (lp = supported_files, n = 0; lp != NULL; lp = lp->next, ++n)
{
uris[n] = thunar_file_dup_uri (lp->data);
mime_hints[n] = thunar_file_get_content_type (lp->data);
}
+ /* NULL-terminate both arrays */
uris[n] = NULL;
mime_hints[n] = NULL;
+ /* queue a thumbnail request for the supported files */
+ request = thunar_thumbnailer_queue_async (thumbnailer,
+ (const gchar **)uris,
+ mime_hints);
+
+ /* remember the URIs for this request */
+ g_hash_table_insert (thumbnailer->request_uris_mapping, request, uris);
+
+ /* free mime hints array */
+ g_free (mime_hints);
+
+ /* free the list of supported files */
g_list_free (supported_files);
-
- success = thunar_thumbnailer_proxy_queue (thumbnailer->thumbnailer_proxy,
- (const gchar **)uris, mime_hints,
- 0, handle, NULL);
- g_strfreev (uris);
- g_free (mime_hints);
+ /* we assume success if we've come so far */
+ success = TRUE;
}
}
@@ -494,63 +948,27 @@
void
thunar_thumbnailer_unqueue (ThunarThumbnailer *thumbnailer,
- guint handle)
+ gpointer request)
{
+ gpointer handle;
+
_thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer));
/* acquire the thumbnailer lock */
g_mutex_lock (thumbnailer->lock);
if (thumbnailer->thumbnailer_proxy != NULL)
- thunar_thumbnailer_proxy_unqueue (thumbnailer->thumbnailer_proxy, handle, NULL);
-
- /* release the thumbnailer lock */
- g_mutex_unlock (thumbnailer->lock);
-}
-
-
-
-gboolean
-thunar_thumbnailer_file_is_supported (ThunarThumbnailer *thumbnailer,
- ThunarFile *file)
-{
- const gchar *content_type;
- gboolean supported = FALSE;
- guint n;
-
- _thunar_return_val_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer), FALSE);
- _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
-
- /* acquire the thumbnailer lock */
- g_mutex_lock (thumbnailer->lock);
-
- if (thumbnailer->manager_proxy == NULL)
{
- /* release the thumbnailer lock */
- g_mutex_unlock (thumbnailer->lock);
- return TRUE;
- }
+ handle = g_hash_table_lookup (thumbnailer->request_handle_mapping, request);
- if (thumbnailer->supported_types == NULL)
- {
- thunar_thumbnailer_manager_proxy_get_supported (thumbnailer->manager_proxy,
- &thumbnailer->supported_types,
- NULL);
- }
+ thunar_thumbnailer_proxy_unqueue (thumbnailer->thumbnailer_proxy,
+ GPOINTER_TO_UINT (handle), NULL);
- if (thumbnailer->supported_types != NULL)
- {
- for (n = 0; !supported && thumbnailer->supported_types[n] != NULL; ++n)
- {
- content_type = thunar_file_get_content_type (file);
-
- if (g_content_type_is_a (content_type, thumbnailer->supported_types[n]))
- supported = TRUE;
- }
+ g_hash_table_remove (thumbnailer->handle_request_mapping, handle);
+ g_hash_table_remove (thumbnailer->request_handle_mapping, request);
+ g_hash_table_remove (thumbnailer->request_uris_mapping, request);
}
/* release the thumbnailer lock */
g_mutex_unlock (thumbnailer->lock);
-
- return supported;
}
Modified: thunar/branches/migration-to-gio/thunar/thunar-thumbnailer.h
===================================================================
--- thunar/branches/migration-to-gio/thunar/thunar-thumbnailer.h 2009-06-14 22:58:11 UTC (rev 30017)
+++ thunar/branches/migration-to-gio/thunar/thunar-thumbnailer.h 2009-06-14 22:58:18 UTC (rev 30018)
@@ -39,15 +39,9 @@
ThunarThumbnailer *thunar_thumbnailer_new (void) G_GNUC_MALLOC;
gboolean thunar_thumbnailer_queue_file (ThunarThumbnailer *generator,
- ThunarFile *file,
- guint *handle);
-gboolean thunar_thumbnailer_queue_files (ThunarThumbnailer *generator,
- GList *files,
- guint *handle);
-void thunar_thumbnailer_unqueue (ThunarThumbnailer *thumbnailer,
- guint handle);
-gboolean thunar_thumbnailer_file_is_supported (ThunarThumbnailer *thumbnailer,
ThunarFile *file);
+gboolean thunar_thumbnailer_queue_files (ThunarThumbnailer *generator,
+ GList *files);
G_END_DECLS;
More information about the Xfce4-commits
mailing list