diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-01-01 01:25:02 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-01-03 13:02:16 -0500 |
commit | ad11933eeef652bfa695c94db71bdd76c7396b2a (patch) | |
tree | 2d34c592139c3fb8de0104875b2602170073c85c | |
parent | 27460826b3b36773d3a6a9d37716544728057174 (diff) | |
download | gtk+-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.c | 143 | ||||
-rw-r--r-- | gdk/gdkcontentproviderimpl.h | 15 |
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__ */ |