mirror of
https://gitlab.gnome.org/GNOME/nautilus
synced 2024-09-17 23:01:59 +00:00
Add nautilus_thumbnail_load_image_async and cancel.
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 svn path=/trunk/; revision=13137
This commit is contained in:
parent
59970b14fe
commit
5f0893633d
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
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>
|
2007-09-10 Alexander Larsson <alexl@redhat.com>
|
||||||
|
|
||||||
* libnautilus-private/nautilus-dnd.h:
|
* libnautilus-private/nautilus-dnd.h:
|
||||||
|
|
|
@ -5678,6 +5678,90 @@ handle_vadjustment_changed (GtkAdjustment *adjustment,
|
||||||
nautilus_icon_container_update_visible_icons (container);
|
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
|
void
|
||||||
nautilus_icon_container_update_icon (NautilusIconContainer *container,
|
nautilus_icon_container_update_icon (NautilusIconContainer *container,
|
||||||
NautilusIcon *icon)
|
NautilusIcon *icon)
|
||||||
|
@ -5732,15 +5816,14 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container,
|
||||||
modifier = "accept";
|
modifier = "accept";
|
||||||
}
|
}
|
||||||
|
|
||||||
pixbuf = nautilus_icon_factory_get_pixbuf_for_icon
|
pixbuf = nautilus_icon_factory_get_pixbuf_for_file_with_icon
|
||||||
(icon_name,
|
((NautilusFile *) icon->data,
|
||||||
|
icon_name,
|
||||||
modifier,
|
modifier,
|
||||||
icon_size,
|
icon_size,
|
||||||
&attach_points,
|
&attach_points,
|
||||||
&embedded_text_rect,
|
&embedded_text_rect,
|
||||||
FALSE, TRUE, NULL);
|
FALSE, TRUE, NULL);
|
||||||
|
|
||||||
g_free (icon_name);
|
|
||||||
|
|
||||||
if (embedded_text_rect.width > MINIMUM_EMBEDDED_TEXT_RECT_WIDTH &&
|
if (embedded_text_rect.width > MINIMUM_EMBEDDED_TEXT_RECT_WIDTH &&
|
||||||
embedded_text_rect.height > MINIMUM_EMBEDDED_TEXT_RECT_HEIGHT &&
|
embedded_text_rect.height > MINIMUM_EMBEDDED_TEXT_RECT_HEIGHT &&
|
||||||
|
@ -5794,6 +5877,17 @@ nautilus_icon_container_update_icon (NautilusIconContainer *container,
|
||||||
"additional_text", additional_text,
|
"additional_text", additional_text,
|
||||||
"highlighted_for_drop", icon == details->drop_target,
|
"highlighted_for_drop", icon == details->drop_target,
|
||||||
NULL);
|
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_image (icon->item, pixbuf);
|
||||||
nautilus_icon_canvas_item_set_attach_points (icon->item, &attach_points);
|
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 (editable_text);
|
||||||
g_free (additional_text);
|
g_free (additional_text);
|
||||||
|
|
||||||
|
g_free (icon_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "nautilus-icon-factory.h"
|
#include "nautilus-icon-factory.h"
|
||||||
|
|
||||||
#include "nautilus-default-file-icon.h"
|
#include "nautilus-default-file-icon.h"
|
||||||
|
#include "nautilus-directory-notify.h"
|
||||||
#include "nautilus-file-attributes.h"
|
#include "nautilus-file-attributes.h"
|
||||||
#include "nautilus-file-private.h"
|
#include "nautilus-file-private.h"
|
||||||
#include "nautilus-file-utilities.h"
|
#include "nautilus-file-utilities.h"
|
||||||
|
@ -154,6 +155,7 @@ typedef struct {
|
||||||
CacheIcon *fallback_icon;
|
CacheIcon *fallback_icon;
|
||||||
GHashTable *image_mime_types;
|
GHashTable *image_mime_types;
|
||||||
|
|
||||||
|
GList *async_thumbnail_load_handles;
|
||||||
} NautilusIconFactory;
|
} NautilusIconFactory;
|
||||||
|
|
||||||
#define NAUTILUS_ICON_FACTORY(obj) \
|
#define NAUTILUS_ICON_FACTORY(obj) \
|
||||||
|
@ -347,6 +349,64 @@ load_thumbnail_frame (NautilusIconFactory *factory)
|
||||||
g_free (image_path);
|
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
|
static void
|
||||||
nautilus_icon_factory_instance_init (NautilusIconFactory *factory)
|
nautilus_icon_factory_instance_init (NautilusIconFactory *factory)
|
||||||
{
|
{
|
||||||
|
@ -684,6 +744,14 @@ 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
|
static void
|
||||||
nautilus_icon_factory_finalize (GObject *object)
|
nautilus_icon_factory_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
|
@ -691,6 +759,9 @@ nautilus_icon_factory_finalize (GObject *object)
|
||||||
|
|
||||||
factory = NAUTILUS_ICON_FACTORY (object);
|
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) {
|
if (factory->icon_cache) {
|
||||||
g_hash_table_destroy (factory->icon_cache);
|
g_hash_table_destroy (factory->icon_cache);
|
||||||
factory->icon_cache = NULL;
|
factory->icon_cache = NULL;
|
||||||
|
@ -1300,6 +1371,38 @@ create_normal_cache_icon (const char *icon,
|
||||||
return cache_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.
|
/* Get the icon, handling the caching.
|
||||||
* If @picky is true, then only an unscaled icon is acceptable.
|
* If @picky is true, then only an unscaled icon is acceptable.
|
||||||
|
@ -1316,34 +1419,17 @@ get_icon_from_cache (const char *icon,
|
||||||
{
|
{
|
||||||
NautilusIconFactory *factory;
|
NautilusIconFactory *factory;
|
||||||
GHashTable *hash_table;
|
GHashTable *hash_table;
|
||||||
CacheKey lookup_key;
|
|
||||||
CacheKey *key;
|
CacheKey *key;
|
||||||
CacheIcon *cached_icon;
|
CacheIcon *cached_icon;
|
||||||
gpointer key_in_table, value;
|
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
|
||||||
g_return_val_if_fail (icon != NULL, NULL);
|
g_return_val_if_fail (icon != NULL, NULL);
|
||||||
|
|
||||||
key = NULL;
|
|
||||||
cached_icon = NULL;
|
|
||||||
|
|
||||||
factory = get_icon_factory ();
|
factory = get_icon_factory ();
|
||||||
hash_table = factory->icon_cache;
|
hash_table = factory->icon_cache;
|
||||||
|
|
||||||
/* Check to see if it's already in the table. */
|
/* Check to see if it's already in the table. */
|
||||||
lookup_key.name = (char *)icon;
|
cached_icon = lookup_icon_from_cache (icon, modifier, nominal_size, force_nominal);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure that thumbnails and image-as-itself icons gets
|
/* Make sure that thumbnails and image-as-itself icons gets
|
||||||
reloaded when they change: */
|
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;
|
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
|
/* Convenience cover for nautilus_icon_factory_get_icon_for_file
|
||||||
* and nautilus_icon_factory_get_pixbuf_for_icon.
|
* 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 *
|
GdkPixbuf *
|
||||||
nautilus_icon_factory_get_pixbuf_for_file (NautilusFile *file,
|
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,
|
guint size_in_pixels,
|
||||||
gboolean force_size)
|
gboolean force_size)
|
||||||
{
|
{
|
||||||
char *icon;
|
|
||||||
GdkPixbuf *pixbuf;
|
GdkPixbuf *pixbuf;
|
||||||
|
NautilusIconFactory *factory;
|
||||||
|
char *icon;
|
||||||
|
|
||||||
|
factory = get_icon_factory ();
|
||||||
|
|
||||||
/* Get the pixbuf for this file. */
|
/* Get the pixbuf for this file. */
|
||||||
icon = nautilus_icon_factory_get_icon_for_file (file, FALSE);
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixbuf = nautilus_icon_factory_get_pixbuf_for_icon (icon, modifier,
|
pixbuf = nautilus_icon_factory_get_pixbuf_for_file_with_icon (file,
|
||||||
size_in_pixels,
|
icon, modifier,
|
||||||
NULL, NULL,
|
size_in_pixels,
|
||||||
force_size,
|
NULL, NULL,
|
||||||
TRUE, NULL);
|
force_size,
|
||||||
|
TRUE, NULL);
|
||||||
g_free (icon);
|
g_free (icon);
|
||||||
|
|
||||||
return pixbuf;
|
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,
|
return nautilus_icon_factory_get_pixbuf_for_file (file, modifier,
|
||||||
gtk_icon_size_to_nominal_size (stock_size),
|
gtk_icon_size_to_nominal_size (stock_size),
|
||||||
TRUE); /* force_size */
|
TRUE /* force_size */);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,16 @@ GdkPixbuf *nautilus_icon_factory_get_pixbuf_for_file_with_stock_size (NautilusFi
|
||||||
const char *modifier,
|
const char *modifier,
|
||||||
GtkIconSize stock_size);
|
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
|
/* Convenience routine for getting a pixbuf from an icon name
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -69,6 +69,16 @@ typedef struct {
|
||||||
time_t original_file_mtime;
|
time_t original_file_mtime;
|
||||||
} NautilusThumbnailInfo;
|
} 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.
|
* 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;
|
*args->scale_y_out = (double) gdk_pixbuf_get_height (pixbuf) / args->original_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* routine to load an image from the passed-in path
|
static GdkPixbuf *
|
||||||
*/
|
get_pixbuf_from_data (const unsigned char *buffer,
|
||||||
GdkPixbuf *
|
gsize buflen,
|
||||||
nautilus_thumbnail_load_image (const char *path,
|
const char *path,
|
||||||
guint base_size,
|
guint base_size,
|
||||||
guint nominal_size,
|
guint nominal_size,
|
||||||
gboolean force_nominal,
|
gboolean force_nominal,
|
||||||
double *scale_x_out,
|
double *scale_x_out,
|
||||||
double *scale_y_out)
|
double *scale_y_out)
|
||||||
{
|
{
|
||||||
guchar *buffer;
|
|
||||||
GdkPixbufLoader *loader;
|
GdkPixbufLoader *loader;
|
||||||
GdkPixbuf *pixbuf;
|
GdkPixbuf *pixbuf;
|
||||||
GError *error;
|
|
||||||
gsize buflen;
|
|
||||||
ThumbnailLoadArgs args;
|
ThumbnailLoadArgs args;
|
||||||
|
GError *error;
|
||||||
error = NULL;
|
|
||||||
|
|
||||||
if (thumbnail_icon_size == 0) {
|
if (thumbnail_icon_size == 0) {
|
||||||
eel_preferences_add_auto_integer (NAUTILUS_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE,
|
eel_preferences_add_auto_integer (NAUTILUS_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE,
|
||||||
&thumbnail_icon_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 ();
|
loader = gdk_pixbuf_loader_new ();
|
||||||
g_signal_connect (loader, "size-prepared",
|
g_signal_connect (loader, "size-prepared",
|
||||||
G_CALLBACK (thumbnail_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_x_out = scale_x_out;
|
||||||
args.scale_y_out = scale_y_out;
|
args.scale_y_out = scale_y_out;
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
|
||||||
if (!gdk_pixbuf_loader_write (loader, buffer, buflen, &error)) {
|
if (!gdk_pixbuf_loader_write (loader, buffer, buflen, &error)) {
|
||||||
g_message ("Failed to write %s to thumbnail pixbuf loader: %s", path, error->message);
|
g_message ("Failed to write %s to thumbnail pixbuf loader: %s", path, error->message);
|
||||||
|
|
||||||
gdk_pixbuf_loader_close (loader, NULL);
|
gdk_pixbuf_loader_close (loader, NULL);
|
||||||
g_object_unref (G_OBJECT (loader));
|
g_object_unref (G_OBJECT (loader));
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
g_free (buffer);
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
|
||||||
if (!gdk_pixbuf_loader_close (loader, &error) ||
|
if (!gdk_pixbuf_loader_close (loader, &error) ||
|
||||||
/* Seems we have to check this even if it returned TRUE (#403255) */
|
/* Seems we have to check this even if it returned TRUE (#403255) */
|
||||||
error != NULL) {
|
error != NULL) {
|
||||||
|
@ -396,7 +396,6 @@ nautilus_thumbnail_load_image (const char *path,
|
||||||
|
|
||||||
g_object_unref (G_OBJECT (loader));
|
g_object_unref (G_OBJECT (loader));
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
g_free (buffer);
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -404,11 +403,122 @@ nautilus_thumbnail_load_image (const char *path,
|
||||||
pixbuf = g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader));
|
pixbuf = g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader));
|
||||||
|
|
||||||
g_object_unref (G_OBJECT (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);
|
g_free (buffer);
|
||||||
|
|
||||||
return pixbuf;
|
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
|
void
|
||||||
nautilus_thumbnail_remove_from_queue (const char *file_uri)
|
nautilus_thumbnail_remove_from_queue (const char *file_uri)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,6 +28,15 @@
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
#include <libnautilus-private/nautilus-file.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. */
|
/* Returns NULL if there's no thumbnail yet. */
|
||||||
void nautilus_create_thumbnail (NautilusFile *file);
|
void nautilus_create_thumbnail (NautilusFile *file);
|
||||||
void nautilus_thumbnail_frame_image (GdkPixbuf **pixbuf);
|
void nautilus_thumbnail_frame_image (GdkPixbuf **pixbuf);
|
||||||
|
@ -37,6 +46,14 @@ GdkPixbuf *nautilus_thumbnail_load_image (const char *path,
|
||||||
gboolean force_nominal,
|
gboolean force_nominal,
|
||||||
double *scale_x_out,
|
double *scale_x_out,
|
||||||
double *scale_y_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,
|
void nautilus_update_thumbnail_file_copied (const char *source_file_uri,
|
||||||
const char *destination_file_uri);
|
const char *destination_file_uri);
|
||||||
void nautilus_update_thumbnail_file_renamed (const char *source_file_uri,
|
void nautilus_update_thumbnail_file_renamed (const char *source_file_uri,
|
||||||
|
|
Loading…
Reference in a new issue