diff options
author | Alexander Larsson <alexl@redhat.com> | 2012-01-12 18:11:19 +0100 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2012-01-16 13:59:58 +0100 |
commit | c72a76c754e75d9c03db1030f96393fc385c648e (patch) | |
tree | f5529a45db44c445ca12bae4a38f2311e679b96e /gtk/gtkbuilder.c | |
parent | 84883ccf7c2b51d852787f789f57d100f1dfff15 (diff) | |
download | gtk+-c72a76c754e75d9c03db1030f96393fc385c648e.tar.gz |
Add resource support for GtkBuilder
There are new calls to load ui files from resources, and
you can now read pixbufs by using relative paths in a ui
file read from a resource, or by using absolute resource:/// uris.
Diffstat (limited to 'gtk/gtkbuilder.c')
-rw-r--r-- | gtk/gtkbuilder.c | 193 |
1 files changed, 190 insertions, 3 deletions
diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c index 273285fb3c..f4904fa9b2 100644 --- a/gtk/gtkbuilder.c +++ b/gtk/gtkbuilder.c @@ -296,6 +296,7 @@ struct _GtkBuilderPrivate GSList *delayed_properties; GSList *signals; gchar *filename; + gchar *resource_prefix; }; G_DEFINE_TYPE (GtkBuilder, gtk_builder, G_TYPE_OBJECT) @@ -356,6 +357,7 @@ gtk_builder_finalize (GObject *object) g_free (priv->domain); g_free (priv->filename); + g_free (priv->resource_prefix); g_hash_table_destroy (priv->objects); @@ -913,7 +915,9 @@ gtk_builder_add_from_file (GtkBuilder *builder, } g_free (builder->priv->filename); + g_free (builder->priv->resource_prefix); builder->priv->filename = g_strdup (filename); + builder->priv->resource_prefix = NULL; _gtk_builder_parser_parse_buffer (builder, filename, buffer, length, @@ -980,7 +984,9 @@ gtk_builder_add_objects_from_file (GtkBuilder *builder, } g_free (builder->priv->filename); + g_free (builder->priv->resource_prefix); builder->priv->filename = g_strdup (filename); + builder->priv->resource_prefix = NULL; _gtk_builder_parser_parse_buffer (builder, filename, buffer, length, @@ -999,6 +1005,157 @@ gtk_builder_add_objects_from_file (GtkBuilder *builder, } /** + * gtk_builder_add_from_resource: + * @builder: a #GtkBuilder + * @resource_path: the path of the resource file to parse + * @error: (allow-none): return location for an error, or %NULL + * + * Parses a resource file containing a <link linkend="BUILDER-UI">GtkBuilder + * UI definition</link> and merges it with the current contents of @builder. + * + * Upon errors 0 will be returned and @error will be assigned a + * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_RESOURCE_ERROR + * domain. + * + * Returns: A positive value on success, 0 if an error occurred + * + * Since: 3.4 + **/ +guint +gtk_builder_add_from_resource (GtkBuilder *builder, + const gchar *resource_path, + GError **error) +{ + GError *tmp_error; + GBytes *data; + char *filename_for_errors; + char *slash; + + g_return_val_if_fail (GTK_IS_BUILDER (builder), 0); + g_return_val_if_fail (resource_path != NULL, 0); + g_return_val_if_fail (error == NULL || *error == NULL, 0); + + tmp_error = NULL; + + data = g_resources_lookup_data (resource_path, 0, &tmp_error); + if (data == NULL) + { + g_propagate_error (error, tmp_error); + return 0; + } + + g_free (builder->priv->filename); + g_free (builder->priv->resource_prefix); + builder->priv->filename = g_strdup ("."); + + slash = strrchr (resource_path, '/'); + if (slash != NULL) + builder->priv->resource_prefix = + g_strndup (resource_path, slash - resource_path + 1); + else + builder->priv->resource_prefix = + g_strdup ("/"); + + filename_for_errors = g_strconcat ("<resource>", resource_path, NULL); + + _gtk_builder_parser_parse_buffer (builder, filename_for_errors, + g_bytes_get_data (data, NULL), g_bytes_get_size (data), + NULL, + &tmp_error); + + g_free (filename_for_errors); + g_bytes_unref (data); + + if (tmp_error != NULL) + { + g_propagate_error (error, tmp_error); + return 0; + } + + return 1; +} + +/** + * gtk_builder_add_objects_from_resource: + * @builder: a #GtkBuilder + * @resource_path: the path of the resource file to parse + * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build + * @error: (allow-none): return location for an error, or %NULL + * + * Parses a resource file containing a <link linkend="BUILDER-UI">GtkBuilder + * UI definition</link> building only the requested objects and merges + * them with the current contents of @builder. + * + * Upon errors 0 will be returned and @error will be assigned a + * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_RESOURCE_ERROR + * domain. + * + * <note><para> + * If you are adding an object that depends on an object that is not + * its child (for instance a #GtkTreeView that depends on its + * #GtkTreeModel), you have to explicitely list all of them in @object_ids. + * </para></note> + * + * Returns: A positive value on success, 0 if an error occurred + * + * Since: 3.4 + **/ +guint +gtk_builder_add_objects_from_resource (GtkBuilder *builder, + const gchar *resource_path, + gchar **object_ids, + GError **error) +{ + GError *tmp_error; + GBytes *data; + char *filename_for_errors; + char *slash; + + g_return_val_if_fail (GTK_IS_BUILDER (builder), 0); + g_return_val_if_fail (resource_path != NULL, 0); + g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0); + g_return_val_if_fail (error == NULL || *error == NULL, 0); + + tmp_error = NULL; + + data = g_resources_lookup_data (resource_path, 0, &tmp_error); + if (data == NULL) + { + g_propagate_error (error, tmp_error); + return 0; + } + + g_free (builder->priv->filename); + g_free (builder->priv->resource_prefix); + builder->priv->filename = g_strdup ("."); + + slash = strrchr (resource_path, '/'); + if (slash != NULL) + builder->priv->resource_prefix = + g_strndup (resource_path, slash - resource_path + 1); + else + builder->priv->resource_prefix = + g_strdup ("/"); + + filename_for_errors = g_strconcat ("<resource>", resource_path, NULL); + + _gtk_builder_parser_parse_buffer (builder, filename_for_errors, + g_bytes_get_data (data, NULL), g_bytes_get_size (data), + object_ids, + &tmp_error); + g_free (filename_for_errors); + g_bytes_unref (data); + + if (tmp_error != NULL) + { + g_propagate_error (error, tmp_error); + return 0; + } + + return 1; +} + +/** * gtk_builder_add_from_string: * @builder: a #GtkBuilder * @buffer: the string to parse @@ -1030,7 +1187,9 @@ gtk_builder_add_from_string (GtkBuilder *builder, tmp_error = NULL; g_free (builder->priv->filename); + g_free (builder->priv->resource_prefix); builder->priv->filename = g_strdup ("."); + builder->priv->resource_prefix = NULL; _gtk_builder_parser_parse_buffer (builder, "<input>", buffer, length, @@ -1087,7 +1246,9 @@ gtk_builder_add_objects_from_string (GtkBuilder *builder, tmp_error = NULL; g_free (builder->priv->filename); + g_free (builder->priv->resource_prefix); builder->priv->filename = g_strdup ("."); + builder->priv->resource_prefix = NULL; _gtk_builder_parser_parse_buffer (builder, "<input>", buffer, length, @@ -1655,7 +1816,7 @@ gtk_builder_value_from_string_type (GtkBuilder *builder, { gchar *filename; GError *tmp_error = NULL; - GdkPixbuf *pixbuf; + GdkPixbuf *pixbuf = NULL; if (gtk_builder_get_object (builder, string)) { @@ -1668,8 +1829,21 @@ gtk_builder_value_from_string_type (GtkBuilder *builder, return FALSE; } - filename = _gtk_builder_get_absolute_filename (builder, string); - pixbuf = gdk_pixbuf_new_from_file (filename, &tmp_error); + filename = _gtk_builder_get_resource_path (builder, string); + if (filename != NULL) + { + GInputStream *stream = g_resources_open_stream (filename, 0, &tmp_error); + if (stream != NULL) + { + pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &tmp_error); + g_object_unref (stream); + } + } + else + { + filename = _gtk_builder_get_absolute_filename (builder, string); + pixbuf = gdk_pixbuf_new_from_file (filename, &tmp_error); + } if (pixbuf == NULL) { @@ -1899,6 +2073,19 @@ gtk_builder_error_quark (void) } gchar * +_gtk_builder_get_resource_path (GtkBuilder *builder, const gchar *string) +{ + if (g_str_has_prefix (string, "resource:///")) + return g_uri_unescape_string (string + 11, "/"); + + if (g_path_is_absolute (string) || + builder->priv->resource_prefix == NULL) + return NULL; + + return g_build_path ("/", builder->priv->resource_prefix, string, NULL); +} + +gchar * _gtk_builder_get_absolute_filename (GtkBuilder *builder, const gchar *string) { gchar *filename; |