[gthumb/ext: 29/79] Fixed many issues related to the thumbnailer
- From: Paolo Bacchilega <paobac src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gthumb/ext: 29/79] Fixed many issues related to the thumbnailer
- Date: Sun, 2 Aug 2009 20:26:20 +0000 (UTC)
commit 95f7873201cae50c1510e4ed3d2b7cbed2c32342
Author: Paolo Bacchilega <paobac src gnome org>
Date: Mon Jun 29 00:39:45 2009 +0200
Fixed many issues related to the thumbnailer
Force the thumbnailer to stop when closing the window or
changing directory; Kill the thumbnailer if it lasts more then
3 seconds; Update the thumbnail icons every 250 msec instead of
every 20 thumbnails.
gthumb/gnome-desktop-thumbnail.c | 204 +++++++++++++++++++++++++-------------
gthumb/gnome-desktop-thumbnail.h | 10 ++-
gthumb/gth-file-list.c | 96 +++++++++++++++++-
gthumb/gth-file-store.c | 7 +-
gthumb/gth-main-default-types.c | 26 +++++-
gthumb/gth-main.c | 12 +--
gthumb/gth-thumb-loader.c | 171 +++++++++++++++++++++++++-------
7 files changed, 407 insertions(+), 119 deletions(-)
---
diff --git a/gthumb/gnome-desktop-thumbnail.c b/gthumb/gnome-desktop-thumbnail.c
index 0927f91..ca81ad5 100644
--- a/gthumb/gnome-desktop-thumbnail.c
+++ b/gthumb/gnome-desktop-thumbnail.c
@@ -77,21 +77,21 @@ typedef struct {
#define LOAD_BUFFER_SIZE 4096
static void
-size_prepared_cb (GdkPixbufLoader *loader,
+size_prepared_cb (GdkPixbufLoader *loader,
int width,
int height,
gpointer data)
{
SizePrepareContext *info = data;
-
+
g_return_if_fail (width > 0 && height > 0);
-
+
info->input_width = width;
info->input_height = height;
-
+
if (width < info->width && height < info->height) return;
-
- if (info->preserve_aspect_ratio &&
+
+ if (info->preserve_aspect_ratio &&
(info->width > 0 || info->height > 0)) {
if (info->width < 0)
{
@@ -117,7 +117,7 @@ size_prepared_cb (GdkPixbufLoader *loader,
if (info->height > 0)
height = info->height;
}
-
+
gdk_pixbuf_loader_set_size (loader, width, height);
}
@@ -131,7 +131,7 @@ _gdk_pixbuf_new_from_uri_at_scale (const char *uri,
char buffer[LOAD_BUFFER_SIZE];
gsize bytes_read;
GdkPixbufLoader *loader;
- GdkPixbuf *pixbuf;
+ GdkPixbuf *pixbuf;
GdkPixbufAnimation *animation;
GdkPixbufAnimationIter *iter;
gboolean has_frame;
@@ -154,7 +154,7 @@ _gdk_pixbuf_new_from_uri_at_scale (const char *uri,
info.width = width;
info.height = height;
info.input_width = info.input_height = 0;
- info.preserve_aspect_ratio = preserve_aspect_ratio;
+ info.preserve_aspect_ratio = preserve_aspect_ratio;
g_signal_connect (loader, "size-prepared", G_CALLBACK (size_prepared_cb), &info);
}
@@ -227,11 +227,11 @@ gnome_desktop_thumbnail_factory_finalize (GObject *object)
GnomeDesktopThumbnailFactory *factory;
GnomeDesktopThumbnailFactoryPrivate *priv;
GConfClient *client;
-
+
factory = GNOME_DESKTOP_THUMBNAIL_FACTORY (object);
priv = factory->priv;
-
+
g_free (priv->application);
priv->application = NULL;
@@ -246,7 +246,7 @@ gnome_desktop_thumbnail_factory_finalize (GObject *object)
priv->thumbnailers_notify = 0;
g_object_unref (client);
}
-
+
if (priv->scripts_hash)
{
g_hash_table_destroy (priv->scripts_hash);
@@ -258,10 +258,10 @@ gnome_desktop_thumbnail_factory_finalize (GObject *object)
g_mutex_free (priv->lock);
priv->lock = NULL;
}
-
+
g_free (priv);
factory->priv = NULL;
-
+
if (G_OBJECT_CLASS (parent_class)->finalize)
(* G_OBJECT_CLASS (parent_class)->finalize) (object);
}
@@ -284,12 +284,12 @@ read_scripts (void)
g_object_unref (G_OBJECT (client));
return NULL;
}
-
+
scripts_hash = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free, g_free);
-
+
subdirs = gconf_client_all_dirs (client, "/desktop/gnome/thumbnailers", NULL);
for (l = subdirs; l != NULL; l = l->next)
@@ -310,7 +310,7 @@ read_scripts (void)
if (mimetype != NULL)
{
mimetype++; /* skip past slash */
-
+
/* Convert '@' to slash in mimetype */
escape = strchr (mimetype, '@');
if (escape != NULL)
@@ -330,14 +330,14 @@ read_scripts (void)
}
}
g_free (enable);
-
+
g_free (subdir);
}
-
+
g_slist_free(subdirs);
g_object_unref (G_OBJECT (client));
-
+
return scripts_hash;
}
@@ -355,9 +355,9 @@ gnome_desktop_thumbnail_factory_reread_scripts (GnomeDesktopThumbnailFactory *fa
if (priv->scripts_hash != NULL)
g_hash_table_destroy (priv->scripts_hash);
-
+
priv->scripts_hash = scripts_hash;
-
+
g_mutex_unlock (priv->lock);
}
@@ -372,7 +372,7 @@ reread_idle_callback (gpointer user_data)
g_mutex_lock (priv->lock);
priv->reread_scheduled = 0;
g_mutex_unlock (priv->lock);
-
+
return FALSE;
}
@@ -392,7 +392,7 @@ schedule_reread (GConfClient* client,
priv->reread_scheduled = g_idle_add (reread_idle_callback,
factory);
}
-
+
g_mutex_unlock (priv->lock);
}
@@ -402,16 +402,16 @@ gnome_desktop_thumbnail_factory_init (GnomeDesktopThumbnailFactory *factory)
{
GConfClient *client;
GnomeDesktopThumbnailFactoryPrivate *priv;
-
+
factory->priv = g_new0 (GnomeDesktopThumbnailFactoryPrivate, 1);
priv = factory->priv;
priv->size = GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL;
priv->application = g_strdup ("gnome-thumbnail-factory");
-
+
priv->scripts_hash = NULL;
-
+
priv->lock = g_mutex_new ();
gnome_desktop_thumbnail_factory_reread_scripts (factory);
@@ -434,7 +434,7 @@ gnome_desktop_thumbnail_factory_class_init (GnomeDesktopThumbnailFactoryClass *c
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (class);
-
+
gobject_class->finalize = gnome_desktop_thumbnail_factory_finalize;
}
@@ -445,7 +445,7 @@ gnome_desktop_thumbnail_factory_class_init (GnomeDesktopThumbnailFactoryClass *c
* Creates a new #GnomeDesktopThumbnailFactory.
*
* This function must be called on the main thread.
- *
+ *
* Return value: a new #GnomeDesktopThumbnailFactory
*
* Since: 2.2
@@ -454,11 +454,11 @@ GnomeDesktopThumbnailFactory *
gnome_desktop_thumbnail_factory_new (GnomeDesktopThumbnailSize size)
{
GnomeDesktopThumbnailFactory *factory;
-
+
factory = g_object_new (GNOME_DESKTOP_TYPE_THUMBNAIL_FACTORY, NULL);
-
+
factory->priv->size = size;
-
+
return factory;
}
@@ -500,7 +500,7 @@ gnome_desktop_thumbnail_factory_lookup (GnomeDesktopThumbnailFactory *factory,
g_assert (digest_len == 16);
file = g_strconcat (g_checksum_get_string (checksum), ".png", NULL);
-
+
path = g_build_filename (g_get_home_dir (),
".thumbnails",
(priv->size == GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL)?"normal":"large",
@@ -591,23 +591,23 @@ mimetype_supported_by_gdk_pixbuf (const char *mime_type)
if (!formats_hash) {
GSList *formats, *list;
-
+
formats_hash = g_hash_table_new (g_str_hash, g_str_equal);
formats = gdk_pixbuf_get_formats ();
list = formats;
-
+
while (list) {
GdkPixbufFormat *format = list->data;
gchar **mime_types;
-
+
mime_types = gdk_pixbuf_format_get_mime_types (format);
for (i = 0; mime_types[i] != NULL; i++)
g_hash_table_insert (formats_hash,
(gpointer) g_strdup (mime_types[i]),
- GUINT_TO_POINTER (1));
-
+ GUINT_TO_POINTER (1));
+
g_strfreev (mime_types);
list = list->next;
}
@@ -647,7 +647,7 @@ gnome_desktop_thumbnail_factory_can_thumbnail (GnomeDesktopThumbnailFactory *fac
strncmp (uri, "file:/", 6) == 0 &&
strstr (uri, "/.thumbnails/") != NULL)
return FALSE;
-
+
if (mime_type != NULL &&
(mimetype_supported_by_gdk_pixbuf (mime_type) ||
(factory->priv->scripts_hash != NULL &&
@@ -657,13 +657,13 @@ gnome_desktop_thumbnail_factory_can_thumbnail (GnomeDesktopThumbnailFactory *fac
uri,
mtime);
}
-
+
return FALSE;
}
static char *
expand_thumbnailing_script (const char *script,
- const int size,
+ const int size,
const char *inuri,
const char *outfile)
{
@@ -673,7 +673,7 @@ expand_thumbnailing_script (const char *script,
gboolean got_in;
str = g_string_new (NULL);
-
+
got_in = FALSE;
last = script;
while ((p = strchr (last, '%')) != NULL)
@@ -764,7 +764,7 @@ gnome_desktop_thumbnail_factory_generate_thumbnail (GnomeDesktopThumbnailFactory
g_return_val_if_fail (mime_type != NULL, NULL);
/* Doesn't access any volatile fields in factory, so it's threadsafe */
-
+
size = 128;
if (factory->priv->size == GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE)
size = 256;
@@ -774,7 +774,7 @@ gnome_desktop_thumbnail_factory_generate_thumbnail (GnomeDesktopThumbnailFactory
script = NULL;
if (factory->priv->scripts_hash != NULL)
script = g_hash_table_lookup (factory->priv->scripts_hash, mime_type);
-
+
if (script)
{
int fd;
@@ -814,7 +814,7 @@ gnome_desktop_thumbnail_factory_generate_thumbnail (GnomeDesktopThumbnailFactory
"gnome-original-height"));
}
}
-
+
if (pixbuf == NULL)
return NULL;
@@ -827,7 +827,7 @@ gnome_desktop_thumbnail_factory_generate_thumbnail (GnomeDesktopThumbnailFactory
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
-
+
if (width > size || height > size)
{
const gchar *orig_width, *orig_height;
@@ -846,11 +846,11 @@ gnome_desktop_thumbnail_factory_generate_thumbnail (GnomeDesktopThumbnailFactory
if (orig_height != NULL) {
gdk_pixbuf_set_option (scaled, "tEXt::Thumb::Image::Height", orig_height);
}
-
+
g_object_unref (pixbuf);
pixbuf = scaled;
}
-
+
if (original_width > 0) {
g_snprintf (dimension, sizeof (dimension), "%i", original_width);
gdk_pixbuf_set_option (pixbuf, "tEXt::Thumb::Image::Width", dimension);
@@ -863,6 +863,76 @@ gnome_desktop_thumbnail_factory_generate_thumbnail (GnomeDesktopThumbnailFactory
return pixbuf;
}
+
+gboolean
+gnome_desktop_thumbnail_factory_generate_thumbnail_async (GnomeDesktopThumbnailFactory *factory,
+ const char *uri,
+ const char *mime_type,
+ GPid *pid,
+ char **tmpname,
+ GError **error)
+{
+ gboolean retval = FALSE;
+ int size;
+ char *script;
+ int fd;
+ char *expanded_script;
+ int argc;
+ char **argv;
+
+ g_return_val_if_fail (uri != NULL, FALSE);
+ g_return_val_if_fail (mime_type != NULL, FALSE);
+
+ size = 128;
+ if (factory->priv->size == GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE)
+ size = 256;
+
+ script = NULL;
+ if (factory->priv->scripts_hash != NULL)
+ script = g_hash_table_lookup (factory->priv->scripts_hash, mime_type);
+
+ if (script == NULL)
+ return FALSE;
+
+ fd = g_file_open_tmp (".gnome_desktop_thumbnail.XXXXXX", tmpname, error);
+ if (fd == -1)
+ return FALSE;
+ close (fd);
+
+ expanded_script = expand_thumbnailing_script (script, size, uri, *tmpname);
+ if (g_shell_parse_argv (expanded_script, &argc, &argv, error))
+ if (g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, pid, error))
+ retval = TRUE;
+
+ g_free (expanded_script);
+
+ return retval;
+}
+
+
+GdkPixbuf *
+gnome_desktop_thumbnail_factory_load_from_tempfile (GnomeDesktopThumbnailFactory *factory,
+ char **tmpname)
+{
+ GdkPixbuf *pixbuf;
+ GdkPixbuf *tmp_pixbuf;
+
+ pixbuf = gdk_pixbuf_new_from_file (*tmpname, NULL);
+ g_unlink (*tmpname);
+ g_free (*tmpname);
+ *tmpname = NULL;
+
+ if (pixbuf == NULL)
+ return NULL;
+
+ tmp_pixbuf = gdk_pixbuf_apply_embedded_orientation (pixbuf);
+ g_object_unref (pixbuf);
+ pixbuf = tmp_pixbuf;
+
+ return pixbuf;
+}
+
+
static gboolean
make_thumbnail_dirs (GnomeDesktopThumbnailFactory *factory)
{
@@ -892,7 +962,7 @@ make_thumbnail_dirs (GnomeDesktopThumbnailFactory *factory)
g_free (thumbnail_dir);
g_free (image_dir);
-
+
return res;
}
@@ -936,7 +1006,7 @@ make_thumbnail_fail_dirs (GnomeDesktopThumbnailFactory *factory)
g_free (thumbnail_dir);
g_free (fail_dir);
g_free (app_dir);
-
+
return res;
}
@@ -944,9 +1014,9 @@ make_thumbnail_fail_dirs (GnomeDesktopThumbnailFactory *factory)
/**
* gnome_desktop_thumbnail_factory_save_thumbnail:
* @factory: a #GnomeDesktopThumbnailFactory
- * @thumbnail: the thumbnail as a pixbuf
+ * @thumbnail: the thumbnail as a pixbuf
* @uri: the uri of a file
- * @original_mtime: the modification time of the original file
+ * @original_mtime: the modification time of the original file
*
* Saves @thumbnail at the right place. If the save fails a
* failed thumbnail is written.
@@ -979,12 +1049,12 @@ gnome_desktop_thumbnail_factory_save_thumbnail (GnomeDesktopThumbnailFactory *fa
g_assert (digest_len == 16);
file = g_strconcat (g_checksum_get_string (checksum), ".png", NULL);
-
+
dir = g_build_filename (g_get_home_dir (),
".thumbnails",
(priv->size == GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL)?"normal":"large",
NULL);
-
+
path = g_build_filename (dir,
file,
NULL);
@@ -1012,12 +1082,12 @@ gnome_desktop_thumbnail_factory_save_thumbnail (GnomeDesktopThumbnailFactory *fa
return;
}
close (tmp_fd);
-
+
g_snprintf (mtime_str, 21, "%ld", original_mtime);
width = gdk_pixbuf_get_option (thumbnail, "tEXt::Thumb::Image::Width");
height = gdk_pixbuf_get_option (thumbnail, "tEXt::Thumb::Image::Height");
- if (width != NULL && height != NULL)
+ if (width != NULL && height != NULL)
saved_ok = gdk_pixbuf_save (thumbnail,
tmp_path,
"png", NULL,
@@ -1035,7 +1105,7 @@ gnome_desktop_thumbnail_factory_save_thumbnail (GnomeDesktopThumbnailFactory *fa
"tEXt::Thumb::MTime", mtime_str,
"tEXt::Software", "GNOME::ThumbnailFactory",
NULL);
-
+
if (saved_ok)
{
@@ -1087,12 +1157,12 @@ gnome_desktop_thumbnail_factory_create_failed_thumbnail (GnomeDesktopThumbnailFa
g_assert (digest_len == 16);
file = g_strconcat (g_checksum_get_string (checksum), ".png", NULL);
-
+
dir = g_build_filename (g_get_home_dir (),
".thumbnails/fail",
factory->priv->application,
NULL);
-
+
path = g_build_filename (dir,
file,
NULL);
@@ -1119,12 +1189,12 @@ gnome_desktop_thumbnail_factory_create_failed_thumbnail (GnomeDesktopThumbnailFa
return;
}
close (tmp_fd);
-
+
g_snprintf (mtime_str, 21, "%ld", mtime);
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
saved_ok = gdk_pixbuf_save (pixbuf,
tmp_path,
- "png", NULL,
+ "png", NULL,
"tEXt::Thumb::URI", uri,
"tEXt::Thumb::MTime", mtime_str,
"tEXt::Software", "GNOME::ThumbnailFactory",
@@ -1184,13 +1254,13 @@ gnome_desktop_thumbnail_path_for_uri (const char *uri,
md5 = gnome_desktop_thumbnail_md5 (uri);
file = g_strconcat (md5, ".png", NULL);
g_free (md5);
-
+
path = g_build_filename (g_get_home_dir (),
".thumbnails",
(size == GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL)?"normal":"large",
file,
NULL);
-
+
g_free (file);
return path;
@@ -1213,7 +1283,7 @@ gnome_desktop_thumbnail_has_uri (GdkPixbuf *pixbuf,
const char *uri)
{
const char *thumb_uri;
-
+
thumb_uri = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::URI");
if (!thumb_uri)
return FALSE;
@@ -1241,19 +1311,19 @@ gnome_desktop_thumbnail_is_valid (GdkPixbuf *pixbuf,
{
const char *thumb_uri, *thumb_mtime_str;
time_t thumb_mtime;
-
+
thumb_uri = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::URI");
if (!thumb_uri)
return FALSE;
if (strcmp (uri, thumb_uri) != 0)
return FALSE;
-
+
thumb_mtime_str = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::MTime");
if (!thumb_mtime_str)
return FALSE;
thumb_mtime = atol (thumb_mtime_str);
if (mtime != thumb_mtime)
return FALSE;
-
+
return TRUE;
}
diff --git a/gthumb/gnome-desktop-thumbnail.h b/gthumb/gnome-desktop-thumbnail.h
index c7537de..dfdc1af 100644
--- a/gthumb/gnome-desktop-thumbnail.h
+++ b/gthumb/gnome-desktop-thumbnail.h
@@ -50,7 +50,7 @@ typedef struct _GnomeDesktopThumbnailFactoryPrivate GnomeDesktopThumbnailFactory
struct _GnomeDesktopThumbnailFactory {
GObject parent;
-
+
GnomeDesktopThumbnailFactoryPrivate *priv;
};
@@ -75,6 +75,14 @@ gboolean gnome_desktop_thumbnail_factory_can_thumbnail (GnomeDeskt
GdkPixbuf * gnome_desktop_thumbnail_factory_generate_thumbnail (GnomeDesktopThumbnailFactory *factory,
const char *uri,
const char *mime_type);
+gboolean gnome_desktop_thumbnail_factory_generate_thumbnail_async (GnomeDesktopThumbnailFactory *factory,
+ const char *uri,
+ const char *mime_type,
+ GPid *pid,
+ char **tmpname,
+ GError **error);
+GdkPixbuf * gnome_desktop_thumbnail_factory_load_from_tempfile (GnomeDesktopThumbnailFactory *factory,
+ char **tmpname);
void gnome_desktop_thumbnail_factory_save_thumbnail (GnomeDesktopThumbnailFactory *factory,
GdkPixbuf *thumbnail,
const char *uri,
diff --git a/gthumb/gth-file-list.c b/gthumb/gth-file-list.c
index 319122e..a150d2c 100644
--- a/gthumb/gth-file-list.c
+++ b/gthumb/gth-file-list.c
@@ -37,6 +37,7 @@
#define DEFAULT_THUMBNAIL_SIZE 112
#define N_THUMBS_PER_NOTIFICATION 15
+#define UPDATE_THUMBNAILS_TIMEOUT 250
#define N_LOOKAHEAD 50
#define EMPTY (N_("(Empty)"))
@@ -96,6 +97,8 @@ struct _GthFileListPrivateData
GthFileData *thumb_fd;
gboolean loading_thumbs;
gboolean cancel;
+ gboolean dirty;
+ guint dirty_event;
GList *queue; /* list of GthFileListOp */
GtkCellRenderer *thumbnail_renderer;
GtkCellRenderer *text_renderer;
@@ -154,6 +157,11 @@ gth_file_list_op_free (GthFileListOp *op)
static void
_gth_file_list_clear_queue (GthFileList *file_list)
{
+ if (file_list->priv->dirty_event != 0) {
+ g_source_remove (file_list->priv->dirty_event);
+ file_list->priv->dirty = FALSE;
+ }
+
g_list_foreach (file_list->priv->queue, (GFunc) gth_file_list_op_free, NULL);
g_list_free (file_list->priv->queue);
file_list->priv->queue = NULL;
@@ -249,6 +257,23 @@ gth_file_list_init (GthFileList *file_list)
static void _gth_file_list_update_next_thumb (GthFileList *file_list);
+static gboolean
+flash_queue_cb (gpointer data)
+{
+ GthFileList *file_list = data;
+ GthFileStore *file_store;
+
+ file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
+ gth_file_store_exec_set (file_store);
+
+ g_source_remove (file_list->priv->dirty_event);
+ file_list->priv->dirty_event = 0;
+ file_list->priv->dirty = FALSE;
+
+ return FALSE;
+}
+
+
static void
update_thumb_in_file_view (GthFileList *file_list)
{
@@ -258,16 +283,46 @@ update_thumb_in_file_view (GthFileList *file_list)
file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
pixbuf = gth_thumb_loader_get_pixbuf (file_list->priv->thumb_loader);
- if (pixbuf != NULL)
+ if (pixbuf != NULL) {
gth_file_store_queue_set (file_store,
gth_file_store_get_abs_pos (file_store, file_list->priv->thumb_pos),
NULL,
pixbuf,
FALSE,
NULL);
+ file_list->priv->dirty = TRUE;
+ if (file_list->priv->dirty_event == 0)
+ file_list->priv->dirty_event = g_timeout_add (UPDATE_THUMBNAILS_TIMEOUT, flash_queue_cb, file_list);
+ }
+}
- if (file_list->priv->n_thumb % N_THUMBS_PER_NOTIFICATION == N_THUMBS_PER_NOTIFICATION - 1)
- gth_file_store_exec_set (file_store);
+
+static void
+set_mime_type_icon (GthFileList *file_list,
+ GthFileData *file_data)
+{
+ GthFileStore *file_store;
+ int pos;
+ GIcon *icon;
+ GdkPixbuf *pixbuf;
+
+ file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
+
+ pos = gth_file_store_find (file_store, file_data->file);
+ if (pos < 0)
+ return;
+
+ icon = g_file_info_get_icon (file_data->info);
+ pixbuf = gth_icon_cache_get_pixbuf (file_list->priv->icon_cache, icon);
+ gth_file_store_queue_set (file_store,
+ pos,
+ NULL,
+ pixbuf,
+ TRUE,
+ NULL);
+
+ if (pixbuf != NULL)
+ g_object_unref (pixbuf);
}
@@ -291,8 +346,11 @@ thumb_loader_ready_cb (GthThumbLoader *tloader,
file_list->priv->thumb_fd->error = TRUE;
file_list->priv->thumb_fd->thumb_loaded = FALSE;
file_list->priv->thumb_fd->thumb_created = FALSE;
+ if (file_list->priv->update_thumb_in_view)
+ set_mime_type_icon (file_list, file_list->priv->thumb_fd);
}
}
+
_gth_file_list_update_next_thumb (file_list);
}
@@ -715,7 +773,7 @@ gfl_update_files (GthFileList *file_list,
abs_pos,
fd,
NULL,
- FALSE,
+ -1,
NULL);
}
gth_file_store_exec_set (file_store);
@@ -949,8 +1007,38 @@ _gth_file_list_thumbs_completed (GthFileList *file_list)
static void
+set_loading_icon (GthFileList *file_list,
+ GthFileData *file_data)
+{
+ GthFileStore *file_store;
+ int pos;
+ GIcon *icon;
+ GdkPixbuf *pixbuf;
+
+ file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
+
+ pos = gth_file_store_find (file_store, file_data->file);
+ if (pos < 0)
+ return;
+
+ icon = g_themed_icon_new ("image-loading");
+ pixbuf = gth_icon_cache_get_pixbuf (file_list->priv->icon_cache, icon);
+ gth_file_store_queue_set (file_store,
+ pos,
+ NULL,
+ pixbuf,
+ TRUE,
+ NULL);
+
+ _g_object_unref (pixbuf);
+ g_object_unref (icon);
+}
+
+
+static void
_gth_file_list_update_current_thumb (GthFileList *file_list)
{
+ set_loading_icon (file_list, file_list->priv->thumb_fd);
gth_thumb_loader_set_file (file_list->priv->thumb_loader, file_list->priv->thumb_fd);
gth_thumb_loader_load (file_list->priv->thumb_loader);
}
diff --git a/gthumb/gth-file-store.c b/gthumb/gth-file-store.c
index ee12c01..00ee185 100644
--- a/gthumb/gth-file-store.c
+++ b/gthumb/gth-file-store.c
@@ -1162,7 +1162,7 @@ gth_file_store_find (GthFileStore *file_store,
continue;
if (g_file_equal (row->file->file, file))
- return i;
+ return row->abs_pos;
}
return -1;
@@ -1182,7 +1182,7 @@ gth_file_store_find_visible (GthFileStore *file_store,
continue;
if (g_file_equal (row->file->file, file))
- return i;
+ return row->pos;
}
return -1;
@@ -1272,7 +1272,8 @@ gth_file_store_queue_set (GthFileStore *file_store,
_gth_file_row_set_file (row, file);
_gth_file_row_set_thumbnail (row, thumbnail);
_gth_file_row_set_metadata (row, metadata);
- row->is_icon = is_icon;
+ if (is_icon != -1)
+ row->is_icon = is_icon;
row->changed = TRUE;
if (file != NULL)
diff --git a/gthumb/gth-main-default-types.c b/gthumb/gth-main-default-types.c
index 64b33ff..9cc7609 100644
--- a/gthumb/gth-main-default-types.c
+++ b/gthumb/gth-main-default-types.c
@@ -25,10 +25,34 @@
#include <glib/gi18n.h>
#include "gth-file-properties.h"
#include "gth-main.h"
+#include "pixbuf-io.h"
-void
+static void
+gth_main_register_default_file_loader (void)
+{
+ GSList *formats;
+ GSList *scan;
+
+ formats = gdk_pixbuf_get_formats ();
+ for (scan = formats; scan; scan = scan->next) {
+ GdkPixbufFormat *format = scan->data;
+ char **mime_types;
+ int i;
+
+ if (gdk_pixbuf_format_is_disabled (format))
+ continue;
+
+ mime_types = gdk_pixbuf_format_get_mime_types (format);
+ for (i = 0; mime_types[i] != NULL; i++)
+ gth_main_register_file_loader (gth_pixbuf_animation_new_from_file, mime_types[i], NULL);
+ }
+}
+
+
+void
gth_main_register_default_types (void)
{
gth_main_register_type ("file-properties", GTH_TYPE_FILE_PROPERTIES);
+ gth_main_register_default_file_loader ();
}
diff --git a/gthumb/gth-main.c b/gthumb/gth-main.c
index 4993022..c5385ea 100644
--- a/gthumb/gth-main.c
+++ b/gthumb/gth-main.c
@@ -718,9 +718,9 @@ gth_main_register_file_loader (FileLoader loader,
va_start (var_args, first_mime_type);
mime_type = first_mime_type;
while (mime_type != NULL) {
- mime_type = va_arg (var_args, const char *);
g_hash_table_insert (Main->priv->loaders, (gpointer) get_static_string (mime_type), loader);
- }
+ mime_type = va_arg (var_args, const char *);
+ }
va_end (var_args);
}
@@ -728,13 +728,7 @@ gth_main_register_file_loader (FileLoader loader,
FileLoader
gth_main_get_file_loader (const char *mime_type)
{
- FileLoader loader;
-
- loader = g_hash_table_lookup (Main->priv->loaders, mime_type);
- if (loader == NULL)
- loader = gth_pixbuf_animation_new_from_file;
-
- return loader;
+ return (FileLoader) g_hash_table_lookup (Main->priv->loaders, mime_type);
}
diff --git a/gthumb/gth-thumb-loader.c b/gthumb/gth-thumb-loader.c
index 164c3f5..0baa2c7 100644
--- a/gthumb/gth-thumb-loader.c
+++ b/gthumb/gth-thumb-loader.c
@@ -24,6 +24,8 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
#define GDK_PIXBUF_ENABLE_BACKEND
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf-animation.h>
@@ -39,10 +41,11 @@
#include "pixbuf-utils.h"
#include "typedefs.h"
-#define DEFAULT_MAX_FILE_SIZE (4*1024*1024)
-#define THUMBNAIL_LARGE_SIZE 256
-#define THUMBNAIL_NORMAL_SIZE 128
+#define DEFAULT_MAX_FILE_SIZE (4*1024*1024)
+#define THUMBNAIL_LARGE_SIZE 256
+#define THUMBNAIL_NORMAL_SIZE 128
#define THUMBNAIL_DIR_PERMISSIONS 0700
+#define KILL_THUMBNAILER_DELAY 3000
struct _GthThumbLoaderPrivateData
{
@@ -65,6 +68,10 @@ struct _GthThumbLoaderPrivateData
GnomeDesktopThumbnailSize thumb_size;
GnomeDesktopThumbnailFactory *thumb_factory;
+ char *thumbnailer_tmpfile;
+ GPid thumbnailer_pid;
+ guint thumbnailer_watch;
+ guint thumbnailer_timeout;
};
@@ -89,8 +96,8 @@ gth_thumb_loader_finalize (GObject *object)
tloader = GTH_THUMB_LOADER (object);
if (tloader->priv != NULL) {
- if (tloader->priv->pixbuf != NULL)
- g_object_unref (tloader->priv->pixbuf);
+ g_free (tloader->priv->thumbnailer_tmpfile);
+ _g_object_unref (tloader->priv->pixbuf);
g_object_unref (tloader->priv->iloader);
g_object_unref (tloader->priv->file);
g_free (tloader->priv);
@@ -260,10 +267,10 @@ _gth_thumb_loader_save_to_cache (GthThumbLoader *tloader)
static void
image_loader_loaded (GthImageLoader *iloader,
+ GdkPixbuf *pixbuf,
gpointer data)
{
GthThumbLoader *tloader = data;
- GdkPixbuf *pixbuf;
int width, height;
gboolean modified;
@@ -272,7 +279,6 @@ image_loader_loaded (GthImageLoader *iloader,
tloader->priv->pixbuf = NULL;
}
- pixbuf = gth_image_loader_get_pixbuf (tloader->priv->iloader);
if (pixbuf == NULL) {
char *uri;
@@ -372,15 +378,107 @@ image_loader_error (GthImageLoader *iloader,
}
+static gboolean
+kill_thumbnailer_cb (gpointer data)
+{
+ GthThumbLoader *tloader = data;
+
+ g_source_remove (tloader->priv->thumbnailer_timeout);
+ tloader->priv->thumbnailer_timeout = 0;
+
+ if (tloader->priv->thumbnailer_pid != 0) {
+ /*g_source_remove (tloader->priv->thumbnailer_watch);
+ tloader->priv->thumbnailer_watch = 0;*/
+ kill (tloader->priv->thumbnailer_pid, SIGTERM);
+ /*tloader->priv->thumbnailer_pid = 0;*/
+ }
+
+ return FALSE;
+}
+
+
+static void
+watch_thumbnailer_cb (GPid pid,
+ int status,
+ gpointer data)
+{
+ GthThumbLoader *tloader = data;
+ GdkPixbuf *pixbuf;
+ GError *error;
+
+ if (tloader->priv->thumbnailer_timeout != 0) {
+ g_source_remove (tloader->priv->thumbnailer_timeout);
+ tloader->priv->thumbnailer_timeout = 0;
+ }
+
+ g_spawn_close_pid (pid);
+ tloader->priv->thumbnailer_pid = 0;
+ tloader->priv->thumbnailer_watch = 0;
+
+ if (status != 0) {
+ error = g_error_new_literal (GTHUMB_ERROR, 0, "cannot generate the thumbnail");
+ image_loader_error (NULL, error, data);
+ return;
+ }
+
+ pixbuf = gnome_desktop_thumbnail_factory_load_from_tempfile (tloader->priv->thumb_factory,
+ &tloader->priv->thumbnailer_tmpfile);
+ if (pixbuf != NULL) {
+ image_loader_loaded (NULL, pixbuf, data);
+ g_object_unref (pixbuf);
+ }
+ else {
+ error = g_error_new_literal (GTHUMB_ERROR, 0, "cannot generate the thumbnail");
+ image_loader_error (NULL, error, data);
+ }
+}
+
+
static void
image_loader_ready_cb (GthImageLoader *iloader,
GError *error,
gpointer data)
{
- if (error == NULL)
- image_loader_loaded (iloader, data);
- else
+ GthThumbLoader *tloader = data;
+ char *uri;
+
+ if (error == NULL) {
+ image_loader_loaded (iloader, gth_image_loader_get_pixbuf (tloader->priv->iloader), data);
+ return;
+ }
+
+ if (tloader->priv->from_cache) {
image_loader_error (iloader, error, data);
+ return;
+ }
+
+ /* try with the system thumbnailer as fallback */
+
+ g_clear_error (&error);
+ g_free (tloader->priv->thumbnailer_tmpfile);
+ tloader->priv->thumbnailer_tmpfile = NULL;
+ uri = g_file_get_uri (tloader->priv->file->file);
+ if (gnome_desktop_thumbnail_factory_generate_thumbnail_async (tloader->priv->thumb_factory,
+ uri,
+ gth_file_data_get_mime_type (tloader->priv->file),
+ &tloader->priv->thumbnailer_pid,
+ &tloader->priv->thumbnailer_tmpfile,
+ &error))
+ {
+ tloader->priv->thumbnailer_watch = g_child_watch_add (tloader->priv->thumbnailer_pid,
+ watch_thumbnailer_cb,
+ tloader);
+ tloader->priv->thumbnailer_timeout = g_timeout_add (KILL_THUMBNAILER_DELAY,
+ kill_thumbnailer_cb,
+ tloader);
+ }
+ else {
+ if (error == NULL)
+ error = g_error_new_literal (GTHUMB_ERROR, 0, "cannot generate the thumbnail");
+ image_loader_error (iloader, error, data);
+ }
+
+ g_free (uri);
}
@@ -390,41 +488,34 @@ thumb_loader (GthFileData *file,
gpointer data)
{
GthThumbLoader *tloader = data;
- GdkPixbuf *pixbuf;
GdkPixbufAnimation *animation = NULL;
+ GdkPixbuf *pixbuf = NULL;
- /* try with a custom thumbnailer first */
-
- if (! tloader->priv->from_cache) {
- FileLoader thumbnailer;
-
- thumbnailer = gth_main_get_file_loader (gth_file_data_get_mime_type (file));
- if (thumbnailer != NULL)
- animation = thumbnailer (file, error, tloader->priv->cache_max_w, tloader->priv->cache_max_h);
-
- if (animation != NULL)
- return animation;
+ if (tloader->priv->from_cache) {
+ pixbuf = gth_pixbuf_new_from_file (file, error, -1, -1);
}
+ else {
+ /* try with a custom thumbnailer first */
- /* use the default thumbnailer as fallback */
-
- if (! tloader->priv->from_cache) {
- char *uri;
+ if (! tloader->priv->from_cache) {
+ FileLoader thumbnailer;
- uri = g_file_get_uri (file->file);
- pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (tloader->priv->thumb_factory, uri, gth_file_data_get_mime_type (file));
- g_free (uri);
+ thumbnailer = gth_main_get_file_loader (gth_file_data_get_mime_type (file));
+ if (thumbnailer != NULL)
+ animation = thumbnailer (file, error, tloader->priv->cache_max_w, tloader->priv->cache_max_h);
- if (pixbuf == NULL)
- *error = g_error_new_literal (GTHUMB_ERROR, 0, "cannot generate the thumbnail");
+ if (animation != NULL)
+ return animation;
+ }
}
- else
- pixbuf = gth_pixbuf_new_from_file (file, error, -1, -1);
if (pixbuf != NULL) {
+ g_clear_error (error);
animation = gdk_pixbuf_non_anim_new (pixbuf);
g_object_unref (pixbuf);
}
+ else
+ *error = g_error_new_literal (GTHUMB_ERROR, 0, "cannot generate the thumbnail");
return animation;
}
@@ -461,7 +552,7 @@ gth_thumb_loader_new (int width,
void
gth_thumb_loader_set_thumb_size (GthThumbLoader *tloader,
- int width,
+ int width,
int height)
{
if (tloader->priv->thumb_factory != NULL) {
@@ -667,5 +758,17 @@ gth_thumb_loader_cancel (GthThumbLoader *tloader,
{
g_return_if_fail (tloader->priv->iloader != NULL);
+ if (tloader->priv->thumbnailer_timeout != 0) {
+ g_source_remove (tloader->priv->thumbnailer_timeout);
+ tloader->priv->thumbnailer_timeout = 0;
+ }
+
+ if (tloader->priv->thumbnailer_pid != 0) {
+ g_source_remove (tloader->priv->thumbnailer_watch);
+ tloader->priv->thumbnailer_watch = 0;
+ kill (tloader->priv->thumbnailer_pid, SIGTERM);
+ tloader->priv->thumbnailer_pid = 0;
+ }
+
gth_image_loader_cancel (tloader->priv->iloader, done_func, done_func_data);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]