[gthumb] use the new thumbnail system if the --enable-gnome-3 flag is used
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] use the new thumbnail system if the --enable-gnome-3 flag is used
- Date: Mon, 6 Jun 2011 15:24:11 +0000 (UTC)
commit b69fe7c765fd2f7ce863ae061bb1b431d41619dd
Author: Paolo Bacchilega <paobac src gnome org>
Date: Mon Jun 6 17:21:16 2011 +0200
use the new thumbnail system if the --enable-gnome-3 flag is used
gthumb/gnome-desktop-thumbnail.c | 619 +++++++++++++++++++++++++++++++++++---
1 files changed, 573 insertions(+), 46 deletions(-)
---
diff --git a/gthumb/gnome-desktop-thumbnail.c b/gthumb/gnome-desktop-thumbnail.c
index 3a2045a..d5cdec6 100644
--- a/gthumb/gnome-desktop-thumbnail.c
+++ b/gthumb/gnome-desktop-thumbnail.c
@@ -73,9 +73,24 @@ struct _GnomeDesktopThumbnailFactoryPrivate {
GMutex *lock;
+#ifdef HAVE_GNOME_3
+
+ GList *thumbnailers;
+ GHashTable *mime_types_map;
+ GList *monitors;
+
+ GSettings *settings;
+ gboolean loaded : 1;
+ gboolean disabled : 1;
+ gchar **disabled_types;
+
+#else /* ! HAVE_GNOME_3 */
+
GHashTable *scripts_hash;
guint thumbnailers_notify;
guint reread_scheduled;
+
+#endif
};
static const char *appname = "gnome-thumbnail-factory";
@@ -274,45 +289,496 @@ _gdk_pixbuf_new_from_uri_at_scale (const char *uri,
}
+#ifdef HAVE_GNOME_3
+
+
+#define LOAD_BUFFER_SIZE 4096
+
+#define THUMBNAILER_ENTRY_GROUP "Thumbnailer Entry"
+#define THUMBNAILER_EXTENSION ".thumbnailer"
+
+typedef struct {
+ volatile gint ref_count;
+
+ gchar *path;
+
+ gchar *try_exec;
+ gchar *command;
+ gchar **mime_types;
+} Thumbnailer;
+
+static Thumbnailer *
+thumbnailer_ref (Thumbnailer *thumb)
+{
+ g_return_val_if_fail (thumb != NULL, NULL);
+ g_return_val_if_fail (thumb->ref_count > 0, NULL);
+
+ g_atomic_int_inc (&thumb->ref_count);
+ return thumb;
+}
+
static void
-gnome_desktop_thumbnail_factory_finalize (GObject *object)
+thumbnailer_unref (Thumbnailer *thumb)
{
- GnomeDesktopThumbnailFactory *factory;
- GnomeDesktopThumbnailFactoryPrivate *priv;
- GConfClient *client;
+ g_return_if_fail (thumb != NULL);
+ g_return_if_fail (thumb->ref_count > 0);
- factory = GNOME_DESKTOP_THUMBNAIL_FACTORY (object);
+ if (g_atomic_int_dec_and_test (&thumb->ref_count))
+ {
+ g_free (thumb->path);
+ g_free (thumb->try_exec);
+ g_free (thumb->command);
+ g_strfreev (thumb->mime_types);
- priv = factory->priv;
+ g_slice_free (Thumbnailer, thumb);
+ }
+}
- if (priv->reread_scheduled != 0) {
- g_source_remove (priv->reread_scheduled);
- priv->reread_scheduled = 0;
- }
+static Thumbnailer *
+thumbnailer_load (Thumbnailer *thumb)
+{
+ GKeyFile *key_file;
+ GError *error = NULL;
- if (priv->thumbnailers_notify != 0) {
- client = gconf_client_get_default ();
- gconf_client_notify_remove (client, priv->thumbnailers_notify);
- priv->thumbnailers_notify = 0;
- g_object_unref (client);
- }
+ key_file = g_key_file_new ();
+ if (!g_key_file_load_from_file (key_file, thumb->path, 0, &error))
+ {
+ g_warning ("Failed to load thumbnailer from \"%s\": %s\n", thumb->path, error->message);
+ g_error_free (error);
+ thumbnailer_unref (thumb);
+ g_key_file_free (key_file);
+
+ return NULL;
+ }
+
+ if (!g_key_file_has_group (key_file, THUMBNAILER_ENTRY_GROUP))
+ {
+ g_warning ("Invalid thumbnailer: missing group \"%s\"\n", THUMBNAILER_ENTRY_GROUP);
+ thumbnailer_unref (thumb);
+ g_key_file_free (key_file);
+
+ return NULL;
+ }
+
+ thumb->command = g_key_file_get_string (key_file, THUMBNAILER_ENTRY_GROUP, "Exec", NULL);
+ if (!thumb->command)
+ {
+ g_warning ("Invalid thumbnailer: missing Exec key\n");
+ thumbnailer_unref (thumb);
+ g_key_file_free (key_file);
+
+ return NULL;
+ }
+
+ thumb->mime_types = g_key_file_get_string_list (key_file, THUMBNAILER_ENTRY_GROUP, "MimeType", NULL, NULL);
+ if (!thumb->mime_types)
+ {
+ g_warning ("Invalid thumbnailer: missing MimeType key\n");
+ thumbnailer_unref (thumb);
+ g_key_file_free (key_file);
+
+ return NULL;
+ }
+
+ thumb->try_exec = g_key_file_get_string (key_file, THUMBNAILER_ENTRY_GROUP, "TryExec", NULL);
+
+ g_key_file_free (key_file);
+
+ return thumb;
+}
+
+static Thumbnailer *
+thumbnailer_reload (Thumbnailer *thumb)
+{
+ g_return_val_if_fail (thumb != NULL, NULL);
+
+ g_free (thumb->command);
+ thumb->command = NULL;
+ g_strfreev (thumb->mime_types);
+ thumb->mime_types = NULL;
+ g_free (thumb->try_exec);
+ thumb->try_exec = NULL;
+
+ return thumbnailer_load (thumb);
+}
+
+static Thumbnailer *
+thumbnailer_new (const gchar *path)
+{
+ Thumbnailer *thumb;
+
+ thumb = g_slice_new0 (Thumbnailer);
+ thumb->ref_count = 1;
+ thumb->path = g_strdup (path);
+
+ return thumbnailer_load (thumb);
+}
+
+
+static gpointer
+init_thumbnailers_dirs (gpointer data)
+{
+ const gchar * const *data_dirs;
+ gchar **thumbs_dirs;
+ guint i, length;
+
+ data_dirs = g_get_system_data_dirs ();
+ length = g_strv_length ((char **) data_dirs);
+
+ thumbs_dirs = g_new (gchar *, length + 2);
+ thumbs_dirs[0] = g_build_filename (g_get_user_data_dir (), "thumbnailers", NULL);
+ for (i = 0; i < length; i++)
+ thumbs_dirs[i + 1] = g_build_filename (data_dirs[i], "thumbnailers", NULL);
+ thumbs_dirs[length + 1] = NULL;
- if (priv->scripts_hash)
+ return thumbs_dirs;
+}
+
+static const gchar * const *
+get_thumbnailers_dirs (void)
+{
+ static GOnce once_init = G_ONCE_INIT;
+ return g_once (&once_init, init_thumbnailers_dirs, NULL);
+}
+
+
+/* These should be called with the lock held */
+static void
+gnome_desktop_thumbnail_factory_register_mime_types (GnomeDesktopThumbnailFactory *factory,
+ Thumbnailer *thumb)
+{
+ GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
+ gint i;
+
+ for (i = 0; thumb->mime_types[i]; i++)
{
- g_hash_table_destroy (priv->scripts_hash);
- priv->scripts_hash = NULL;
+ if (!g_hash_table_lookup (priv->mime_types_map, thumb->mime_types[i]))
+ g_hash_table_insert (priv->mime_types_map,
+ g_strdup (thumb->mime_types[i]),
+ thumbnailer_ref (thumb));
}
+}
+
+static void
+gnome_desktop_thumbnail_factory_add_thumbnailer (GnomeDesktopThumbnailFactory *factory,
+ Thumbnailer *thumb)
+{
+ GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
+
+ gnome_desktop_thumbnail_factory_register_mime_types (factory, thumb);
+ priv->thumbnailers = g_list_prepend (priv->thumbnailers, thumb);
+}
- if (priv->lock)
+
+static gboolean
+gnome_desktop_thumbnail_factory_is_disabled (GnomeDesktopThumbnailFactory *factory,
+ const gchar *mime_type)
+{
+ GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
+ guint i;
+
+ if (priv->disabled)
+ return TRUE;
+
+ if (!priv->disabled_types)
+ return FALSE;
+
+ for (i = 0; priv->disabled_types[i]; i++)
{
- g_mutex_free (priv->lock);
- priv->lock = NULL;
+ if (g_strcmp0 (priv->disabled_types[i], mime_type) == 0)
+ return TRUE;
}
- if (G_OBJECT_CLASS (parent_class)->finalize)
- (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+ return FALSE;
+}
+
+
+static gboolean
+remove_thumbnailer_from_mime_type_map (gchar *key,
+ Thumbnailer *value,
+ gchar *path)
+{
+ return (strcmp (value->path, path) == 0);
}
+
+static void
+update_or_create_thumbnailer (GnomeDesktopThumbnailFactory *factory,
+ const gchar *path)
+{
+ GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
+ GList *l;
+ Thumbnailer *thumb;
+ gboolean found = FALSE;
+
+ g_mutex_lock (priv->lock);
+
+ for (l = priv->thumbnailers; l && !found; l = g_list_next (l))
+ {
+ thumb = (Thumbnailer *)l->data;
+
+ if (strcmp (thumb->path, path) == 0)
+ {
+ found = TRUE;
+
+ /* First remove the mime_types associated to this thumbnailer */
+ g_hash_table_foreach_remove (priv->mime_types_map,
+ (GHRFunc)remove_thumbnailer_from_mime_type_map,
+ (gpointer)path);
+ if (!thumbnailer_reload (thumb))
+ priv->thumbnailers = g_list_delete_link (priv->thumbnailers, l);
+ else
+ gnome_desktop_thumbnail_factory_register_mime_types (factory, thumb);
+ }
+ }
+
+ if (!found)
+ {
+ thumb = thumbnailer_new (path);
+ if (thumb)
+ gnome_desktop_thumbnail_factory_add_thumbnailer (factory, thumb);
+ }
+
+ g_mutex_unlock (priv->lock);
+}
+
+
+static void
+remove_thumbnailer (GnomeDesktopThumbnailFactory *factory,
+ const gchar *path)
+{
+ GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
+ GList *l;
+ Thumbnailer *thumb;
+
+ g_mutex_lock (priv->lock);
+
+ for (l = priv->thumbnailers; l; l = g_list_next (l))
+ {
+ thumb = (Thumbnailer *)l->data;
+
+ if (strcmp (thumb->path, path) == 0)
+ {
+ priv->thumbnailers = g_list_delete_link (priv->thumbnailers, l);
+ g_hash_table_foreach_remove (priv->mime_types_map,
+ (GHRFunc)remove_thumbnailer_from_mime_type_map,
+ (gpointer)path);
+ thumbnailer_unref (thumb);
+
+ break;
+ }
+ }
+
+ g_mutex_unlock (priv->lock);
+}
+
+
+static void
+thumbnailers_directory_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ GnomeDesktopThumbnailFactory *factory)
+{
+ gchar *path;
+
+ switch (event_type)
+ {
+ case G_FILE_MONITOR_EVENT_CREATED:
+ case G_FILE_MONITOR_EVENT_CHANGED:
+ case G_FILE_MONITOR_EVENT_DELETED:
+ path = g_file_get_path (file);
+ if (!g_str_has_suffix (path, THUMBNAILER_EXTENSION))
+ {
+ g_free (path);
+ return;
+ }
+
+ if (event_type == G_FILE_MONITOR_EVENT_DELETED)
+ remove_thumbnailer (factory, path);
+ else
+ update_or_create_thumbnailer (factory, path);
+
+ g_free (path);
+ break;
+ default:
+ break;
+ }
+}
+
+
+static void
+gnome_desktop_thumbnail_factory_load_thumbnailers (GnomeDesktopThumbnailFactory *factory)
+{
+ GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
+ const gchar * const *dirs;
+ guint i;
+
+ if (priv->loaded)
+ return;
+
+ dirs = get_thumbnailers_dirs ();
+ for (i = 0; dirs[i]; i++)
+ {
+ const gchar *path = dirs[i];
+ GDir *dir;
+ GFile *dir_file;
+ GFileMonitor *monitor;
+ const gchar *dirent;
+
+ dir = g_dir_open (path, 0, NULL);
+ if (!dir)
+ continue;
+
+ /* Monitor dir */
+ dir_file = g_file_new_for_path (path);
+ monitor = g_file_monitor_directory (dir_file,
+ G_FILE_MONITOR_NONE,
+ NULL, NULL);
+ if (monitor)
+ {
+ g_signal_connect (monitor, "changed",
+ G_CALLBACK (thumbnailers_directory_changed),
+ factory);
+ priv->monitors = g_list_prepend (priv->monitors, monitor);
+ }
+ g_object_unref (dir_file);
+
+ while ((dirent = g_dir_read_name (dir)))
+ {
+ Thumbnailer *thumb;
+ gchar *filename;
+
+ if (!g_str_has_suffix (dirent, THUMBNAILER_EXTENSION))
+ continue;
+
+ filename = g_build_filename (path, dirent, NULL);
+ thumb = thumbnailer_new (filename);
+ g_free (filename);
+
+ if (thumb)
+ gnome_desktop_thumbnail_factory_add_thumbnailer (factory, thumb);
+ }
+
+ g_dir_close (dir);
+ }
+
+ priv->loaded = TRUE;
+}
+
+
+static void
+external_thumbnailers_disabled_all_changed_cb (GSettings *settings,
+ const gchar *key,
+ GnomeDesktopThumbnailFactory *factory)
+{
+ g_mutex_lock (factory->priv->lock);
+
+ factory->priv->disabled = g_settings_get_boolean (factory->priv->settings, "disable-all");
+ if (factory->priv->disabled) {
+ g_strfreev (factory->priv->disabled_types);
+ factory->priv->disabled_types = NULL;
+ }
+ else {
+ factory->priv->disabled_types = g_settings_get_strv (factory->priv->settings, "disable");
+ gnome_desktop_thumbnail_factory_load_thumbnailers (factory);
+ }
+
+ g_mutex_unlock (factory->priv->lock);
+}
+
+static void
+external_thumbnailers_disabled_changed_cb (GSettings *settings,
+ const gchar *key,
+ GnomeDesktopThumbnailFactory *factory)
+{
+ g_mutex_lock (factory->priv->lock);
+
+ if (factory->priv->disabled)
+ return;
+ g_strfreev (factory->priv->disabled_types);
+ factory->priv->disabled_types = g_settings_get_strv (factory->priv->settings, "disable");
+
+ g_mutex_unlock (factory->priv->lock);
+}
+
+
+static void
+gnome_desktop_thumbnail_factory_init_scripts (GnomeDesktopThumbnailFactory *factory)
+{
+ factory->priv->mime_types_map = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)thumbnailer_unref);
+ factory->priv->settings = g_settings_new ("org.gnome.desktop.thumbnailers");
+ factory->priv->disabled = g_settings_get_boolean (factory->priv->settings, "disable-all");
+ if (! factory->priv->disabled)
+ factory->priv->disabled_types = g_settings_get_strv (factory->priv->settings, "disable");
+ g_signal_connect (factory->priv->settings,
+ "changed::disable-all",
+ G_CALLBACK (external_thumbnailers_disabled_all_changed_cb),
+ factory);
+ g_signal_connect (factory->priv->settings,
+ "changed::disable",
+ G_CALLBACK (external_thumbnailers_disabled_changed_cb),
+ factory);
+
+ if (! factory->priv->disabled)
+ gnome_desktop_thumbnail_factory_load_thumbnailers (factory);
+}
+
+
+static void
+gnome_desktop_thumbnail_factory_finalize_scripts (GnomeDesktopThumbnailFactory *factory)
+{
+ if (factory->priv->thumbnailers) {
+ g_list_free_full (factory->priv->thumbnailers, (GDestroyNotify)thumbnailer_unref);
+ factory->priv->thumbnailers = NULL;
+ }
+
+ if (factory->priv->mime_types_map) {
+ g_hash_table_destroy (factory->priv->mime_types_map);
+ factory->priv->mime_types_map = NULL;
+ }
+
+ if (factory->priv->monitors) {
+ g_list_free_full (factory->priv->monitors, (GDestroyNotify)g_object_unref);
+ factory->priv->monitors = NULL;
+ }
+
+ if (factory->priv->disabled_types) {
+ g_strfreev (factory->priv->disabled_types);
+ factory->priv->disabled_types = NULL;
+ }
+
+ if (factory->priv->settings) {
+ g_object_unref (factory->priv->settings);
+ factory->priv->settings = NULL;
+ }
+}
+
+
+static char *
+gnome_desktop_thumbnail_factory_get_script (GnomeDesktopThumbnailFactory *factory,
+ const char *mime_type)
+{
+ char *script = NULL;
+
+ if (!gnome_desktop_thumbnail_factory_is_disabled (factory, mime_type)) {
+ Thumbnailer *thumb;
+
+ thumb = g_hash_table_lookup (factory->priv->mime_types_map, mime_type);
+ if (thumb)
+ script = g_strdup (thumb->command);
+ }
+
+ return script;
+}
+
+
+#else /* ! HAVE_GNOME_3 */
+
+
/* Must be called on main thread */
static GHashTable *
read_scripts (void)
@@ -408,6 +874,7 @@ gnome_desktop_thumbnail_factory_reread_scripts (GnomeDesktopThumbnailFactory *fa
g_mutex_unlock (priv->lock);
}
+
static gboolean
reread_idle_callback (gpointer user_data)
{
@@ -445,33 +912,97 @@ schedule_reread (GConfClient* client,
static void
-gnome_desktop_thumbnail_factory_init (GnomeDesktopThumbnailFactory *factory)
+gnome_desktop_thumbnail_factory_init_scripts (GnomeDesktopThumbnailFactory *factory)
{
- GConfClient *client;
- GnomeDesktopThumbnailFactoryPrivate *priv;
+ GConfClient *client;
- factory->priv = GNOME_DESKTOP_THUMBNAIL_FACTORY_GET_PRIVATE (factory);
+ factory->priv->scripts_hash = NULL;
- priv = factory->priv;
+ client = gconf_client_get_default ();
+ gconf_client_add_dir (client,
+ "/desktop/gnome/thumbnailers",
+ GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
- priv->size = GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL;
+ gnome_desktop_thumbnail_factory_reread_scripts (factory);
- priv->scripts_hash = NULL;
+ factory->priv->thumbnailers_notify = gconf_client_notify_add (client, "/desktop/gnome/thumbnailers",
+ schedule_reread, factory, NULL,
+ NULL);
- priv->lock = g_mutex_new ();
+ g_object_unref (G_OBJECT (client));
+}
- client = gconf_client_get_default ();
- gconf_client_add_dir (client,
- "/desktop/gnome/thumbnailers",
- GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
- gnome_desktop_thumbnail_factory_reread_scripts (factory);
+static void
+gnome_desktop_thumbnail_factory_finalize_scripts (GnomeDesktopThumbnailFactory *factory)
+{
+ if (factory->priv->scripts_hash) {
+ g_hash_table_destroy (factory->priv->scripts_hash);
+ factory->priv->scripts_hash = NULL;
+ }
+
+ if (factory->priv->reread_scheduled != 0) {
+ g_source_remove (factory->priv->reread_scheduled);
+ factory->priv->reread_scheduled = 0;
+ }
- priv->thumbnailers_notify = gconf_client_notify_add (client, "/desktop/gnome/thumbnailers",
- schedule_reread, factory, NULL,
- NULL);
+ if (factory->priv->thumbnailers_notify != 0) {
+ GConfClient *client;
+
+ client = gconf_client_get_default ();
+ gconf_client_notify_remove (client, factory->priv->thumbnailers_notify);
+ factory->priv->thumbnailers_notify = 0;
+ g_object_unref (client);
+ }
+}
+
+
+static char *
+gnome_desktop_thumbnail_factory_get_script (GnomeDesktopThumbnailFactory *factory,
+ const char *mime_type)
+{
+ char *script = NULL;
+
+ if (factory->priv->scripts_hash != NULL) {
+ script = g_hash_table_lookup (factory->priv->scripts_hash, mime_type);
+ if (script)
+ script = g_strdup (script);
+ }
+
+ return script;
+}
+
+#endif
+
+
+static void
+gnome_desktop_thumbnail_factory_finalize (GObject *object)
+{
+ GnomeDesktopThumbnailFactory *factory;
+
+ factory = GNOME_DESKTOP_THUMBNAIL_FACTORY (object);
+
+ gnome_desktop_thumbnail_factory_finalize_scripts (factory);
+
+ if (factory->priv->lock) {
+ g_mutex_free (factory->priv->lock);
+ factory->priv->lock = NULL;
+ }
+
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+
+static void
+gnome_desktop_thumbnail_factory_init (GnomeDesktopThumbnailFactory *factory)
+{
+ factory->priv = GNOME_DESKTOP_THUMBNAIL_FACTORY_GET_PRIVATE (factory);
+ factory->priv->size = GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL;
+ factory->priv->lock = g_mutex_new ();
+
+ gnome_desktop_thumbnail_factory_init_scripts (factory);
- g_object_unref (G_OBJECT (client));
}
static void
@@ -805,11 +1336,7 @@ gnome_desktop_thumbnail_factory_generate_from_script (GnomeDesktopThumbnailFacto
script = NULL;
g_mutex_lock (factory->priv->lock);
- if (factory->priv->scripts_hash != NULL) {
- script = g_hash_table_lookup (factory->priv->scripts_hash, mime_type);
- if (script)
- script = g_strdup (script);
- }
+ script = gnome_desktop_thumbnail_factory_get_script (factory, mime_type);
g_mutex_unlock (factory->priv->lock);
if (script == NULL) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]