File glib2-thumbnailer.patch of Package glib2

diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c
index 487f8cc1a..b0e6db728 100644
--- a/gio/glocalfileinfo.c
+++ b/gio/glocalfileinfo.c
@@ -66,6 +66,12 @@
 #include "glib-private.h"
 
 #include "thumbnail-verify.h"
+#ifdef HAVE_DBUS1
+#define FREEDESKTOP_THUMBNAILER
+#include <gio/gio.h>
+#include <gio/gdbusproxy.h>
+#include <glib-object.h>
+#endif /* HAVE_DBUS1 */
 
 #ifdef G_OS_WIN32
 #include <windows.h>
@@ -103,6 +109,16 @@ struct ThumbMD5Context {
 	unsigned char in[64];
 };
 
+#ifdef FREEDESKTOP_THUMBNAILER
+typedef struct
+{
+  GMainLoop *mainloop;
+  guint32 handle;
+  gboolean success;
+  const char *error_message;
+} ThumbnailerState;
+#endif /* FREEDESKTOP_THUMBNAILER */
+
 #ifndef G_OS_WIN32
 
 typedef struct {
@@ -1355,16 +1371,130 @@ get_content_type (const char          *basename,
   
 }
 
+#ifdef FREEDESKTOP_THUMBNAILER
+static void
+thumbnailer_signal_cb (GDBusProxy *proxy,
+                       gchar      *sender_name,
+                       gchar      *signal_name,
+                       GVariant   *parameters,
+                       gpointer    thumbnailer_state)
+{
+  ThumbnailerState *state = (ThumbnailerState *) thumbnailer_state;
+  guint32 signal_handle;
+  const gchar **uris;
+
+
+  if (g_strcmp0 (signal_name, "Error") == 0)
+    {
+      g_variant_get (parameters, "(uasis)", &signal_handle, NULL, NULL, &state->error_message);
+      state->success = FALSE;
+    }
+  else if (g_strcmp0 (signal_name, "Ready") == 0)
+    {
+      g_variant_get (parameters, "(u^as)", &signal_handle, &uris);
+      state->success = TRUE;
+    }
+  else if (g_strcmp0 (signal_name, "Finished") == 0)
+    {
+      g_main_loop_quit (state->mainloop);
+    }
+
+}
+
+static gboolean
+generate_thumbnail(const char *uri, const char *mime_type)
+{
+  GMainContext *thread_context;
+  GDBusConnection *connection;
+  GDBusProxy *proxy;
+  GVariant *result = NULL;
+  GError *error = NULL;
+  ThumbnailerState state;
+  const gchar *uris[2] = { uri, NULL };
+  const gchar *mime_types[2] = { mime_type, NULL };
+
+  thread_context = g_main_context_new ();
+  state.mainloop = g_main_loop_new (thread_context, FALSE);
+  state.success = FALSE;
+
+  connection = g_dbus_connection_new_for_address_sync (
+      g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SESSION, NULL, NULL),
+      G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION | G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
+      NULL,
+      NULL,
+      &error);
+
+  proxy = g_dbus_proxy_new_sync (connection,
+                                 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+                                 NULL,
+                                 "org.freedesktop.thumbnails.Thumbnailer1",
+                                 "/org/freedesktop/thumbnails/Thumbnailer1",
+                                 "org.freedesktop.thumbnails.Thumbnailer1",
+                                 NULL, /* TODO: cancellable */
+                                 &error);
+  if (!proxy)
+    {
+      g_warning ("generate_thumbnail (): g_dbus_proxy_new_sync failed");
+      g_main_loop_unref (state.mainloop);
+      return FALSE;
+    }
+  else
+    g_debug("generate_thumbnail (): connected to D-Bus");
+
+  g_signal_connect (G_OBJECT (proxy), "g-signal",
+                    G_CALLBACK (thumbnailer_signal_cb), &state);
+
+  g_main_context_push_thread_default (thread_context);
+  result = g_dbus_proxy_call_sync (proxy,
+                                  "Queue",
+                                   g_variant_new("(^as^asssu)",
+                                                 uris,
+                                                 mime_types,
+                                                 "normal",
+                                                 "default",
+                                                 0),
+                                   G_DBUS_CALL_FLAGS_NONE,
+                                   -1,
+                                   NULL,
+                                   &error);
+  if (!result || error)
+    {
+      g_warning ("generate_thumbnail (): g_dbus_proxy_call_sync() failed: %s", error->message);
+      return FALSE;
+    }
+  g_variant_get (result, "(u)", &(state.handle));
+  g_variant_unref (result);
+  // block until the loop is terminated in thumbnailer_signal_cb ()
+  g_main_loop_run (state.mainloop);
+  g_object_unref (proxy);
+  g_object_unref (connection);
+  g_main_loop_unref (state.mainloop);
+  g_main_context_pop_thread_default (thread_context);
+  g_main_context_unref (thread_context);
+
+  if (state.success)
+    {
+      g_debug ("generate_thumbnail (): Thumbnail generated for %s", uris[0]);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+#endif /* FREEDESKTOP_THUMBNAILER */
+
+
 /* @stat_buf is the pre-calculated result of stat(path), or %NULL if that failed. */
 static void
 get_thumbnail_attributes (const char     *path,
                           GFileInfo      *info,
-                          const GLocalFileStat *stat_buf)
+                          const GLocalFileStat *stat_buf,
+                          gboolean        generate)
 {
   GChecksum *checksum;
   char *uri;
   char *filename;
   char *basename;
+  const char *content_type;
 
   uri = g_filename_to_uri (path, NULL, NULL);
 
@@ -1383,6 +1513,7 @@ get_thumbnail_attributes (const char     *path,
       _g_file_info_set_attribute_byte_string_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH, filename);
       _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID,
                                                 thumbnail_verify (filename, uri, stat_buf));
+      generate = FALSE;
     }
   else
     {
@@ -1396,6 +1527,7 @@ get_thumbnail_attributes (const char     *path,
           _g_file_info_set_attribute_byte_string_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH, filename);
           _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID,
                                                     thumbnail_verify (filename, uri, stat_buf));
+          generate = FALSE;
         }
       else
         {
@@ -1411,9 +1543,32 @@ get_thumbnail_attributes (const char     *path,
               _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED, TRUE);
               _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID,
                                                         thumbnail_verify (filename, uri, stat_buf));
+              generate = FALSE;
             }
         }
     }
+
+  if (generate)
+    {
+#ifdef FREEDESKTOP_THUMBNAILER
+      content_type = g_file_info_get_content_type (info);
+      if (content_type)
+        {
+          g_debug ("invoking Freedesktop Thumbnailer for %s (%s)", uri, content_type);
+          if(generate_thumbnail (uri, content_type))
+            {
+              /* Now that the thumbnail is generated, find it. */
+              get_thumbnail_attributes (path, info, stat_buf, FALSE);
+            }
+          else
+            {
+              _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED, TRUE);
+              _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID, FALSE);
+            }
+         }
+#endif /* FREEDESKTOP_THUMBNAILER */
+    }
+
   g_free (basename);
   g_free (filename);
   g_free (uri);
@@ -1767,6 +1922,18 @@ _g_local_file_info_get (const char             *basename,
 
   info = g_file_info_new ();
 
+  /* Thumbnail generation requires a content-type.
+   * TODO: implement g_file_attribute_matcher_add () in gfileinfo.c */
+  if (_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH)
+      && !_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE))
+    {
+      char *attributes = g_file_attribute_matcher_to_string (attribute_matcher);
+      char *_attributes = g_strdup_printf ("%s,standard::content-type", attributes);
+      attribute_matcher = g_file_attribute_matcher_new (_attributes);
+      g_free (attributes);
+      g_free (_attributes);
+    }
+
   /* Make sure we don't set any unwanted attributes */
   g_file_info_set_attribute_mask (info, attribute_matcher);
   
@@ -1901,7 +2068,9 @@ _g_local_file_info_get (const char             *basename,
       _g_file_attribute_matcher_matches_id (attribute_matcher,
 					    G_FILE_ATTRIBUTE_ID_STANDARD_ICON) ||
       _g_file_attribute_matcher_matches_id (attribute_matcher,
-					    G_FILE_ATTRIBUTE_ID_STANDARD_SYMBOLIC_ICON))
+					    G_FILE_ATTRIBUTE_ID_STANDARD_SYMBOLIC_ICON) ||
+      _g_file_attribute_matcher_matches_id (attribute_matcher,
+              G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH))
     {
       char *content_type = get_content_type (basename, path, stat_ok ? &statbuf : NULL, is_symlink, symlink_broken, flags, FALSE);
 
@@ -2018,9 +2187,9 @@ _g_local_file_info_get (const char             *basename,
                                             G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED))
     {
       if (stat_ok)
-          get_thumbnail_attributes (path, info, &statbuf);
+          get_thumbnail_attributes (path, info, &statbuf, TRUE);
       else
-          get_thumbnail_attributes (path, info, NULL);
+          get_thumbnail_attributes (path, info, NULL, TRUE);
     }
 
   vfs = g_vfs_get_default ();
openSUSE Build Service is sponsored by