*/
#include <config.h>
-#include <ctype.h> /* tolower, toupper */
#include <errno.h> /* errno */
#include <stdlib.h> /* strtol, strtoul */
#include <string.h> /* strlen */
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtktypebuiltins.h"
+#include "gtkwindow.h"
+#include "gtkicontheme.h"
+#include "gtkstock.h"
#include "gtkalias.h"
static void gtk_builder_class_init (GtkBuilderClass *klass);
guint prop_id,
GValue *value,
GParamSpec *pspec);
-static GType gtk_builder_real_get_type_from_name (GtkBuilder *builder,
- const char *type_name);
-static gint _gtk_builder_enum_from_string (GType type, const char *string);
+static GType gtk_builder_real_get_type_from_name (GtkBuilder *builder,
+ const gchar *type_name);
+static gboolean _gtk_builder_enum_from_string (GType type,
+ const gchar *string,
+ gint *enum_value,
+ GError **error);
enum {
{
gchar *domain;
GHashTable *objects;
- GHashTable *delayed_properties;
+ GSList *delayed_properties;
GSList *signals;
- gchar *current_toplevel;
+ gchar *filename;
};
G_DEFINE_TYPE (GtkBuilder, gtk_builder, G_TYPE_OBJECT)
klass->get_type_from_name = gtk_builder_real_get_type_from_name;
+ /**
+ * GtkBuilder:translation-domain:
+ *
+ * The translation domain used when translating property values that
+ * have been marked as translatable in interface descriptions.
+ * If the translation domain is %NULL, #GtkBuilder uses gettext(),
+ * otherwise dgettext().
+ *
+ * Since: 2.12
+ */
g_object_class_install_property (gobject_class,
PROP_TRANSLATION_DOMAIN,
g_param_spec_string ("translation-domain",
GtkBuilderPrivate);
builder->priv->domain = NULL;
builder->priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, NULL);
- builder->priv->delayed_properties = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free, NULL);
+ g_free, g_object_unref);
}
static void
gtk_builder_finalize (GObject *object)
{
- GtkBuilder *builder = GTK_BUILDER (object);
+ GtkBuilderPrivate *priv = GTK_BUILDER (object)->priv;
- g_free (builder->priv->domain);
+ g_free (priv->domain);
+ g_free (priv->filename);
+
+ g_hash_table_destroy (priv->objects);
- g_free (builder->priv->current_toplevel);
- g_hash_table_destroy (builder->priv->delayed_properties);
- builder->priv->delayed_properties = NULL;
- g_slist_foreach (builder->priv->signals, (GFunc)_free_signal_info, NULL);
- g_slist_free (builder->priv->signals);
- g_hash_table_destroy (builder->priv->objects);
+ g_slist_foreach (priv->signals, (GFunc) _free_signal_info, NULL);
+ g_slist_free (priv->signals);
+
+ G_OBJECT_CLASS (gtk_builder_parent_class)->finalize (object);
}
static void
{
c = name[i];
/* skip if uppercase, first or previous is uppercase */
- if ((c == toupper (c) &&
- i > 0 && name[i-1] != toupper (name[i-1])) ||
- (i > 2 && name[i] == toupper (name[i]) &&
- name[i-1] == toupper (name[i-1]) &&
- name[i-2] == toupper (name[i-2])))
+ if ((c == g_ascii_toupper (c) &&
+ i > 0 && name[i-1] != g_ascii_toupper (name[i-1])) ||
+ (i > 2 && name[i] == g_ascii_toupper (name[i]) &&
+ name[i-1] == g_ascii_toupper (name[i-1]) &&
+ name[i-2] == g_ascii_toupper (name[i-2])))
g_string_append_c (symbol_name, '_');
- g_string_append_c (symbol_name, tolower (c));
+ g_string_append_c (symbol_name, g_ascii_tolower (c));
}
g_string_append (symbol_name, "_get_type");
*/
static GType
-gtk_builder_real_get_type_from_name (GtkBuilder *builder, const char *type_name)
+gtk_builder_real_get_type_from_name (GtkBuilder *builder,
+ const gchar *type_name)
{
GType gtype;
GParamSpec *pspec;
GObjectClass *oclass;
DelayedProperty *property;
-
+ GError *error = NULL;
+
oclass = g_type_class_ref (object_type);
g_assert (oclass != NULL);
prop->name);
if (!pspec)
{
- g_warning ("Unknown property: %s.%s\n",
+ g_warning ("Unknown property: %s.%s",
g_type_name (object_type), prop->name);
continue;
}
parameter.name = prop->name;
- if (G_IS_PARAM_SPEC_OBJECT (pspec))
+ if (G_IS_PARAM_SPEC_OBJECT (pspec) &&
+ (G_PARAM_SPEC_VALUE_TYPE (pspec) != GDK_TYPE_PIXBUF))
{
if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
{
object = gtk_builder_get_object (builder, prop->data);
if (!object)
{
- g_warning ("failed to get constuct only property %s of %s "
- "with value `%s'",
+ g_warning ("Failed to get constuct only property "
+ "%s of %s with value `%s'",
prop->name, object_name, prop->data);
continue;
}
g_value_init (¶meter.value, G_OBJECT_TYPE (object));
- g_value_set_object (¶meter.value, g_object_ref (object));
+ g_value_set_object (¶meter.value, object);
}
else
{
- GSList *delayed_properties;
-
- delayed_properties = g_hash_table_lookup (builder->priv->delayed_properties,
- builder->priv->current_toplevel);
property = g_slice_new (DelayedProperty);
property->object = g_strdup (object_name);
property->name = g_strdup (prop->name);
property->value = g_strdup (prop->data);
- delayed_properties = g_slist_prepend (delayed_properties, property);
- g_hash_table_insert (builder->priv->delayed_properties,
- g_strdup (builder->priv->current_toplevel),
- delayed_properties);
+ builder->priv->delayed_properties =
+ g_slist_prepend (builder->priv->delayed_properties, property);
+
continue;
}
}
- else if (!gtk_builder_value_from_string (pspec, prop->data, ¶meter.value))
+ else if (!gtk_builder_value_from_string (builder, pspec,
+ prop->data, ¶meter.value, &error))
{
- g_warning ("failed to set property %s.%s to %s",
- g_type_name (object_type), prop->name, prop->data);
+ g_warning ("Failed to set property %s.%s to %s: %s",
+ g_type_name (object_type), prop->name, prop->data,
+ error->message);
+ g_error_free (error);
+ error = NULL;
continue;
}
static GObject *
gtk_builder_get_internal_child (GtkBuilder *builder,
ObjectInfo *info,
- const gchar *childname)
+ const gchar *childname,
+ GError **error)
{
GObject *obj = NULL;
};
if (!obj)
- g_error ("Unknown internal child: %s\n", childname);
-
+ {
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_VALUE,
+ "Unknown internal child: %s", childname);
+ }
return obj;
}
GObject *
_gtk_builder_construct (GtkBuilder *builder,
- ObjectInfo *info)
+ ObjectInfo *info,
+ GError **error)
{
GArray *parameters, *construct_parameters;
GType object_type;
g_assert (info->class_name != NULL);
object_type = gtk_builder_get_type_from_name (builder, info->class_name);
if (object_type == G_TYPE_INVALID)
- g_error ("Invalid type: %s", info->class_name);
+ {
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_VALUE,
+ "Invalid object type `%s'",
+ info->class_name);
+ return NULL;
+ }
gtk_builder_get_parameters (builder, object_type,
info->id,
constructor = gtk_builder_get_object (builder, info->constructor);
if (constructor == NULL)
- g_error ("Unknown constructor for %s: %s\n", info->id,
- info->constructor);
-
+ {
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_VALUE,
+ "Unknown object constructor for %s: %s",
+ info->id,
+ info->constructor);
+ g_array_free (parameters, TRUE);
+ g_array_free (construct_parameters, TRUE);
+ return NULL;
+ }
obj = gtk_buildable_construct_child (GTK_BUILDABLE (constructor),
builder,
info->id);
g_assert (obj != NULL);
if (construct_parameters->len)
g_warning ("Can't pass in construct-only parameters to %s", info->id);
-
}
else if (info->parent && ((ChildInfo*)info->parent)->internal_child != NULL)
{
gchar *childname = ((ChildInfo*)info->parent)->internal_child;
- obj = gtk_builder_get_internal_child (builder, info, childname);
+ obj = gtk_builder_get_internal_child (builder, info, childname, error);
+ if (!obj)
+ {
+ g_array_free (parameters, TRUE);
+ g_array_free (construct_parameters, TRUE);
+ return NULL;
+ }
if (construct_parameters->len)
g_warning ("Can't pass in construct-only parameters to %s", childname);
+ g_object_ref (obj);
}
else
{
construct_parameters->len,
(GParameter *)construct_parameters->data);
+ /* No matter what, make sure we have a reference.
+ *
+ * If it's an initially unowned object, sink it.
+ * If it's not initially unowned then we have the reference already.
+ *
+ * In the case that this is a window it will be sunk already and
+ * this is effectively a call to g_object_ref(). That's what
+ * we want.
+ */
+ if (G_IS_INITIALLY_UNOWNED (obj))
+ g_object_ref_sink (obj);
+
GTK_NOTE (BUILDER,
g_print ("created %s of type %s\n", info->id, info->class_name));
g_strdup (info->id),
g_free);
- if (!info->parent)
- {
- g_free (builder->priv->current_toplevel);
- builder->priv->current_toplevel = g_strdup (info->id);
- }
+ /* we already own a reference to obj. put it in the hash table. */
g_hash_table_insert (builder->priv->objects, g_strdup (info->id), obj);
- builder->priv->signals = g_slist_concat (builder->priv->signals,
- g_slist_copy (info->signals));
return obj;
}
if (!child_info->parent)
{
- g_warning ("%s: Not adding, No parent\n",
+ g_warning ("%s: Not adding, No parent",
gtk_buildable_get_name (GTK_BUILDABLE (object)));
return;
}
child_info->added = TRUE;
}
+void
+_gtk_builder_add_signals (GtkBuilder *builder,
+ GSList *signals)
+{
+ builder->priv->signals = g_slist_concat (builder->priv->signals,
+ g_slist_copy (signals));
+}
+
static void
-apply_delayed_properties (const gchar *window_name,
- GSList *props,
- GtkBuilder *builder)
+gtk_builder_apply_delayed_properties (GtkBuilder *builder)
{
- GSList *l;
+ GSList *l, *props;
DelayedProperty *property;
GObject *object;
GType object_type;
GObjectClass *oclass;
GParamSpec *pspec;
- g_assert (props != NULL);
- props = g_slist_reverse (props);
+ /* take the list over from the builder->priv.
+ *
+ * g_slist_reverse does not copy the list, so the list now
+ * belongs to us (and we free it at the end of this function).
+ */
+ props = g_slist_reverse (builder->priv->delayed_properties);
+ builder->priv->delayed_properties = NULL;
+
for (l = props; l; l = l->next)
{
property = (DelayedProperty*)l->data;
pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass),
property->name);
if (!pspec)
- g_warning ("Unknown property: %s.%s\n", g_type_name (object_type),
+ g_warning ("Unknown property: %s.%s", g_type_name (object_type),
property->name);
else
{
obj = g_hash_table_lookup (builder->priv->objects, property->value);
if (!obj)
- g_warning ("No object called: %s\n", property->object);
+ g_warning ("No object called: %s", property->value);
else
g_object_set (object, property->name, obj, NULL);
}
}
void
-_gtk_builder_finish (GtkBuilder *builder)
+_gtk_builder_finish (GtkBuilder *builder)
{
- if (builder->priv->delayed_properties)
- g_hash_table_foreach (builder->priv->delayed_properties,
- (GHFunc)apply_delayed_properties, builder);
+ gtk_builder_apply_delayed_properties (builder);
}
/**
*
* Creates a new builder object.
*
- * Return value: a new builder object.
+ * Return value: a new #GtkBuilder object
*
* Since: 2.12
**/
* gtk_builder_add_from_file:
* @builder: a #GtkBuilder
* @filename: the name of the file to parse
- * @error: return location for an error
+ * @error: return location for an error, or %NULL
*
- * Parses a string containing a <link linkend="BUILDER-UI">GtkBuilder UI definition</link> and
- * merges it with the current contents of @builder.
+ * Parses a file containing a <link linkend="BUILDER-UI">GtkBuilder
+ * UI definition</link> and merges it with the current contents of @builder.
*
* Returns: A positive value on success, 0 if an error occurred
*
const gchar *filename,
GError **error)
{
- char *buffer;
+ gchar *buffer;
gsize length;
GError *tmp_error;
g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
g_return_val_if_fail (filename != NULL, 0);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
tmp_error = NULL;
return 0;
}
+ g_free (builder->priv->filename);
+ builder->priv->filename = g_strdup (filename);
+
_gtk_builder_parser_parse_buffer (builder, filename,
buffer, length,
&tmp_error);
+ g_free (buffer);
+
if (tmp_error != NULL)
{
g_propagate_error (error, tmp_error);
return 0;
}
- g_free (buffer);
-
return 1;
}
* @builder: a #GtkBuilder
* @buffer: the string to parse
* @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
- * @error: return location for an error
+ * @error: return location for an error, or %NULL
*
- * Parses a file containing a <link linkend="BUILDER-UI">GtkBuilder UI definition</link> and
- * merges it with the current contents of @builder.
+ * Parses a string containing a <link linkend="BUILDER-UI">GtkBuilder
+ * UI definition</link> and merges it with the current contents of @builder.
*
* Returns: A positive value on success, 0 if an error occurred
*
g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
g_return_val_if_fail (buffer != NULL, 0);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
tmp_error = NULL;
+ g_free (builder->priv->filename);
+ builder->priv->filename = g_strdup (".");
+
_gtk_builder_parser_parse_buffer (builder, "<input>",
buffer, length,
&tmp_error);
* @builder: a #GtkBuilder
* @name: name of object to get
*
- * Gets the object named @name.
+ * Gets the object named @name. Note that this function does not
+ * increment the reference count of the returned object.
*
* Return value: the object named @name or %NULL if it could not be
- * found in the object tree
+ * found in the object tree.
*
* Since: 2.12
**/
}
static void
-object_add_to_list (gchar *object_id,
- GObject *object,
- GSList **list)
+object_add_to_list (gchar *object_id,
+ GObject *object,
+ GSList **list)
{
*list = g_slist_prepend (*list, object);
}
* gtk_builder_get_objects:
* @builder: a #GtkBuilder
*
- * Gets all objects that have been constructed by @builder.
+ * Gets all objects that have been constructed by @builder. Note that
+ * this function does not increment the reference counts of the returned
+ * objects.
*
* Return value: a newly-allocated #GSList containing all the objects
- * constructed by the #GtkBuilder instance
+ * constructed by the #GtkBuilder instance. It should be freed by
+ * g_slist_free()
*
* Since: 2.12
**/
* @builder: a #GtkBuilder
* @domain: the translation domain or %NULL
*
- * Sets the translation domain and uses dgettext() for translating the
- * property values marked as translatable from an interface description.
- * You can also pass in %NULL to this method to use gettext() instead of
- * dgettext().
+ * Sets the translation domain of @builder.
+ * See #GtkBuilder:translation-domain.
*
* Since: 2.12
**/
* gtk_builder_get_translation_domain:
* @builder: a #GtkBuilder
*
- * Gets the translation domain.
+ * Gets the translation domain of @builder.
*
* Return value: the translation domain. This string is owned
* by the builder object and must not be modified or freed.
if (!g_module_symbol (args->module, handler_name, (gpointer)&func))
{
- g_warning ("could not find signal handler '%s'", handler_name);
+ g_warning ("Could not find signal handler '%s'", handler_name);
return;
}
* @user_data: a pointer to a structure sent in as user data to all signals
*
* This method is a simpler variation of gtk_builder_connect_signals_full().
- * It uses #GModule's introspective features (by opening the module %NULL) to
- * look at the application's symbol table. From here it tries to match
+ * It uses #GModule's introspective features (by opening the module %NULL)
+ * to look at the application's symbol table. From here it tries to match
* the signal handler names given in the interface description with
* symbols in the application and connects the signals.
*
* Note that this function will not work correctly if #GModule is not
* supported on the platform.
*
+ * When compiling applications for Windows, you must declare signal callbacks
+ * with #G_MODULE_EXPORT, or they will not be put in the symbol table.
+ * On Linux and Unices, this is not necessary; applications should instead
+ * be compiled with the -Wl,--export-dynamic CFLAGS, and linked against
+ * gmodule-export-2.0.
+ *
* Since: 2.12
**/
void
g_return_if_fail (GTK_IS_BUILDER (builder));
if (!g_module_supported ())
- g_error ("gtk_builder_connect_signals requires working GModule");
+ g_error ("gtk_builder_connect_signals() requires working GModule");
args = g_slice_new0 (connect_args);
args->module = g_module_open (NULL, G_MODULE_BIND_LAZY);
/**
* GtkBuilderConnectFunc:
* @builder: a #GtkBuilder
- * @object: a GObject subclass to connect a signal to
+ * @object: object to connect a signal to
* @signal_name: name of the signal
* @handler_name: name of the handler
- * @connect_object: GObject, if non-%NULL, use g_signal_connect_object.
+ * @connect_object: a #GObject, if non-%NULL, use g_signal_connect_object()
* @flags: #GConnectFlags to use
* @user_data: user data
*
/**
* gtk_builder_connect_signals_full:
* @builder: a #GtkBuilder
- * @func: the function used to connect the signals.
- * @user_data: arbitrary data that will be passed to the connection function.
+ * @func: the function used to connect the signals
+ * @user_data: arbitrary data that will be passed to the connection function
*
* This function can be thought of the interpreted language binding
- * version of gtk_builder_signal_autoconnect(), except that it does not
- * require gmodule to function correctly.
+ * version of gtk_builder_connect_signals(), except that it does not
+ * require GModule to function correctly.
*
* Since: 2.12
*/
connect_object = g_hash_table_lookup (builder->priv->objects,
signal->connect_object_name);
if (!connect_object)
- g_warning ("could not lookup object %s on signal %s of object %s",
+ g_warning ("Could not lookup object %s on signal %s of object %s",
signal->connect_object_name, signal->name,
signal->object_name);
}
}
/**
- * gtk_builder_value_from_string
- * @pspec: the GParamSpec for the property
- * @string: the string representation of the value.
- * @value: the GValue to store the result in.
+ * gtk_builder_value_from_string:
+ * @builder: a #GtkBuilder
+ * @pspec: the #GParamSpec for the property
+ * @string: the string representation of the value
+ * @value: the #GValue to store the result in
+ * @error: return location for an error, or %NULL
*
- * This function demarshals a value from a string. This function
+ * This function demarshals a value from a string. This function
* calls g_value_init() on the @value argument, so it need not be
* initialised beforehand.
*
* This function can handle char, uchar, boolean, int, uint, long,
- * ulong, enum, flags, float, double, string, GdkColor and
- * GtkAdjustment type values. Support for GtkWidget type values is
+ * ulong, enum, flags, float, double, string, #GdkColor and
+ * #GtkAdjustment type values. Support for #GtkWidget type values is
* still to come.
*
- * Returns: %TRUE on success.
+ * Returns: %TRUE on success
*
* Since: 2.12
*/
gboolean
-gtk_builder_value_from_string (GParamSpec *pspec,
- const gchar *string,
- GValue *value)
+gtk_builder_value_from_string (GtkBuilder *builder,
+ GParamSpec *pspec,
+ const gchar *string,
+ GValue *value,
+ GError **error)
{
+ g_return_val_if_fail (GTK_IS_BUILDER (builder), FALSE);
+ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
+ g_return_val_if_fail (string != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
/*
* GParamSpecUnichar has the internal type G_TYPE_UINT,
* so we cannot handle this in the switch, do it separately
return TRUE;
}
- return gtk_builder_value_from_string_type (G_PARAM_SPEC_VALUE_TYPE (pspec),
- string, value);
+ return gtk_builder_value_from_string_type (builder,
+ G_PARAM_SPEC_VALUE_TYPE (pspec),
+ string, value, error);
}
/**
- * gtk_builder_value_from_string_type
- * @type: the GType of the value
- * @string: the string representation of the value.
- * @value: the GValue to store the result in.
+ * gtk_builder_value_from_string_type:
+ * @builder: a #GtkBuilder
+ * @type: the #GType of the value
+ * @string: the string representation of the value
+ * @value: the #GValue to store the result in
+ * @error: return location for an error, or %NULL
*
- * Like gtk_builder_value_from_string(), but takes a #GType instead of #GParamSpec.
+ * Like gtk_builder_value_from_string(), this function demarshals
+ * a value from a string, but takes a #GType instead of #GParamSpec.
+ * This function calls g_value_init() on the @value argument, so it
+ * need not be initialised beforehand.
*
- * Returns: %TRUE on success.
+ * Returns: %TRUE on success
*
* Since: 2.12
*/
gboolean
-gtk_builder_value_from_string_type (GType type,
- const gchar *string,
- GValue *value)
+gtk_builder_value_from_string_type (GtkBuilder *builder,
+ GType type,
+ const gchar *string,
+ GValue *value,
+ GError **error)
{
gboolean ret = TRUE;
g_return_val_if_fail (type != G_TYPE_INVALID, FALSE);
g_return_val_if_fail (string != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
g_value_init (value, type);
{
gboolean b;
- switch (g_ascii_tolower (string[0]))
- {
- case 't':
- case 'y':
- b = TRUE;
- break;
- case 'f':
- case 'n':
- b = FALSE;
- break;
- default:
- {
- gchar *endptr;
- errno = 0;
- b = strtol (string, &endptr, 0);
- if (errno || endptr == string)
- {
- g_warning ("could not parse int `%s'", string);
- ret = FALSE;
- break;
- }
- }
- break;
+ if (!_gtk_builder_boolean_from_string (string, &b, error))
+ {
+ ret = FALSE;
+ break;
}
g_value_set_boolean (value, b);
break;
l = strtol (string, &endptr, 0);
if (errno || endptr == string)
{
- g_warning ("could not parse long `%s'", string);
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_VALUE,
+ "Could not parse integer `%s'",
+ string);
ret = FALSE;
break;
}
ul = strtoul (string, &endptr, 0);
if (errno || endptr == string)
{
- g_warning ("could not parse ulong `%s'", string);
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_VALUE,
+ "Could not parse unsigned integer `%s'",
+ string);
ret = FALSE;
break;
}
break;
}
case G_TYPE_ENUM:
- g_value_set_enum (value, _gtk_builder_enum_from_string (type, string));
- break;
+ {
+ gint enum_value;
+ if (!_gtk_builder_enum_from_string (type, string, &enum_value, error))
+ {
+ ret = FALSE;
+ break;
+ }
+ g_value_set_enum (value, enum_value);
+ break;
+ }
case G_TYPE_FLAGS:
- g_value_set_flags (value, _gtk_builder_flags_from_string (type, string));
- break;
+ {
+ guint flags_value;
+
+ if (!_gtk_builder_flags_from_string (type, string, &flags_value, error))
+ {
+ ret = FALSE;
+ break;
+ }
+ g_value_set_flags (value, flags_value);
+ break;
+ }
case G_TYPE_FLOAT:
case G_TYPE_DOUBLE:
{
- double d;
+ gdouble d;
gchar *endptr;
errno = 0;
d = g_ascii_strtod (string, &endptr);
if (errno || endptr == string)
{
- g_warning ("could not parse double `%s'", string);
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_VALUE,
+ "Could not parse double `%s'",
+ string);
ret = FALSE;
break;
}
g_value_set_boxed (value, &colour);
else
{
- g_warning ("could not parse colour name `%s'", string);
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_VALUE,
+ "Could not parse color `%s'",
+ string);
ret = FALSE;
}
}
else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
{
- char **vector = g_strsplit (string, "\n", 0);
+ gchar **vector = g_strsplit (string, "\n", 0);
g_value_take_boxed (value, vector);
}
else
ret = FALSE;
break;
case G_TYPE_OBJECT:
-#if 0
- if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF))
- {
- gchar *filename;
- GError *error = NULL;
- GdkPixbuf *pixbuf;
+ if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF))
+ {
+ gchar *filename;
+ GError *tmp_error = NULL;
+ GdkPixbuf *pixbuf;
+
+ if (gtk_builder_get_object (builder, string))
+ {
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_VALUE,
+ "Could not load image '%s': "
+ " '%s' is already used as object id",
+ string, string);
+ return FALSE;
+ }
- filename = gtk_xml_relative_file (xml, string);
- pixbuf = gdk_pixbuf_new_from_file (filename, &error);
- if (pixbuf)
- {
- g_value_set_object (value, pixbuf);
- g_object_unref (G_OBJECT (pixbuf));
- }
- else
- {
- g_warning ("Error loading image: %s", error->message);
- g_error_free (error);
- ret = FALSE;
- }
- g_free (filename);
- }
- else
-#endif
- ret = FALSE;
+ filename = _gtk_builder_get_absolute_filename (builder, string);
+ pixbuf = gdk_pixbuf_new_from_file (filename, &tmp_error);
+
+ if (pixbuf == NULL)
+ {
+ GtkIconTheme *theme;
+
+ g_warning ("Could not load image '%s': %s",
+ string, tmp_error->message);
+ g_error_free (tmp_error);
+
+ /* fall back to a missing image */
+ theme = gtk_icon_theme_get_default ();
+ pixbuf = gtk_icon_theme_load_icon (theme,
+ GTK_STOCK_MISSING_IMAGE,
+ 16,
+ GTK_ICON_LOOKUP_USE_BUILTIN,
+ NULL);
+ }
+
+ if (pixbuf)
+ {
+ g_value_set_object (value, pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+
+ g_free (filename);
+
+ ret = TRUE;
+ }
+ else
+ ret = FALSE;
break;
default:
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_VALUE,
+ "Unsupported GType `%s'",
+ g_type_name (type));
ret = FALSE;
break;
}
return ret;
}
-static gint
-_gtk_builder_enum_from_string (GType type, const char *string)
+static gboolean
+_gtk_builder_enum_from_string (GType type,
+ const gchar *string,
+ gint *enum_value,
+ GError **error)
{
GEnumClass *eclass;
GEnumValue *ev;
gchar *endptr;
- gint ret = 0;
-
- g_return_val_if_fail (G_TYPE_IS_ENUM (type), 0);
- g_return_val_if_fail (string != NULL, 0);
+ gint value;
+ gboolean ret;
- ret = strtoul (string, &endptr, 0);
- if (endptr != string) /* parsed a number */
- return ret;
-
- eclass = g_type_class_ref (type);
- ev = g_enum_get_value_by_name (eclass, string);
- if (!ev)
- ev = g_enum_get_value_by_nick (eclass, string);
-
- if (ev)
- ret = ev->value;
+ g_return_val_if_fail (G_TYPE_IS_ENUM (type), FALSE);
+ g_return_val_if_fail (string != NULL, FALSE);
+
+ ret = TRUE;
- g_type_class_unref (eclass);
+ value = strtoul (string, &endptr, 0);
+ if (endptr != string) /* parsed a number */
+ *enum_value = value;
+ else
+ {
+ eclass = g_type_class_ref (type);
+ ev = g_enum_get_value_by_name (eclass, string);
+ if (!ev)
+ ev = g_enum_get_value_by_nick (eclass, string);
+ if (ev)
+ *enum_value = ev->value;
+ else
+ {
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_VALUE,
+ "Could not parse enum: `%s'",
+ string);
+ ret = FALSE;
+ }
+
+ g_type_class_unref (eclass);
+ }
+
return ret;
}
-guint
-_gtk_builder_flags_from_string (GType type, const char *string)
+gboolean
+_gtk_builder_flags_from_string (GType type,
+ const gchar *string,
+ guint *flags_value,
+ GError **error)
{
GFlagsClass *fclass;
gchar *endptr, *prevptr;
- guint i, j, ret;
- char *flagstr;
+ guint i, j, value;
+ gchar *flagstr;
GFlagsValue *fv;
- const char *flag;
+ const gchar *flag;
gunichar ch;
- gboolean eos;
+ gboolean eos, ret;
- g_return_val_if_fail (G_TYPE_IS_FLAGS (type), 0);
- g_return_val_if_fail (string != 0, 0);
+ g_return_val_if_fail (G_TYPE_IS_FLAGS (type), FALSE);
+ g_return_val_if_fail (string != 0, FALSE);
- ret = strtoul (string, &endptr, 0);
+ ret = TRUE;
+
+ value = strtoul (string, &endptr, 0);
if (endptr != string) /* parsed a number */
- return ret;
-
- fclass = g_type_class_ref (type);
-
- flagstr = g_strdup (string);
- for (ret = i = j = 0; ; i++)
+ *flags_value = value;
+ else
{
+ fclass = g_type_class_ref (type);
- eos = flagstr[i] == '\0';
-
- if (!eos && flagstr[i] != '|')
- continue;
-
- flag = &flagstr[j];
- endptr = &flagstr[i];
-
- if (!eos)
- {
- flagstr[i++] = '\0';
- j = i;
- }
-
- /* trim spaces */
- for (;;)
- {
- ch = g_utf8_get_char (flag);
- if (!g_unichar_isspace (ch))
- break;
- flag = g_utf8_next_char (flag);
- }
-
- while (endptr > flag)
- {
- prevptr = g_utf8_prev_char (endptr);
- ch = g_utf8_get_char (prevptr);
- if (!g_unichar_isspace (ch))
- break;
- endptr = prevptr;
- }
-
- if (endptr > flag)
- {
- *endptr = '\0';
- fv = g_flags_get_value_by_name (fclass, flag);
-
- if (!fv)
- fv = g_flags_get_value_by_nick (fclass, flag);
-
- if (fv)
- ret |= fv->value;
- else
- g_warning ("Unknown flag: '%s'", flag);
- }
-
- if (eos)
- break;
+ flagstr = g_strdup (string);
+ for (value = i = j = 0; ; i++)
+ {
+
+ eos = flagstr[i] == '\0';
+
+ if (!eos && flagstr[i] != '|')
+ continue;
+
+ flag = &flagstr[j];
+ endptr = &flagstr[i];
+
+ if (!eos)
+ {
+ flagstr[i++] = '\0';
+ j = i;
+ }
+
+ /* trim spaces */
+ for (;;)
+ {
+ ch = g_utf8_get_char (flag);
+ if (!g_unichar_isspace (ch))
+ break;
+ flag = g_utf8_next_char (flag);
+ }
+
+ while (endptr > flag)
+ {
+ prevptr = g_utf8_prev_char (endptr);
+ ch = g_utf8_get_char (prevptr);
+ if (!g_unichar_isspace (ch))
+ break;
+ endptr = prevptr;
+ }
+
+ if (endptr > flag)
+ {
+ *endptr = '\0';
+ fv = g_flags_get_value_by_name (fclass, flag);
+
+ if (!fv)
+ fv = g_flags_get_value_by_nick (fclass, flag);
+
+ if (fv)
+ value |= fv->value;
+ else
+ {
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_VALUE,
+ "Unknown flag: `%s'",
+ flag);
+ ret = FALSE;
+ break;
+ }
+ }
+
+ if (eos)
+ {
+ *flags_value = value;
+ break;
+ }
+ }
+
+ g_free (flagstr);
+
+ g_type_class_unref (fclass);
}
- g_free (flagstr);
-
- g_type_class_unref (fclass);
-
return ret;
}
/**
* gtk_builder_get_type_from_name:
* @builder: a #GtkBuilder
- * @type_name: Type name to lookup
+ * @type_name: type name to lookup
*
- * This method is used to lookup a type. It can be implemented in a
- * subclass to override the #GType of an object created by the builder.
+ * Looks up a type by name, using the virtual function that
+ * #GtkBuilder has for that purpose. This is mainly used when
+ * implementing the #GtkBuildable interface on a type.
*
- * Returns: the #GType found for @type_name or #G_TYPE_INVALID if no
- * type was found
+ * Returns: the #GType found for @type_name or #G_TYPE_INVALID
+ * if no type was found
*
- * Since 2.12
+ * Since: 2.12
*/
GType
-gtk_builder_get_type_from_name (GtkBuilder *builder, const gchar *type_name)
+gtk_builder_get_type_from_name (GtkBuilder *builder,
+ const gchar *type_name)
{
g_return_val_if_fail (GTK_IS_BUILDER (builder), G_TYPE_INVALID);
g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID);
return GTK_BUILDER_GET_CLASS (builder)->get_type_from_name (builder, type_name);
}
-/**
- * gtk_builder_error_quark:
- *
- * Registers an error quark for #GtkBuilder if necessary.
- *
- * Return value: The error quark used for #GtkBuilder errors.
- *
- * Since: 2.12
- **/
GQuark
gtk_builder_error_quark (void)
{
return g_quark_from_static_string ("gtk-builder-error-quark");
}
+gchar *
+_gtk_builder_get_absolute_filename (GtkBuilder *builder, const gchar *string)
+{
+ gchar *filename;
+ gchar *dirname = NULL;
+
+ if (g_path_is_absolute (string))
+ return g_strdup (string);
+
+ if (builder->priv->filename &&
+ strcmp (builder->priv->filename, ".") != 0)
+ dirname = g_path_get_dirname (builder->priv->filename);
+ else
+ dirname = g_get_current_dir ();
+
+ filename = g_build_filename (dirname, string, NULL);
+ g_free (dirname);
+
+ return filename;
+}
#define __GTK_BUILDER_C__
#include "gtkaliasdef.c"