Commit c72a76c7 authored by Alexander Larsson's avatar Alexander Larsson

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.
parent 84883ccf
......@@ -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,
......@@ -998,6 +1004,157 @@ gtk_builder_add_objects_from_file (GtkBuilder *builder,
return 1;
}
/**
* 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
......@@ -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)
{
......@@ -1898,6 +2072,19 @@ gtk_builder_error_quark (void)
return g_quark_from_static_string ("gtk-builder-error-quark");
}
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)
{
......
......@@ -119,6 +119,9 @@ GtkBuilder* gtk_builder_new (void);
guint gtk_builder_add_from_file (GtkBuilder *builder,
const gchar *filename,
GError **error);
guint gtk_builder_add_from_resource (GtkBuilder *builder,
const gchar *resource_path,
GError **error);
guint gtk_builder_add_from_string (GtkBuilder *builder,
const gchar *buffer,
gsize length,
......@@ -127,6 +130,10 @@ guint gtk_builder_add_objects_from_file (GtkBuilder *builder,
const gchar *filename,
gchar **object_ids,
GError **error);
guint gtk_builder_add_objects_from_resource(GtkBuilder *builder,
const gchar *resource_path,
gchar **object_ids,
GError **error);
guint gtk_builder_add_objects_from_string (GtkBuilder *builder,
const gchar *buffer,
gsize length,
......
......@@ -149,6 +149,8 @@ gboolean _gtk_builder_flags_from_string (GType type,
gchar * _gtk_builder_parser_translate (const gchar *domain,
const gchar *context,
const gchar *text);
gchar * _gtk_builder_get_resource_path (GtkBuilder *builder,
const gchar *string);
gchar * _gtk_builder_get_absolute_filename (GtkBuilder *builder,
const gchar *string);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment