summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-01-01 01:25:02 -0500
committerMatthias Clasen <mclasen@redhat.com>2020-01-03 13:02:16 -0500
commitad11933eeef652bfa695c94db71bdd76c7396b2a (patch)
tree2d34c592139c3fb8de0104875b2602170073c85c
parent27460826b3b36773d3a6a9d37716544728057174 (diff)
downloadgtk+-ad11933eeef652bfa695c94db71bdd76c7396b2a.tar.gz
Add another callback-based provider
This one can be used in cases where data needs to be served in multiple formats that may not all be covered by content serializers.
-rw-r--r--gdk/gdkcontentproviderimpl.c143
-rw-r--r--gdk/gdkcontentproviderimpl.h15
2 files changed, 155 insertions, 3 deletions
diff --git a/gdk/gdkcontentproviderimpl.c b/gdk/gdkcontentproviderimpl.c
index 5278cd2c86..838c7b72c5 100644
--- a/gdk/gdkcontentproviderimpl.c
+++ b/gdk/gdkcontentproviderimpl.c
@@ -367,3 +367,146 @@ gdk_content_provider_new_with_callback (GType type,
return GDK_CONTENT_PROVIDER (content);
}
+
+#define GDK_TYPE_CONTENT_PROVIDER_CALLBACK2 (gdk_content_provider_callback2_get_type ())
+#define GDK_CONTENT_PROVIDER_CALLBACK2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CONTENT_PROVIDER_CALLBACK2, GdkContentProviderCallback2))
+
+typedef struct _GdkContentProviderCallback2 GdkContentProviderCallback2;
+typedef struct _GdkContentProviderCallback2Class GdkContentProviderCallback2Class;
+
+struct _GdkContentProviderCallback2
+{
+ GdkContentProvider parent;
+
+ GdkContentFormats *formats;
+ GdkContentProviderGetBytesFunc func;
+ gpointer data;
+};
+
+struct _GdkContentProviderCallback2Class
+{
+ GdkContentProviderClass parent_class;
+};
+
+GType gdk_content_provider_callback2_get_type (void) G_GNUC_CONST;
+
+G_DEFINE_TYPE (GdkContentProviderCallback2, gdk_content_provider_callback2, GDK_TYPE_CONTENT_PROVIDER)
+
+static GdkContentFormats *
+gdk_content_provider_callback2_ref_formats (GdkContentProvider *provider)
+{
+ GdkContentProviderCallback2 *callback = GDK_CONTENT_PROVIDER_CALLBACK2 (provider);
+
+ return gdk_content_formats_ref (callback->formats);
+}
+
+static void
+gdk_content_provider_callback2_write_mime_type_done (GObject *stream,
+ GAsyncResult *result,
+ gpointer task)
+{
+ GError *error = NULL;
+
+ if (!g_output_stream_write_all_finish (G_OUTPUT_STREAM (stream), result, NULL, &error))
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, TRUE);
+
+ g_object_unref (task);
+}
+
+static void
+gdk_content_provider_callback2_write_mime_type_async (GdkContentProvider *provider,
+ const char *mime_type,
+ GOutputStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GdkContentProviderCallback2 *content = GDK_CONTENT_PROVIDER_CALLBACK2 (provider);
+ GTask *task;
+ GBytes *bytes;
+
+ task = g_task_new (content, cancellable, callback, user_data);
+ g_task_set_priority (task, io_priority);
+ g_task_set_source_tag (task, gdk_content_provider_callback2_write_mime_type_async);
+
+ if (!gdk_content_formats_contain_mime_type (content->formats, mime_type))
+ {
+ g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Cannot provide contents as ā€œ%sā€"), mime_type);
+ g_object_unref (task);
+ return;
+ }
+
+ bytes = content->func (mime_type, content->data);
+ if (!bytes)
+ {
+ g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Failed to get contents as ā€œ%sā€"), mime_type);
+ g_object_unref (task);
+ return;
+ }
+
+ g_object_set_data_full (G_OBJECT (task), "bytes", bytes, (GDestroyNotify)g_bytes_unref);
+
+ g_output_stream_write_all_async (stream,
+ g_bytes_get_data (bytes, NULL),
+ g_bytes_get_size (bytes),
+ io_priority,
+ cancellable,
+ gdk_content_provider_callback2_write_mime_type_done,
+ task);
+}
+
+static gboolean
+gdk_content_provider_callback2_write_mime_type_finish (GdkContentProvider *provider,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, provider), FALSE);
+ g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_content_provider_callback2_write_mime_type_async, FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+gdk_content_provider_callback2_class_init (GdkContentProviderCallback2Class *class)
+{
+ GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
+
+ provider_class->ref_formats = gdk_content_provider_callback2_ref_formats;
+ provider_class->write_mime_type_async = gdk_content_provider_callback2_write_mime_type_async;
+ provider_class->write_mime_type_finish = gdk_content_provider_callback2_write_mime_type_finish;
+}
+
+static void
+gdk_content_provider_callback2_init (GdkContentProviderCallback2 *content)
+{
+}
+
+/**
+ * gdk_content_provider_new_with_formats:
+ * @formats: formats to advertise
+ * @func: callback to populate a #GValue
+ * @data: data that gets passed to @func
+ *
+ * Create a content provider that provides data that is provided via a callback.
+ *
+ * Returns: a new #GdkContentProvider
+ **/
+GdkContentProvider *
+gdk_content_provider_new_with_formats (GdkContentFormats *formats,
+ GdkContentProviderGetBytesFunc func,
+ gpointer data)
+{
+ GdkContentProviderCallback2 *content;
+
+ content = g_object_new (GDK_TYPE_CONTENT_PROVIDER_CALLBACK2, NULL);
+ content->formats = gdk_content_formats_ref (formats);
+ content->func = func;
+ content->data = data;
+
+ return GDK_CONTENT_PROVIDER (content);
+}
diff --git a/gdk/gdkcontentproviderimpl.h b/gdk/gdkcontentproviderimpl.h
index b98d02bdef..19ac6969e1 100644
--- a/gdk/gdkcontentproviderimpl.h
+++ b/gdk/gdkcontentproviderimpl.h
@@ -39,9 +39,18 @@ typedef void (*GdkContentProviderGetValueFunc) (GValue *value,
gpointer data);
GDK_AVAILABLE_IN_ALL
-GdkContentProvider * gdk_content_provider_new_with_callback (GType type,
- GdkContentProviderGetValueFunc func,
- gpointer data);
+GdkContentProvider * gdk_content_provider_new_with_callback (GType type,
+ GdkContentProviderGetValueFunc func,
+ gpointer data);
+
+typedef GBytes * (*GdkContentProviderGetBytesFunc) (const char *mime_type,
+ gpointer data);
+
+GDK_AVAILABLE_IN_ALL
+GdkContentProvider * gdk_content_provider_new_with_formats (GdkContentFormats *formats,
+ GdkContentProviderGetBytesFunc func,
+ gpointer data);
+
G_END_DECLS
#endif /* __GDK_CONTENT_PROVIDER_IMPL_H__ */