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.
This commit is contained in:
Alexander Larsson 2012-01-12 18:11:19 +01:00
parent 84883ccf7c
commit c72a76c754
3 changed files with 199 additions and 3 deletions

View File

@ -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)
{

View File

@ -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,

View File

@ -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);