[gtk+/wip/otte/clipboard: 53/64] gdk: Add GDK_TYPE_FILE_LIST with serializers



commit 4e07858a76090edad7af7a96a171d8d5b1401bae
Author: Benjamin Otte <otte redhat com>
Date:   Wed Nov 29 09:37:50 2017 +0100

    gdk: Add GDK_TYPE_FILE_LIST with serializers
    
    This is a GSList of GFile and we want it so we can operate with lists of
    files and text/uri-list.
    
    I chose GSList over GList because that's what the GtkFileChooser API
    uses, too.

 gdk/gdkcontentdeserializer.c |   23 ++++++++----
 gdk/gdkcontentformats.c      |   16 ++++++++
 gdk/gdkcontentformats.h      |    6 +++
 gdk/gdkcontentserializer.c   |   83 +++++++++++++++++++++++++++++++++++++-----
 tests/testclipboard2.c       |   27 +++++++++++++-
 5 files changed, 137 insertions(+), 18 deletions(-)
---
diff --git a/gdk/gdkcontentdeserializer.c b/gdk/gdkcontentdeserializer.c
index b9a369f..22f911d 100644
--- a/gdk/gdkcontentdeserializer.c
+++ b/gdk/gdkcontentdeserializer.c
@@ -22,7 +22,6 @@
 #include "gdkcontentdeserializer.h"
 
 #include "gdkcontentformats.h"
-#include "gdkintl.h"
 
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
@@ -532,6 +531,7 @@ file_uri_deserializer_finish (GObject      *source,
   GOutputStream *stream = G_OUTPUT_STREAM (source);
   GError *error = NULL;
   gssize written;
+  GValue *value;
   char *str;
   char **uris;
 
@@ -554,17 +554,21 @@ file_uri_deserializer_finish (GObject      *source,
   uris = g_uri_list_extract_uris (str);
   g_free (str);
 
-  if (uris == NULL || uris[0] == NULL)
+  value = gdk_content_deserializer_get_value (deserializer);
+  if (G_VALUE_HOLDS (value, G_TYPE_FILE))
     {
-      error = g_error_new (G_IO_ERROR, G_IO_ERROR, _("No file given"));
-      gdk_content_deserializer_return_error (deserializer, error);
+      if (uris[0] != NULL)
+        g_value_take_object (value, g_file_new_for_uri (uris[0]));
     }
   else
     {
-      GFile *file = g_file_new_for_uri (uris[0]);
+      GSList *l = NULL;
+      gsize i;
+
+      for (i = 0; uris[i] != NULL; i++)
+        l = g_slist_prepend (l, g_file_new_for_uri (uris[i]));
 
-      g_value_take_object (gdk_content_deserializer_get_value (deserializer), file);
-      gdk_content_deserializer_return_success (deserializer);
+      g_value_take_boxed (value, g_slist_reverse (l));
     }
   g_strfreev (uris);
 }
@@ -640,6 +644,11 @@ init (void)
   g_slist_free (formats);
 
   gdk_content_register_deserializer ("text/uri-list",
+                                     GDK_TYPE_FILE_LIST,
+                                     file_uri_deserializer,
+                                     NULL,
+                                     NULL);
+  gdk_content_register_deserializer ("text/uri-list",
                                      G_TYPE_FILE,
                                      file_uri_deserializer,
                                      NULL,
diff --git a/gdk/gdkcontentformats.c b/gdk/gdkcontentformats.c
index 5e7d5ea..d5d071f 100644
--- a/gdk/gdkcontentformats.c
+++ b/gdk/gdkcontentformats.c
@@ -642,3 +642,19 @@ gdk_content_formats_builder_add_mime_type (GdkContentFormatsBuilder *builder,
   builder->n_mime_types++;
 }
 
+/* G_DEFINE_BOXED wants this */
+typedef gpointer GdkFileList;
+
+static gpointer
+gdk_file_list_copy (gpointer list)
+{
+  return g_slist_copy_deep (list, (GCopyFunc) g_object_ref, NULL);
+}
+
+static void
+gdk_file_list_free (gpointer list)
+{
+  g_slist_free_full (list, g_object_unref);
+}
+
+G_DEFINE_BOXED_TYPE (GdkFileList, gdk_file_list, gdk_file_list_copy, gdk_file_list_free)
diff --git a/gdk/gdkcontentformats.h b/gdk/gdkcontentformats.h
index 1e5f714..58bbb10 100644
--- a/gdk/gdkcontentformats.h
+++ b/gdk/gdkcontentformats.h
@@ -93,6 +93,12 @@ GDK_AVAILABLE_IN_3_94
 void                    gdk_content_formats_builder_add_gtype   (GdkContentFormatsBuilder       *builder,
                                                                  GType                           type);
 
+/* dunno where else to put this */
+#define GDK_TYPE_FILE_LIST (gdk_file_list_get_type ())
+GDK_AVAILABLE_IN_3_94
+GType     gdk_file_list_get_type  (void) G_GNUC_CONST;
+
+
 G_END_DECLS
 
 #endif /* __GTK_CONTENT_FORMATS_H__ */
diff --git a/gdk/gdkcontentserializer.c b/gdk/gdkcontentserializer.c
index eddc8be..6153e82 100644
--- a/gdk/gdkcontentserializer.c
+++ b/gdk/gdkcontentserializer.c
@@ -530,15 +530,39 @@ file_uri_serializer (GdkContentSerializer *serializer)
 {
   GFile *file;
   GString *str;
+  const GValue *value;
   char *uri;
 
   str = g_string_new (NULL);
+  value = gdk_content_serializer_get_value (serializer);
 
-  file = g_value_get_object (gdk_content_serializer_get_value (serializer));
-  uri = g_file_get_uri (file);
-  g_string_append (str, uri);
-  g_free (uri);
-  g_string_append (str, "\r\n");
+  if (G_VALUE_HOLDS (value, G_TYPE_FILE))
+    {
+      file = g_value_get_object (gdk_content_serializer_get_value (serializer));
+      if (file)
+        {
+          uri = g_file_get_uri (file);
+          g_string_append (str, uri);
+          g_free (uri);
+        }
+      else
+        {
+          g_string_append (str, "# GTK does not crash when copying a NULL GFile!");
+        }
+      g_string_append (str, "\r\n");
+    }
+  else if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST))
+    {
+      GSList *l;
+      
+      for (l = g_value_get_boxed (value); l; l = l->next)
+        {
+          uri = g_file_get_uri (l->data);
+          g_string_append (str, uri);
+          g_free (uri);
+          g_string_append (str, "\r\n");
+        }
+    }
 
   g_output_stream_write_all_async (gdk_content_serializer_get_output_stream (serializer),
                                    str->str,
@@ -553,13 +577,42 @@ file_uri_serializer (GdkContentSerializer *serializer)
 static void
 file_text_serializer (GdkContentSerializer *serializer)
 {
-  GFile *file;
+  const GValue *value;
   char *path;
 
-  file = g_value_get_object (gdk_content_serializer_get_value (serializer));
-  path = g_file_get_path (file);
-  if (path == NULL)
-    path = g_file_get_uri (file);
+  value = gdk_content_serializer_get_value (serializer);
+
+  if (G_VALUE_HOLDS (value, G_TYPE_FILE))
+    {
+      GFile *file;
+
+      file = g_value_get_object (value);
+      if (file)
+        {
+          path = g_file_get_path (file);
+          if (path == NULL)
+            path = g_file_get_uri (file);
+        }
+    }
+  else if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST))
+    {
+      GString *str;
+      GSList *l;
+      
+      str = g_string_new (NULL);
+
+      for (l = g_value_get_boxed (value); l; l = l->next)
+        {
+          path = g_file_get_path (l->data);
+          if (path == NULL)
+            path = g_file_get_uri (l->data);
+          g_string_append (str, path);
+          g_free (path);
+          if (l->next)
+            g_string_append (str, " ");
+        }
+      path = g_string_free (str, FALSE);
+    }
 
   g_output_stream_write_all_async (gdk_content_serializer_get_output_stream (serializer),
                                    path,
@@ -637,6 +690,16 @@ init (void)
                                    file_text_serializer,
                                    NULL,
                                    NULL);
+  gdk_content_register_serializer (GDK_TYPE_FILE_LIST,
+                                   "text/uri-list",
+                                   file_uri_serializer,
+                                   NULL,
+                                   NULL);
+  gdk_content_register_serializer (GDK_TYPE_FILE_LIST,
+                                   "text/plain;charset=utf-8",
+                                   file_text_serializer,
+                                   NULL,
+                                   NULL);
 
   gdk_content_register_serializer (G_TYPE_STRING,
                                    "text/plain;charset=utf-8",
diff --git a/tests/testclipboard2.c b/tests/testclipboard2.c
index 4baabf5..abc4751 100644
--- a/tests/testclipboard2.c
+++ b/tests/testclipboard2.c
@@ -102,7 +102,26 @@ visible_child_changed_cb (GtkWidget    *stack,
                                      label);
     }
 }
-                
+
+static GList *
+get_file_list (const char *dir)
+{
+  GFileEnumerator *enumerator;
+  GFile *file;
+  GList *list = NULL;
+  
+  file = g_file_new_for_path (dir);
+  enumerator = g_file_enumerate_children (file, "standard::name", 0, NULL, NULL);
+  g_object_unref (file);
+  if (enumerator == NULL)
+    return NULL;
+
+  while (g_file_enumerator_iterate (enumerator, NULL, &file, NULL, NULL) && file != NULL)
+    list = g_list_prepend (list, g_object_ref (file));
+
+  return g_list_reverse (list);
+}
+
 static void
 format_list_add_row (GtkWidget         *list,
                      const char        *format_name,
@@ -271,6 +290,12 @@ get_button_list (GdkClipboard *clipboard,
                        "home directory");
   g_value_unset (&value);
 
+  g_value_init (&value, GDK_TYPE_FILE_LIST);
+  g_value_take_boxed (&value, get_file_list (g_get_home_dir ()));
+  add_provider_button (box,
+                       gdk_content_provider_new_for_value (&value),
+                       clipboard,
+                       "files in home");
   return box;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]