summaryrefslogtreecommitdiff
path: root/gtk/gtkbuilder.c
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2012-01-12 18:11:19 +0100
committerAlexander Larsson <alexl@redhat.com>2012-01-16 13:59:58 +0100
commitc72a76c754e75d9c03db1030f96393fc385c648e (patch)
treef5529a45db44c445ca12bae4a38f2311e679b96e /gtk/gtkbuilder.c
parent84883ccf7c2b51d852787f789f57d100f1dfff15 (diff)
downloadgtk+-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.c193
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;