summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--libnautilus-private/nautilus-icon-container.c104
-rw-r--r--libnautilus-private/nautilus-icon-factory.c219
-rw-r--r--libnautilus-private/nautilus-icon-factory.h10
-rw-r--r--libnautilus-private/nautilus-thumbnails.c160
-rw-r--r--libnautilus-private/nautilus-thumbnails.h17
6 files changed, 464 insertions, 57 deletions
diff --git a/ChangeLog b/ChangeLog
index c3d66ef0c..0c27c5afc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2007-09-10 Alexander Larsson <alexl@redhat.com>
+ * libnautilus-private/nautilus-thumbnails.[ch]:
+ Add nautilus_thumbnail_load_image_async and cancel.
+
+ * libnautilus-private/nautilus-icon-container.c:
+ * libnautilus-private/nautilus-icon-factory.[ch]:
+ Load thumbnails asynchronously
+
+ Patch from Christian Neumair
+
+2007-09-10 Alexander Larsson <alexl@redhat.com>
+
* libnautilus-private/nautilus-dnd.h:
* libnautilus-private/nautilus-file-dnd.c:
* libnautilus-private/nautilus-icon-dnd.c:
diff --git a/libnautilus-private/nautilus-icon-container.c b/libnautilus-private/nautilus-icon-container.c
index eb160e1bf..1c25745c6 100644
--- a/libnautilus-private/nautilus-icon-container.c
+++ b/libnautilus-private/nautilus-icon-container.c
@@ -5678,6 +5678,90 @@ handle_vadjustment_changed (GtkAdjustment *adjustment,
nautilus_icon_container_update_visible_icons (container);
}
+/*
+ * used to resize ICON_NAME_THUMBNAIL_LOADING to the expected thumbnail size.
+ */
+static void
+sanitize_loading_thumbnail_image_size (NautilusIconContainer *container,
+ const char *mime_type,
+ GdkPixbuf **image,
+ NautilusEmblemAttachPoints *attach_points,
+ GdkRectangle *embedded_text_rect)
+{
+ NautilusIconContainerDetails *details;
+ double pixels_per_unit;
+
+ details = container->details;
+ pixels_per_unit = (double) nautilus_get_icon_size_for_zoom_level (container->details->zoom_level)
+ / NAUTILUS_ICON_SIZE_STANDARD;
+
+ if (gdk_pixbuf_get_width (*image) < NAUTILUS_ICON_SIZE_THUMBNAIL * pixels_per_unit &&
+ gdk_pixbuf_get_height (*image) < NAUTILUS_ICON_SIZE_THUMBNAIL * pixels_per_unit) {
+ /* TODO? this only handles icons smaller than the expected thumbnail size ATM.
+ * Should not be a common problem, though */
+ GdkPixbuf *new_image;
+ double x_size;
+ double y_size;
+ double x_offset;
+ double y_offset;
+ int i;
+
+ if (g_str_has_prefix (mime_type, "video/")) {
+ /* assume 4:3 aspect ratio for videos i.e. we'll always occupy the full width. */
+ x_size = NAUTILUS_ICON_SIZE_THUMBNAIL * pixels_per_unit;
+ y_size = 3./4 * x_size;
+ } else {
+ /* scale up to the max. thumbnail size.
+ * This is correct at least in one dimension, and prevents the icons from jumping
+ * around as the thumbnail is created, if it is tall for text below icon, and if it
+ * is wide for text beside icon.
+ */
+ x_size = NAUTILUS_ICON_SIZE_THUMBNAIL * pixels_per_unit;
+ y_size = NAUTILUS_ICON_SIZE_THUMBNAIL * pixels_per_unit;
+ }
+
+ /* maybe the estimated size was smaller than the input pixbuf, so size the surrounding
+ * image up. This only seems to be relevant in the 4:3 case, for y_size.
+ */
+ x_size = MAX (x_size, gdk_pixbuf_get_width (*image));
+ y_size = MAX (y_size, gdk_pixbuf_get_height (*image));
+
+ x_offset = x_size - gdk_pixbuf_get_width (*image);
+ y_offset = y_size - gdk_pixbuf_get_height (*image);
+
+ /* center wrt "minor" dimension, i.e. horizontally for text below
+ * and vertically for text besides icon */
+ if (details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE)
+ y_offset /= 2;
+ else
+ x_offset /= 2;
+
+ new_image = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE,
+ gdk_pixbuf_get_bits_per_sample (*image),
+ x_size, y_size);
+
+ gdk_pixbuf_fill (new_image, 0x00000000);
+ gdk_pixbuf_copy_area (*image,
+ 0, 0,
+ gdk_pixbuf_get_width (*image),
+ gdk_pixbuf_get_height (*image),
+ new_image,
+ x_offset, y_offset);
+
+ g_object_unref (*image);
+ *image = new_image;
+
+ for (i = 0; i < attach_points->num_points; i++) {
+ attach_points->points[i].x += x_offset;
+ attach_points->points[i].y += y_offset;
+ }
+
+ embedded_text_rect->x += x_offset;
+ embedded_text_rect->y += y_offset;
+ }
+}
+
+
void
nautilus_icon_container_update_icon (NautilusIconContainer *container,
NautilusIcon *icon)
@@ -5732,15 +5816,14 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container,
modifier = "accept";
}
- pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
- (icon_name,
+ pixbuf = nautilus_icon_factory_get_pixbuf_for_file_with_icon
+ ((NautilusFile *) icon->data,
+ icon_name,
modifier,
icon_size,
&attach_points,
&embedded_text_rect,
FALSE, TRUE, NULL);
-
- g_free (icon_name);
if (embedded_text_rect.width > MINIMUM_EMBEDDED_TEXT_RECT_WIDTH &&
embedded_text_rect.height > MINIMUM_EMBEDDED_TEXT_RECT_HEIGHT &&
@@ -5794,6 +5877,17 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container,
"additional_text", additional_text,
"highlighted_for_drop", icon == details->drop_target,
NULL);
+
+ if (nautilus_file_is_thumbnailing ((NautilusFile *) icon->data)) {
+ char* mime_type;
+ mime_type = nautilus_file_get_mime_type ((NautilusFile *)icon->data);
+ sanitize_loading_thumbnail_image_size (container,
+ mime_type,
+ &pixbuf,
+ &attach_points,
+ &embedded_text_rect);
+ g_free (mime_type);
+ }
nautilus_icon_canvas_item_set_image (icon->item, pixbuf);
nautilus_icon_canvas_item_set_attach_points (icon->item, &attach_points);
@@ -5807,6 +5901,8 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container,
g_free (editable_text);
g_free (additional_text);
+
+ g_free (icon_name);
}
static gboolean
diff --git a/libnautilus-private/nautilus-icon-factory.c b/libnautilus-private/nautilus-icon-factory.c
index df071b2cf..4f30bbe1a 100644
--- a/libnautilus-private/nautilus-icon-factory.c
+++ b/libnautilus-private/nautilus-icon-factory.c
@@ -29,6 +29,7 @@
#include "nautilus-icon-factory.h"
#include "nautilus-default-file-icon.h"
+#include "nautilus-directory-notify.h"
#include "nautilus-file-attributes.h"
#include "nautilus-file-private.h"
#include "nautilus-file-utilities.h"
@@ -154,6 +155,7 @@ typedef struct {
CacheIcon *fallback_icon;
GHashTable *image_mime_types;
+ GList *async_thumbnail_load_handles;
} NautilusIconFactory;
#define NAUTILUS_ICON_FACTORY(obj) \
@@ -347,6 +349,64 @@ load_thumbnail_frame (NautilusIconFactory *factory)
g_free (image_path);
}
+typedef struct {
+ NautilusFile *file;
+ char *modifier;
+ guint nominal_size;
+ gboolean force_nominal;
+} AsnycThumbnailLoadFuncData;
+
+static void
+async_thumbnail_load_func (NautilusThumbnailAsyncLoadHandle *handle,
+ const char *path,
+ GdkPixbuf *pixbuf,
+ double scale_x,
+ double scale_y,
+ gpointer user_data)
+{
+ NautilusIconFactory *factory;
+ GHashTable *hash_table;
+ CacheKey *key;
+ CacheIcon *cached_icon;
+ struct stat statbuf;
+ AsnycThumbnailLoadFuncData *data = user_data;
+
+ factory = get_icon_factory ();
+ hash_table = factory->icon_cache;
+
+ nautilus_file_set_is_thumbnailing (data->file, FALSE);
+ factory->async_thumbnail_load_handles =
+ g_list_remove (factory->async_thumbnail_load_handles, handle);
+
+ if (stat (path, &statbuf) != 0 ||
+ !S_ISREG (statbuf.st_mode)) {
+ g_message ("NautilusIconFactory: Failed to determine mtime for %s. Aborting thumbnailing request.", path);
+ goto out;
+ }
+
+ cached_icon = cache_icon_new (pixbuf, NULL, scale_x, scale_y);
+ cached_icon->mtime = statbuf.st_mtime;
+
+ if (cached_icon != NULL) {
+ key = g_new (CacheKey, 1);
+ key->name = g_strdup (path);
+ key->modifier = g_strdup (data->modifier);
+ key->nominal_size = data->nominal_size;
+ key->force_nominal = data->force_nominal;
+
+ g_hash_table_insert (hash_table, key, cached_icon);
+
+ nautilus_file_changed (data->file);
+ }
+
+out:
+ nautilus_file_unref (data->file);
+ g_free (data->modifier);
+ g_free (data);
+}
+
+
+
static void
nautilus_icon_factory_instance_init (NautilusIconFactory *factory)
{
@@ -685,12 +745,23 @@ nautilus_icon_factory_clear (void)
}
static void
+cancel_thumbnail_read_foreach (gpointer data,
+ gpointer user_data)
+{
+ NautilusThumbnailAsyncLoadHandle *handle = data;
+ nautilus_thumbnail_load_image_cancel (handle);
+}
+
+static void
nautilus_icon_factory_finalize (GObject *object)
{
NautilusIconFactory *factory;
factory = NAUTILUS_ICON_FACTORY (object);
+ g_list_foreach (factory->async_thumbnail_load_handles, cancel_thumbnail_read_foreach, NULL);
+ g_list_free (factory->async_thumbnail_load_handles);
+
if (factory->icon_cache) {
g_hash_table_destroy (factory->icon_cache);
factory->icon_cache = NULL;
@@ -1300,6 +1371,38 @@ create_normal_cache_icon (const char *icon,
return cache_icon;
}
+static CacheIcon *
+lookup_icon_from_cache (const char *icon,
+ const char *modifier,
+ guint nominal_size,
+ gboolean force_nominal)
+{
+ NautilusIconFactory *factory;
+ GHashTable *hash_table;
+ CacheKey lookup_key, *key;
+ CacheIcon *value;
+
+ lookup_key.name = (char *)icon;
+ lookup_key.modifier = (char *)modifier;
+ lookup_key.nominal_size = nominal_size;
+ lookup_key.force_nominal = force_nominal;
+
+ factory = get_icon_factory ();
+ hash_table = factory->icon_cache;
+
+ if (g_hash_table_lookup_extended (hash_table, &lookup_key,
+ (gpointer *) &key, (gpointer *) &value)) {
+ /* Found it in the table. */
+ g_assert (key != NULL);
+ g_assert (value != NULL);
+ } else {
+ key = NULL;
+ value = NULL;
+ }
+
+ return value;
+}
+
/* Get the icon, handling the caching.
* If @picky is true, then only an unscaled icon is acceptable.
@@ -1316,34 +1419,17 @@ get_icon_from_cache (const char *icon,
{
NautilusIconFactory *factory;
GHashTable *hash_table;
- CacheKey lookup_key;
CacheKey *key;
CacheIcon *cached_icon;
- gpointer key_in_table, value;
struct stat statbuf;
g_return_val_if_fail (icon != NULL, NULL);
-
- key = NULL;
- cached_icon = NULL;
factory = get_icon_factory ();
hash_table = factory->icon_cache;
/* Check to see if it's already in the table. */
- lookup_key.name = (char *)icon;
- lookup_key.modifier = (char *)modifier;
- lookup_key.nominal_size = nominal_size;
- lookup_key.force_nominal = force_nominal;
-
- if (g_hash_table_lookup_extended (hash_table, &lookup_key,
- &key_in_table, &value)) {
- /* Found it in the table. */
- g_assert (key_in_table != NULL);
- g_assert (value != NULL);
- key = key_in_table;
- cached_icon = value;
- }
+ cached_icon = lookup_icon_from_cache (icon, modifier, nominal_size, force_nominal);
/* Make sure that thumbnails and image-as-itself icons gets
reloaded when they change: */
@@ -1547,10 +1633,85 @@ nautilus_get_relative_icon_size_for_zoom_level (NautilusZoomLevel zoom_level)
return (float)nautilus_get_icon_size_for_zoom_level (zoom_level) / NAUTILUS_ICON_SIZE_STANDARD;
}
-
-
/* Convenience cover for nautilus_icon_factory_get_icon_for_file
* and nautilus_icon_factory_get_pixbuf_for_icon.
+ *
+ * If a file has an associated thumbnail, the thumb is loaded asynchronously,
+ * a loading thumbnail image is returned
+ * and the file will receive a "changed" event once the thumbnail has been loaded.
+ *
+ * The "file" parameter is only used for thumbnailing,
+ * for the file change notification once the actual thumbnail
+ * has been loaded.
+ */
+GdkPixbuf *
+nautilus_icon_factory_get_pixbuf_for_file_with_icon (NautilusFile *file,
+ const char *icon,
+ const char *modifier,
+ guint size_in_pixels,
+ NautilusEmblemAttachPoints *attach_points,
+ GdkRectangle *embedded_text_rect,
+ gboolean force_size,
+ gboolean wants_default,
+ char **display_name)
+{
+ GdkPixbuf *pixbuf;
+ NautilusIconFactory *factory;
+ gboolean is_thumbnail;
+
+ factory = get_icon_factory ();
+
+ is_thumbnail = strstr (icon, "/.thumbnails/") != NULL;
+
+ if (is_thumbnail &&
+ !lookup_icon_from_cache (icon, modifier, size_in_pixels, force_size)) {
+ AsnycThumbnailLoadFuncData *data;
+
+ /* Asynchronous thumbnail loading.
+ *
+ * This heavily improves performance for folders containing lots of
+ * previously thumbnailed files.
+ *
+ * Note: We do not pass the additional thumbnail parameters (attach points etc.)
+ * to the thread as we don't need them for the cache. The API user may herself
+ * re-request the loaded thumbnail with the correct parameters, which will be set
+ * accordingly in nautilus_icon_factory_get_pixbuf_for_icon() on cache hit
+ * once it is filled.
+ */
+
+ data = g_new (AsnycThumbnailLoadFuncData, 1);
+ data->file = nautilus_file_ref (file);
+ data->modifier = g_strdup (modifier);
+ data->nominal_size = size_in_pixels;
+ data->force_nominal = force_size;
+
+ nautilus_file_set_is_thumbnailing (file, TRUE);
+
+ factory->async_thumbnail_load_handles = g_list_prepend (
+ factory->async_thumbnail_load_handles,
+ nautilus_thumbnail_load_image_async (icon,
+ 0, /* base_size */
+ size_in_pixels,
+ force_size,
+ async_thumbnail_load_func,
+ data));
+
+ icon = ICON_NAME_THUMBNAIL_LOADING;
+ }
+
+
+ pixbuf = nautilus_icon_factory_get_pixbuf_for_icon (icon,
+ modifier, size_in_pixels,
+ attach_points, embedded_text_rect,
+ force_size,
+ wants_default, display_name);
+
+ return pixbuf;
+}
+
+/*
+ * like nautilus_icon_factory_get_pixbuf_for_file_with_icon() but does the icon lookup itself,
+ * doesn't allow emblem and text rect fetching.
*/
GdkPixbuf *
nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
@@ -1558,9 +1719,11 @@ nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
guint size_in_pixels,
gboolean force_size)
{
- char *icon;
GdkPixbuf *pixbuf;
+ NautilusIconFactory *factory;
+ char *icon;
+ factory = get_icon_factory ();
/* Get the pixbuf for this file. */
icon = nautilus_icon_factory_get_icon_for_file (file, FALSE);
@@ -1568,12 +1731,12 @@ nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
return NULL;
}
- pixbuf = nautilus_icon_factory_get_pixbuf_for_icon (icon, modifier,
- size_in_pixels,
- NULL, NULL,
- force_size,
- TRUE, NULL);
-
+ pixbuf = nautilus_icon_factory_get_pixbuf_for_file_with_icon (file,
+ icon, modifier,
+ size_in_pixels,
+ NULL, NULL,
+ force_size,
+ TRUE, NULL);
g_free (icon);
return pixbuf;
@@ -1586,7 +1749,7 @@ nautilus_icon_factory_get_pixbuf_for_file_with_stock_size (NautilusFile *file,
{
return nautilus_icon_factory_get_pixbuf_for_file (file, modifier,
gtk_icon_size_to_nominal_size (stock_size),
- TRUE); /* force_size */
+ TRUE /* force_size */);
}
diff --git a/libnautilus-private/nautilus-icon-factory.h b/libnautilus-private/nautilus-icon-factory.h
index c56d36744..673172125 100644
--- a/libnautilus-private/nautilus-icon-factory.h
+++ b/libnautilus-private/nautilus-icon-factory.h
@@ -151,6 +151,16 @@ GdkPixbuf *nautilus_icon_factory_get_pixbuf_for_file_with_stock_size (NautilusFi
const char *modifier,
GtkIconSize stock_size);
+GdkPixbuf * nautilus_icon_factory_get_pixbuf_for_file_with_icon (NautilusFile *file,
+ const char *icon,
+ const char *modifier,
+ guint size_in_pixels,
+ NautilusEmblemAttachPoints *attach_points,
+ GdkRectangle *embedded_text_rect,
+ gboolean force_size,
+ gboolean wants_default,
+ char **display_name);
+
/* Convenience routine for getting a pixbuf from an icon name
*/
diff --git a/libnautilus-private/nautilus-thumbnails.c b/libnautilus-private/nautilus-thumbnails.c
index 380391544..91f79718f 100644
--- a/libnautilus-private/nautilus-thumbnails.c
+++ b/libnautilus-private/nautilus-thumbnails.c
@@ -69,6 +69,16 @@ typedef struct {
time_t original_file_mtime;
} NautilusThumbnailInfo;
+struct NautilusThumbnailAsyncLoadHandle {
+ EelReadFileHandle *eel_read_handle;
+ char *file_path;
+ guint base_size;
+ guint nominal_size;
+ gboolean force_nominal;
+ NautilusThumbnailAsyncLoadFunc load_func;
+ gpointer load_func_user_data;
+};
+
/*
* Thumbnail thread state.
@@ -330,39 +340,26 @@ thumbnail_loader_area_prepared (GdkPixbufLoader *loader,
*args->scale_y_out = (double) gdk_pixbuf_get_height (pixbuf) / args->original_height;
}
-/* routine to load an image from the passed-in path
- */
-GdkPixbuf *
-nautilus_thumbnail_load_image (const char *path,
- guint base_size,
- guint nominal_size,
- gboolean force_nominal,
- double *scale_x_out,
- double *scale_y_out)
+static GdkPixbuf *
+get_pixbuf_from_data (const unsigned char *buffer,
+ gsize buflen,
+ const char *path,
+ guint base_size,
+ guint nominal_size,
+ gboolean force_nominal,
+ double *scale_x_out,
+ double *scale_y_out)
{
- guchar *buffer;
GdkPixbufLoader *loader;
GdkPixbuf *pixbuf;
- GError *error;
- gsize buflen;
ThumbnailLoadArgs args;
-
- error = NULL;
+ GError *error;
if (thumbnail_icon_size == 0) {
eel_preferences_add_auto_integer (NAUTILUS_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE,
&thumbnail_icon_size);
}
-
- if (!g_file_get_contents (path, (gchar **) &buffer, &buflen, &error)) {
- g_message ("Failed to load %s into memory: %s", path, error->message);
-
- g_error_free (error);
-
- return NULL;
- }
-
loader = gdk_pixbuf_loader_new ();
g_signal_connect (loader, "size-prepared",
G_CALLBACK (thumbnail_loader_size_prepared),
@@ -378,17 +375,20 @@ nautilus_thumbnail_load_image (const char *path,
args.scale_x_out = scale_x_out;
args.scale_y_out = scale_y_out;
+ error = NULL;
+
if (!gdk_pixbuf_loader_write (loader, buffer, buflen, &error)) {
g_message ("Failed to write %s to thumbnail pixbuf loader: %s", path, error->message);
gdk_pixbuf_loader_close (loader, NULL);
g_object_unref (G_OBJECT (loader));
g_error_free (error);
- g_free (buffer);
return NULL;
}
+ error = NULL;
+
if (!gdk_pixbuf_loader_close (loader, &error) ||
/* Seems we have to check this even if it returned TRUE (#403255) */
error != NULL) {
@@ -396,7 +396,6 @@ nautilus_thumbnail_load_image (const char *path,
g_object_unref (G_OBJECT (loader));
g_error_free (error);
- g_free (buffer);
return NULL;
}
@@ -404,11 +403,122 @@ nautilus_thumbnail_load_image (const char *path,
pixbuf = g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader));
g_object_unref (G_OBJECT (loader));
+
+ return pixbuf;
+}
+
+
+/* routine to load an image from the passed-in path
+ */
+GdkPixbuf *
+nautilus_thumbnail_load_image (const char *path,
+ guint base_size,
+ guint nominal_size,
+ gboolean force_nominal,
+ double *scale_x_out,
+ double *scale_y_out)
+{
+ GdkPixbuf *pixbuf;
+ guchar *buffer;
+ gsize buflen;
+ GError *error;
+
+ error = NULL;
+
+ if (!g_file_get_contents (path, (gchar **) &buffer, &buflen, &error)) {
+ g_message ("Failed to load %s into memory: %s", path, error->message);
+
+ g_error_free (error);
+
+ return NULL;
+ }
+
+ pixbuf = get_pixbuf_from_data (buffer, buflen, path,
+ base_size, nominal_size, force_nominal,
+ scale_x_out, scale_y_out);
+
g_free (buffer);
return pixbuf;
}
+static void
+async_thumbnail_read_image (GnomeVFSResult result,
+ GnomeVFSFileSize file_size,
+ char *file_contents,
+ gpointer callback_data)
+{
+ GdkPixbuf *pixbuf;
+ double scale_x, scale_y;
+
+ NautilusThumbnailAsyncLoadHandle *handle = callback_data;
+
+ pixbuf = NULL;
+ scale_x = scale_y = 1.0;
+
+ if (result == GNOME_VFS_OK) {
+ pixbuf = get_pixbuf_from_data (file_contents, file_size,
+ handle->file_path,
+ handle->base_size,
+ handle->nominal_size,
+ handle->force_nominal,
+ &scale_x, &scale_y);
+ }
+
+ handle->load_func (handle,
+ handle->file_path,
+ pixbuf, scale_x, scale_y,
+ handle->load_func_user_data);
+
+ gdk_pixbuf_unref (pixbuf);
+
+ g_free (handle->file_path);
+ g_free (handle);
+}
+
+NautilusThumbnailAsyncLoadHandle *
+nautilus_thumbnail_load_image_async (const char *path,
+ guint base_size,
+ guint nominal_size,
+ gboolean force_nominal,
+ NautilusThumbnailAsyncLoadFunc load_func,
+ gpointer load_func_user_data)
+{
+ NautilusThumbnailAsyncLoadHandle *handle;
+ char *uri;
+
+ uri = gnome_vfs_get_uri_from_local_path (path);
+ if (uri == NULL) {
+ return NULL;
+ }
+
+ handle = g_new (NautilusThumbnailAsyncLoadHandle, 1);
+ handle->eel_read_handle =
+ eel_read_entire_file_async (uri, GNOME_VFS_PRIORITY_DEFAULT,
+ (EelReadFileCallback) async_thumbnail_read_image,
+ handle);
+ handle->file_path = g_strdup (path);
+ handle->base_size = base_size;
+ handle->nominal_size = nominal_size;
+ handle->force_nominal = force_nominal;
+ handle->load_func = load_func;
+ handle->load_func_user_data = load_func_user_data;
+
+ g_free (uri);
+
+ return handle;
+}
+
+void
+nautilus_thumbnail_load_image_cancel (NautilusThumbnailAsyncLoadHandle *handle)
+{
+ g_assert (handle != NULL);
+
+ eel_read_file_cancel (handle->eel_read_handle);
+ g_free (handle->file_path);
+ g_free (handle);
+}
+
void
nautilus_thumbnail_remove_from_queue (const char *file_uri)
{
diff --git a/libnautilus-private/nautilus-thumbnails.h b/libnautilus-private/nautilus-thumbnails.h
index c62e3bd76..6e463b59e 100644
--- a/libnautilus-private/nautilus-thumbnails.h
+++ b/libnautilus-private/nautilus-thumbnails.h
@@ -28,6 +28,15 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <libnautilus-private/nautilus-file.h>
+typedef struct NautilusThumbnailAsyncLoadHandle NautilusThumbnailAsyncLoadHandle;
+
+typedef void (* NautilusThumbnailAsyncLoadFunc) (NautilusThumbnailAsyncLoadHandle *handle,
+ const char *path,
+ GdkPixbuf *pixbuf,
+ double scale_x,
+ double scale_y,
+ gpointer user_data);
+
/* Returns NULL if there's no thumbnail yet. */
void nautilus_create_thumbnail (NautilusFile *file);
void nautilus_thumbnail_frame_image (GdkPixbuf **pixbuf);
@@ -37,6 +46,14 @@ GdkPixbuf *nautilus_thumbnail_load_image (const char *path,
gboolean force_nominal,
double *scale_x_out,
double *scale_y_out);
+NautilusThumbnailAsyncLoadHandle *
+ nautilus_thumbnail_load_image_async (const char *path,
+ guint base_size,
+ guint nominal_size,
+ gboolean force_nominal,
+ NautilusThumbnailAsyncLoadFunc load_func,
+ gpointer load_func_user_data);
+void nautilus_thumbnail_load_image_cancel (NautilusThumbnailAsyncLoadHandle *handle);
void nautilus_update_thumbnail_file_copied (const char *source_file_uri,
const char *destination_file_uri);
void nautilus_update_thumbnail_file_renamed (const char *source_file_uri,