/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2001 Ximian, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Authors: * Chema Celorio */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "glade.h" #include "glade-widget.h" #include "glade-widget-class.h" #include "glade-parameter.h" #include "glade-property.h" #include "glade-property-class.h" #include "glade-editor-property.h" #include "glade-debug.h" /* Hardcoded recognized atk actions */ typedef struct { gchar *prop_name; gchar *id; gchar *name; gchar *tooltip; } GPCAtkPropertyTab; static const GPCAtkPropertyTab action_names_table[] = { { "click", "atk-click", N_("Click"), N_("Set the desctription of the Click atk action") }, { "press", "atk-press", N_("Press"), N_("Set the desctription of the Press atk action") }, { "release", "atk-release", N_("Release"), N_("Set the desctription of the Release atk action") }, { "activate", "atk-activate", N_("Activate"), N_("Set the desctription of the Activate atk action") } }; static const GPCAtkPropertyTab relation_names_table[] = { { "controlled-by", "atk-controlled-by", N_("Controlled By"), N_("Indicates an object controlled by one or more target objects") }, { "controlled-for", "atk-controlled-for", N_("Controller For"), N_("Indicates an object is a controller for one or more target objects") }, { "labelled-by", "atk-labelled-by", N_("Labelled By"), N_("Indicates an object is labelled by one or more target objects") }, { "label-for", "atk-label-for", N_("Label For"), N_("Indicates an object is a label for one or more target objects") }, { "member-of", "atk-member-of", N_("Member Of"), N_("Indicates an object is a member of a group of one or more target objects") }, { "child-node-of", "atk-child-node-of", N_("Child Node Of"), N_("Indicates an object is a cell in a treetable which is displayed " "because a cell in the same column is expanded and identifies that cell") }, { "flows-to", "atk-flows-to", N_("Flows To"), N_("Indicates that the object has content that flows logically to another " "AtkObject in a sequential way, (for instance text-flow)") }, { "flows-from", "atk-flows-from", N_("Flows From"), N_("Indicates that the object has content that flows logically from another " "AtkObject in a sequential way, (for instance text-flow)") }, { "subwindow-of", "atk-subwindow-of", N_("Subwindow Of"), N_("Indicates a subwindow attached to a component but otherwise has no " "connection in the UI hierarchy to that component") }, { "embeds", "atk-embeds", N_("Embeds"), N_("Indicates that the object visually embeds another object's content, " "i.e. this object's content flows around another's content") }, { "embedded-by", "atk-embedded-by", N_("Embedded By"), N_("Inverse of 'Embeds', indicates that this object's content " "is visualy embedded in another object") }, { "popup-for", "atk-popup-for", N_("Popup For"), N_("Indicates that an object is a popup for another object") }, { "parent-window-of", "atk-parent-window-of", N_("Parent Window Of"), N_("Indicates that an object is a parent window of another object") } }; /** * glade_property_class_atk_realname: * @atk_name: The id of the atk property * * Translates a GladePropertyClass->id to the name that should be * saved into the glade file. * * Returns: a pointer to a constant string. */ G_CONST_RETURN gchar * glade_property_class_atk_realname (const gchar *atk_name) { gint i; g_return_val_if_fail (atk_name != NULL, NULL); for (i = 0; i < G_N_ELEMENTS (action_names_table); i++) if (!strcmp (action_names_table[i].id, atk_name)) return action_names_table[i].prop_name; for (i = 0; i < G_N_ELEMENTS (relation_names_table); i++) if (!strcmp (relation_names_table[i].id, atk_name)) return relation_names_table[i].prop_name; return atk_name; } /** * glade_property_class_new: * @handle: A generic pointer (i.e. a #GladeWidgetClass) * * Returns: a new #GladePropertyClass */ GladePropertyClass * glade_property_class_new (gpointer handle) { GladePropertyClass *property_class; property_class = g_new0 (GladePropertyClass, 1); property_class->handle = handle; property_class->pspec = NULL; property_class->id = NULL; property_class->name = NULL; property_class->tooltip = NULL; property_class->def = NULL; property_class->orig_def = NULL; property_class->parameters = NULL; property_class->displayable_values = NULL; property_class->query = FALSE; property_class->optional = FALSE; property_class->optional_default = FALSE; property_class->common = FALSE; property_class->packing = FALSE; property_class->is_modified = FALSE; property_class->verify_function = NULL; property_class->set_function = NULL; property_class->get_function = NULL; property_class->visible = TRUE; property_class->save = TRUE; property_class->ignore = FALSE; property_class->resource = FALSE; property_class->translatable = FALSE; property_class->type = GPC_NORMAL; property_class->virtual = TRUE; property_class->transfer_on_paste = FALSE; property_class->weight = -1.0; return property_class; } /** * glade_property_class_clone: * @property_class: a #GladePropertyClass * * Returns: a new #GladePropertyClass cloned from @property_class */ GladePropertyClass * glade_property_class_clone (GladePropertyClass *property_class) { GladePropertyClass *clone; g_return_val_if_fail (GLADE_IS_PROPERTY_CLASS (property_class), NULL); clone = g_new0 (GladePropertyClass, 1); memcpy (clone, property_class, sizeof(GladePropertyClass)); clone->pspec = property_class->pspec; clone->id = g_strdup (clone->id); clone->name = g_strdup (clone->name); clone->tooltip = g_strdup (clone->tooltip); if (G_IS_VALUE (property_class->def)) { clone->def = g_new0 (GValue, 1); g_value_init (clone->def, property_class->pspec->value_type); g_value_copy (property_class->def, clone->def); } if (G_IS_VALUE (property_class->orig_def)) { clone->orig_def = g_new0 (GValue, 1); g_value_init (clone->orig_def, property_class->pspec->value_type); g_value_copy (property_class->orig_def, clone->orig_def); } if (clone->parameters) { GList *parameter; clone->parameters = g_list_copy (clone->parameters); for (parameter = clone->parameters; parameter != NULL; parameter = parameter->next) parameter->data = glade_parameter_clone ((GladeParameter*) parameter->data); } if (property_class->displayable_values) { gint i, len; GEnumValue val; GArray *disp_val; disp_val = property_class->displayable_values; len = disp_val->len; clone->displayable_values = g_array_new(FALSE, TRUE, sizeof(GEnumValue)); for (i = 0; i < len; i++) { val.value = g_array_index(disp_val, GEnumValue, i).value; val.value_name = g_strdup (g_array_index(disp_val, GEnumValue, i).value_name); val.value_nick = g_strdup (g_array_index(disp_val, GEnumValue, i).value_nick); g_array_append_val(clone->displayable_values, val); } } return clone; } /** * glade_property_class_free: * @property_class: a #GladePropertyClass * * Frees @class and its associated memory. */ void glade_property_class_free (GladePropertyClass *property_class) { if (property_class == NULL) return; g_return_if_fail (GLADE_IS_PROPERTY_CLASS (property_class)); g_free (property_class->id); g_free (property_class->tooltip); g_free (property_class->name); if (property_class->orig_def) { if (G_VALUE_TYPE (property_class->orig_def) != 0) g_value_unset (property_class->orig_def); g_free (property_class->orig_def); } if (property_class->def) { if (G_VALUE_TYPE (property_class->def) != 0) g_value_unset (property_class->def); g_free (property_class->def); } g_list_foreach (property_class->parameters, (GFunc) glade_parameter_free, NULL); g_list_free (property_class->parameters); if (property_class->displayable_values) { gint i, len; GArray *disp_val; disp_val = property_class->displayable_values; len = disp_val->len; for (i = 0; i < len; i++) { gchar *name, *nick; name = (gchar *) g_array_index (disp_val, GEnumValue, i).value_name; if (name) g_free(name); nick = (gchar *) g_array_index (disp_val, GEnumValue, i).value_nick; if (nick) g_free(nick); } g_array_free(disp_val, TRUE); } g_free (property_class); } static GValue * glade_property_class_get_default_from_spec (GParamSpec *spec) { GValue *value; value = g_new0 (GValue, 1); g_value_init (value, spec->value_type); g_param_value_set_default (spec, value); return value; } static gchar * glade_property_class_make_string_from_enum (GType etype, gint eval) { GEnumClass *eclass; gchar *string = NULL; guint i; g_return_val_if_fail ((eclass = g_type_class_ref (etype)) != NULL, NULL); for (i = 0; i < eclass->n_values; i++) { if (eval == eclass->values[i].value) { string = g_strdup (eclass->values[i].value_name); break; } } g_type_class_unref (eclass); return string; } static gchar * glade_property_class_make_string_from_flags (GladePropertyClass *class, guint fvals, gboolean displayables) { GFlagsClass *fclass; GFlagsValue *fvalue; GString *string; gchar *retval; g_return_val_if_fail ((fclass = g_type_class_ref (class->pspec->value_type)) != NULL, NULL); string = g_string_new(""); while ((fvalue = g_flags_get_first_value(fclass, fvals)) != NULL) { const gchar *val_str = NULL; fvals &= ~fvalue->value; if (displayables) val_str = glade_property_class_get_displayable_value(class, fvalue->value); if (string->str[0]) g_string_append(string, " | "); g_string_append (string, (val_str) ? val_str : fvalue->value_name); /* If one of the flags value is 0 this loop become infinite :) */ if (fvalue->value == 0) break; } retval = string->str; g_type_class_unref (fclass); g_string_free(string, FALSE); return retval; } static gchar * glade_property_class_make_string_from_object (GladePropertyClass *property_class, GObject *object) { GladeWidget *gwidget; gchar *string = NULL, *filename; if (!object) return NULL; if (property_class->pspec->value_type == GDK_TYPE_PIXBUF) { if ((filename = g_object_get_data (object, "GladeFileName")) != NULL) string = g_path_get_basename (filename); } else if (property_class->pspec->value_type == GTK_TYPE_ADJUSTMENT) { #define FLOAT_BUFSIZ 128 GtkAdjustment *adj = GTK_ADJUSTMENT (object); GString *str = g_string_new (""); gchar buff[FLOAT_BUFSIZ]; g_ascii_dtostr (buff, FLOAT_BUFSIZ, adj->value); g_string_append (str, buff); g_string_append_c (str, ' '); g_ascii_dtostr (buff, FLOAT_BUFSIZ, adj->lower); g_string_append (str, buff); g_string_append_c (str, ' '); g_ascii_dtostr (buff, FLOAT_BUFSIZ, adj->upper); g_string_append (str, buff); g_string_append_c (str, ' '); g_ascii_dtostr (buff, FLOAT_BUFSIZ, adj->step_increment); g_string_append (str, buff); g_string_append_c (str, ' '); g_ascii_dtostr (buff, FLOAT_BUFSIZ, adj->page_increment); g_string_append (str, buff); g_string_append_c (str, ' '); g_ascii_dtostr (buff, FLOAT_BUFSIZ, adj->page_size); g_string_append (str, buff); string = g_string_free (str, FALSE); } else if ((gwidget = glade_widget_get_from_gobject (object)) != NULL) string = g_strdup (gwidget->name); else g_critical ("Object type property refers to an object " "outside the project"); return string; } static gchar * glade_property_class_make_string_from_objects (GladePropertyClass *property_class, GList *objects) { GObject *object; GList *list; gchar *string = NULL, *obj_str, *tmp; for (list = objects; list; list = list->next) { object = list->data; obj_str = glade_property_class_make_string_from_object (property_class, object); if (string == NULL) string = obj_str; else if (obj_str != NULL) { tmp = g_strdup_printf ("%s%s%s", string, GPC_OBJECT_DELIMITER, obj_str); string = (g_free (string), tmp); g_free (obj_str); } } return string; } /* This is not used to save in the glade file... and its a one-way conversion. * its only usefull to show the values in the UI. */ static gchar * glade_property_class_make_string_from_accels (GladePropertyClass *property_class, GList *accels) { GladeAccelInfo *info; GString *string; GList *list; string = g_string_new (""); for (list = accels; list; list = list->next) { info = list->data; if (info->modifiers & GDK_SHIFT_MASK) g_string_append (string, "SHIFT-"); if (info->modifiers & GDK_CONTROL_MASK) g_string_append (string, "CNTL-"); if (info->modifiers & GDK_MOD1_MASK) g_string_append (string, "ALT-"); g_string_append (string, glade_builtin_string_from_key (info->key)); if (list->next) g_string_append (string, ", "); } return g_string_free (string, FALSE); } /** * glade_property_class_make_string_from_gvalue: * @property_class: A #GladePropertyClass * @value: A #GValue * * Returns: A newly allocated string representation of @value */ gchar * glade_property_class_make_string_from_gvalue (GladePropertyClass *property_class, const GValue *value) { gchar *string = NULL, **strv, str[FLOAT_BUFSIZ]; GObject *object; GdkColor *color; GList *objects, *accels; if (G_IS_PARAM_SPEC_ENUM(property_class->pspec)) { gint eval = g_value_get_enum (value); string = glade_property_class_make_string_from_enum (property_class->pspec->value_type, eval); } else if (G_IS_PARAM_SPEC_FLAGS(property_class->pspec)) { guint flags = g_value_get_flags (value); string = glade_property_class_make_string_from_flags (property_class, flags, FALSE); } else if (G_IS_PARAM_SPEC_VALUE_ARRAY (property_class->pspec)) { GValueArray *value_array = g_value_get_boxed (value); if (value_array && value_array->n_values && G_VALUE_HOLDS (&value_array->values [0], G_TYPE_STRING)) { gint i, n_values = value_array->n_values; GString *gstring = g_string_new (NULL); for (i = 0; i < n_values; i++) { g_string_append (gstring, g_value_get_string (&value_array->values [i])); g_string_append_c (gstring, '\n'); } string = gstring->str; g_string_free (gstring, FALSE); } } else if (G_IS_PARAM_SPEC_BOXED(property_class->pspec)) { if (property_class->pspec->value_type == GDK_TYPE_COLOR) { color = g_value_get_boxed (value); if (color) string = g_strdup_printf ("#%04x%04x%04x", color->red, color->green, color->blue); } else if (property_class->pspec->value_type == G_TYPE_STRV) { strv = g_value_get_boxed (value); if (strv) string = g_strjoinv ("\n", strv); } } else if (G_IS_PARAM_SPEC_INT(property_class->pspec)) string = g_strdup_printf ("%d", g_value_get_int (value)); else if (G_IS_PARAM_SPEC_UINT(property_class->pspec)) string = g_strdup_printf ("%u", g_value_get_uint (value)); else if (G_IS_PARAM_SPEC_LONG(property_class->pspec)) string = g_strdup_printf ("%ld", g_value_get_long (value)); else if (G_IS_PARAM_SPEC_ULONG(property_class->pspec)) string = g_strdup_printf ("%lu", g_value_get_ulong (value)); else if (G_IS_PARAM_SPEC_INT64(property_class->pspec)) string = g_strdup_printf ("%lld", g_value_get_int64 (value)); else if (G_IS_PARAM_SPEC_UINT64(property_class->pspec)) string = g_strdup_printf ("%llu", g_value_get_uint64 (value)); else if (G_IS_PARAM_SPEC_FLOAT(property_class->pspec)) { g_ascii_dtostr (str, FLOAT_BUFSIZ, g_value_get_float (value)); string = g_strdup (str); } else if (G_IS_PARAM_SPEC_DOUBLE(property_class->pspec)) { g_ascii_dtostr (str, FLOAT_BUFSIZ, g_value_get_double (value)); string = g_strdup (str); } else if (G_IS_PARAM_SPEC_STRING(property_class->pspec)) { if (property_class->resource && g_value_get_string (value) != NULL) string = g_path_get_basename (g_value_get_string (value)); else string = g_value_dup_string (value); } else if (G_IS_PARAM_SPEC_CHAR(property_class->pspec)) string = g_strdup_printf ("%c", g_value_get_char (value)); else if (G_IS_PARAM_SPEC_UCHAR(property_class->pspec)) string = g_strdup_printf ("%c", g_value_get_uchar (value)); else if (G_IS_PARAM_SPEC_UNICHAR(property_class->pspec)) { string = g_malloc (7); g_unichar_to_utf8 (g_value_get_uint (value), string); *g_utf8_next_char(string) = '\0'; } else if (G_IS_PARAM_SPEC_BOOLEAN(property_class->pspec)) string = g_strdup_printf ("%s", g_value_get_boolean (value) ? GLADE_TAG_TRUE : GLADE_TAG_FALSE); else if (G_IS_PARAM_SPEC_OBJECT(property_class->pspec)) { object = g_value_get_object (value); string = glade_property_class_make_string_from_object (property_class, object); } else if (GLADE_IS_PARAM_SPEC_OBJECTS (property_class->pspec)) { objects = g_value_get_boxed (value); string = glade_property_class_make_string_from_objects (property_class, objects); } else if (GLADE_IS_PARAM_SPEC_ACCEL (property_class->pspec)) { accels = g_value_get_boxed (value); string = glade_property_class_make_string_from_accels (property_class, accels); } else g_critical ("Unsupported pspec type %s", g_type_name(G_PARAM_SPEC_TYPE (property_class->pspec))); return string; } /* This is copied exactly from libglade. I've just renamed the function. */ static guint glade_property_class_make_flags_from_string (GType type, const char *string) { GFlagsClass *fclass; gchar *endptr, *prevptr; guint i, j, ret = 0; char *flagstr; ret = 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++) { gboolean eos; eos = flagstr [i] == '\0'; if (eos || flagstr [i] == '|') { GFlagsValue *fv; const char *flag; gunichar ch; 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; } } g_free (flagstr); g_type_class_unref(fclass); return ret; } /* This is copied exactly from libglade. I've just renamed the function. */ static gint glade_property_class_make_enum_from_string (GType type, const char *string) { GEnumClass *eclass; GEnumValue *ev; gchar *endptr; gint ret = 0; 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_type_class_unref(eclass); return ret; } static GObject * glade_property_class_make_object_from_string (GladePropertyClass *property_class, const gchar *string, GladeProject *project) { GObject *object = NULL; gchar *fullpath; if (string == NULL) return NULL; if (property_class->pspec->value_type == GDK_TYPE_PIXBUF && project) { GdkPixbuf *pixbuf; fullpath = glade_project_resource_fullpath (project, string); if ((pixbuf = gdk_pixbuf_new_from_file (fullpath, NULL)) == NULL) { static GdkPixbuf *icon = NULL; if (icon == NULL) { GtkWidget *widget = gtk_label_new (""); icon = gtk_widget_render_icon (widget, GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_MENU, NULL); gtk_object_sink (GTK_OBJECT (widget)); } pixbuf = gdk_pixbuf_copy (icon); } if (pixbuf) { object = G_OBJECT (pixbuf); g_object_set_data_full (object, "GladeFileName", g_strdup (string), g_free); } g_free (fullpath); } if (property_class->pspec->value_type == GTK_TYPE_ADJUSTMENT) { gdouble value, lower, upper, step_increment, page_increment, page_size; sscanf (string, "%lf %lf %lf %lf %lf %lf", &value, &lower, &upper, &step_increment, &page_increment, &page_size); object = G_OBJECT (gtk_adjustment_new (value, lower, upper, step_increment, page_increment, page_size)); } else { GladeWidget *gwidget; if ((gwidget = glade_project_get_widget_by_name (project, string)) != NULL) object = gwidget->object; } return object; } static GList * glade_property_class_make_objects_from_string (GladePropertyClass *property_class, const gchar *string, GladeProject *project) { GList *objects = NULL; GObject *object; gchar **split; guint i; if ((split = g_strsplit (string, GPC_OBJECT_DELIMITER, 0)) != NULL) { for (i = 0; split[i]; i++) { if ((object = glade_property_class_make_object_from_string (property_class, split[i], project)) != NULL) objects = g_list_prepend (objects, object); } g_strfreev (split); } return objects; } /** * glade_property_class_make_gvalue_from_string: * @property_class: A #GladePropertyClass * @string: a string representation of this property * @project: the glade project that the associated property * belongs to. * * Returns: A #GValue created based on the @property_class * and @string criteria. */ GValue * glade_property_class_make_gvalue_from_string (GladePropertyClass *property_class, const gchar *string, GladeProject *project) { GValue *value = g_new0 (GValue, 1); gchar **strv, *fullpath; GdkColor color = { 0, }; g_value_init (value, property_class->pspec->value_type); if (G_IS_PARAM_SPEC_ENUM(property_class->pspec)) { gint eval = glade_property_class_make_enum_from_string (property_class->pspec->value_type, string); g_value_set_enum (value, eval); } else if (G_IS_PARAM_SPEC_FLAGS(property_class->pspec)) { guint flags = glade_property_class_make_flags_from_string (property_class->pspec->value_type, string); g_value_set_flags (value, flags); } else if (G_IS_PARAM_SPEC_VALUE_ARRAY (property_class->pspec)) { GValueArray *value_array = g_value_array_new (0);; GValue str_value = {0, }; gint i; g_value_init (&str_value, G_TYPE_STRING); strv = g_strsplit (string, "\n", 0); for (i = 0; strv[i]; i++) { g_value_set_static_string (&str_value, strv[i]); value_array = g_value_array_append (value_array, &str_value); } g_value_set_boxed (value, value_array); g_strfreev (strv); } else if (G_IS_PARAM_SPEC_BOXED(property_class->pspec)) { if (property_class->pspec->value_type == GDK_TYPE_COLOR) { if (gdk_color_parse(string, &color) && gdk_colormap_alloc_color(gtk_widget_get_default_colormap(), &color, FALSE, TRUE)) g_value_set_boxed(value, &color); else g_warning ("could not parse colour name `%s'", string); } else if (property_class->pspec->value_type == G_TYPE_STRV) { strv = g_strsplit (string, "\n", 0); g_value_take_boxed (value, strv); } } else if (G_IS_PARAM_SPEC_INT(property_class->pspec)) g_value_set_int (value, atoi (string)); else if (G_IS_PARAM_SPEC_UINT(property_class->pspec)) g_value_set_uint (value, atoi (string)); else if (G_IS_PARAM_SPEC_LONG(property_class->pspec)) g_value_set_long (value, strtol (string, NULL, 10)); else if (G_IS_PARAM_SPEC_ULONG(property_class->pspec)) g_value_set_ulong (value, strtoul (string, NULL, 10)); else if (G_IS_PARAM_SPEC_INT64(property_class->pspec)) #ifndef G_OS_WIN32 g_value_set_int64 (value, strtoll (string, NULL, 10)); #else g_value_set_int64 (value, _atoi64 (string)); #endif else if (G_IS_PARAM_SPEC_UINT64(property_class->pspec)) g_value_set_uint64 (value, g_ascii_strtoull (string, NULL, 10)); else if (G_IS_PARAM_SPEC_FLOAT(property_class->pspec)) g_value_set_float (value, (float) atof (string)); else if (G_IS_PARAM_SPEC_DOUBLE(property_class->pspec)) g_value_set_double (value, (float) atof (string)); else if (G_IS_PARAM_SPEC_STRING(property_class->pspec)) { /* This can be called when loading defaults from * catalog files... it wont happen and we cant do * anything for it. */ if (property_class->resource && project) { fullpath = g_build_filename (project->path, string, NULL); g_value_set_string (value, fullpath); g_free (fullpath); } else g_value_set_string (value, string); } else if (G_IS_PARAM_SPEC_CHAR(property_class->pspec)) g_value_set_char (value, string[0]); else if (G_IS_PARAM_SPEC_UCHAR(property_class->pspec)) g_value_set_uchar (value, string[0]); else if (G_IS_PARAM_SPEC_UNICHAR(property_class->pspec)) g_value_set_uint (value, g_utf8_get_char (string)); else if (G_IS_PARAM_SPEC_BOOLEAN(property_class->pspec)) { if (strcmp (string, GLADE_TAG_TRUE) == 0) g_value_set_boolean (value, TRUE); else g_value_set_boolean (value, FALSE); } else if (G_IS_PARAM_SPEC_OBJECT(property_class->pspec)) { GObject *object = glade_property_class_make_object_from_string (property_class, string, project); g_value_set_object (value, object); } else if (GLADE_IS_PARAM_SPEC_OBJECTS (property_class->pspec)) { GList *objects = glade_property_class_make_objects_from_string (property_class, string, project); g_value_set_boxed (value, objects); } else g_critical ("Unsupported pspec type %s", g_type_name(G_PARAM_SPEC_TYPE (property_class->pspec))); return value; } /** * glade_property_class_make_gvalue_from_vl: * @property_class: A #GladePropertyClass * @vl: a #va_list holding one argument of the correct type * specified by @property_class * * Returns: A #GValue created based on the @property_class * and a @vl arg of the correct type. */ GValue * glade_property_class_make_gvalue_from_vl (GladePropertyClass *class, va_list vl) { GValue *value; g_return_val_if_fail (class != NULL, NULL); value = g_new0 (GValue, 1); g_value_init (value, class->pspec->value_type); if (G_IS_PARAM_SPEC_ENUM(class->pspec)) g_value_set_enum (value, va_arg (vl, gint)); else if (G_IS_PARAM_SPEC_FLAGS(class->pspec)) g_value_set_flags (value, va_arg (vl, gint)); else if (G_IS_PARAM_SPEC_INT(class->pspec)) g_value_set_int (value, va_arg (vl, gint)); else if (G_IS_PARAM_SPEC_UINT(class->pspec)) g_value_set_uint (value, va_arg (vl, guint)); else if (G_IS_PARAM_SPEC_LONG(class->pspec)) g_value_set_long (value, va_arg (vl, glong)); else if (G_IS_PARAM_SPEC_ULONG(class->pspec)) g_value_set_ulong (value, va_arg (vl, gulong)); else if (G_IS_PARAM_SPEC_INT64(class->pspec)) g_value_set_int64 (value, va_arg (vl, gint64)); else if (G_IS_PARAM_SPEC_UINT64(class->pspec)) g_value_set_uint64 (value, va_arg (vl, guint64)); else if (G_IS_PARAM_SPEC_FLOAT(class->pspec)) g_value_set_float (value, (gfloat)va_arg (vl, gdouble)); else if (G_IS_PARAM_SPEC_DOUBLE(class->pspec)) g_value_set_double (value, va_arg (vl, gdouble)); else if (G_IS_PARAM_SPEC_STRING(class->pspec)) g_value_set_string (value, va_arg (vl, gchar *)); else if (G_IS_PARAM_SPEC_CHAR(class->pspec)) g_value_set_char (value, (gchar)va_arg (vl, gint)); else if (G_IS_PARAM_SPEC_UCHAR(class->pspec)) g_value_set_uchar (value, (guchar)va_arg (vl, guint)); else if (G_IS_PARAM_SPEC_UNICHAR(class->pspec)) g_value_set_uint (value, va_arg (vl, gunichar)); else if (G_IS_PARAM_SPEC_BOOLEAN(class->pspec)) g_value_set_boolean (value, va_arg (vl, gboolean)); else if (G_IS_PARAM_SPEC_OBJECT(class->pspec)) g_value_set_object (value, va_arg (vl, gpointer)); else if (G_IS_PARAM_SPEC_BOXED(class->pspec)) g_value_set_boxed (value, va_arg (vl, gpointer)); else if (GLADE_IS_PARAM_SPEC_OBJECTS(class->pspec)) g_value_set_boxed (value, va_arg (vl, gpointer)); else g_critical ("Unsupported pspec type %s", g_type_name(G_PARAM_SPEC_TYPE (class->pspec))); return value; } /** * glade_property_class_make_gvalue: * @class: A #GladePropertyClass * @...: an argument of the correct type specified by @property_class * * Returns: A #GValue created based on the @property_class * and the provided argument. */ GValue * glade_property_class_make_gvalue (GladePropertyClass *class, ...) { GValue *value; va_list vl; g_return_val_if_fail (class != NULL, NULL); va_start (vl, class); value = glade_property_class_make_gvalue_from_vl (class, vl); va_end (vl); return value; } /** * glade_property_class_set_vl_from_gvalue: * @class: A #GladePropertyClass * @value: A #GValue to set * @vl: a #va_list holding one argument of the correct type * specified by @class * * * Sets @vl from @value based on @class criteria. */ void glade_property_class_set_vl_from_gvalue (GladePropertyClass *class, GValue *value, va_list vl) { g_return_if_fail (class != NULL); g_return_if_fail (value != NULL); /* The argument is a pointer of the specified type, cast the pointer and assign * the value using the proper g_value_get_ variation. */ if (G_IS_PARAM_SPEC_ENUM(class->pspec)) *(gint *)(va_arg (vl, gint *)) = g_value_get_enum (value); else if (G_IS_PARAM_SPEC_FLAGS(class->pspec)) *(gint *)(va_arg (vl, gint *)) = g_value_get_flags (value); else if (G_IS_PARAM_SPEC_INT(class->pspec)) *(gint *)(va_arg (vl, gint *)) = g_value_get_int (value); else if (G_IS_PARAM_SPEC_UINT(class->pspec)) *(guint *)(va_arg (vl, guint *)) = g_value_get_uint (value); else if (G_IS_PARAM_SPEC_LONG(class->pspec)) *(glong *)(va_arg (vl, glong *)) = g_value_get_long (value); else if (G_IS_PARAM_SPEC_ULONG(class->pspec)) *(gulong *)(va_arg (vl, gulong *)) = g_value_get_ulong (value); else if (G_IS_PARAM_SPEC_INT64(class->pspec)) *(gint64 *)(va_arg (vl, gint64 *)) = g_value_get_int64 (value); else if (G_IS_PARAM_SPEC_UINT64(class->pspec)) *(guint64 *)(va_arg (vl, guint64 *)) = g_value_get_uint64 (value); else if (G_IS_PARAM_SPEC_FLOAT(class->pspec)) *(gfloat *)(va_arg (vl, gdouble *)) = g_value_get_float (value); else if (G_IS_PARAM_SPEC_DOUBLE(class->pspec)) *(gdouble *)(va_arg (vl, gdouble *)) = g_value_get_double (value); else if (G_IS_PARAM_SPEC_STRING(class->pspec)) *(gchar **)(va_arg (vl, gchar *)) = (gchar *)g_value_get_string (value); else if (G_IS_PARAM_SPEC_CHAR(class->pspec)) *(gchar *)(va_arg (vl, gint *)) = g_value_get_char (value); else if (G_IS_PARAM_SPEC_UCHAR(class->pspec)) *(guchar *)(va_arg (vl, guint *)) = g_value_get_uchar (value); else if (G_IS_PARAM_SPEC_UNICHAR(class->pspec)) *(guint *)(va_arg (vl, gunichar *)) = g_value_get_uint (value); else if (G_IS_PARAM_SPEC_BOOLEAN(class->pspec)) *(gboolean *)(va_arg (vl, gboolean *)) = g_value_get_boolean (value); else if (G_IS_PARAM_SPEC_OBJECT(class->pspec)) *(gpointer *)(va_arg (vl, gpointer *)) = g_value_get_object (value); else if (G_IS_PARAM_SPEC_BOXED(class->pspec)) *(gpointer *)(va_arg (vl, gpointer *)) = g_value_get_boxed (value); else if (GLADE_IS_PARAM_SPEC_OBJECTS(class->pspec)) *(gpointer *)(va_arg (vl, gpointer *)) = g_value_get_boxed (value); else g_critical ("Unsupported pspec type %s", g_type_name(G_PARAM_SPEC_TYPE (class->pspec))); } /** * glade_property_class_get_from_gvalue: * @class: A #GladePropertyClass * @value: A #GValue to set * @...: a return location of the correct type * * * Assignes the provided return location to @value */ void glade_property_class_get_from_gvalue (GladePropertyClass *class, GValue *value, ...) { va_list vl; g_return_if_fail (class != NULL); va_start (vl, value); glade_property_class_set_vl_from_gvalue (class, value, vl); va_end (vl); } /** * glade_property_class_list_atk_relations: * @handle: A generic pointer (i.e. a #GladeWidgetClass) * @owner_type: The #GType of the owning widget class. * * Returns: a #GList of newly created atk relation #GladePropertyClass. */ GList * glade_property_class_list_atk_relations (gpointer handle, GType owner_type) { const GPCAtkPropertyTab *relation_tab = NULL; GladePropertyClass *property_class; GList *list = NULL; gint i; /* Loop through our hard-coded table enties */ for (i = 0; i < G_N_ELEMENTS (relation_names_table); i++) { relation_tab = &relation_names_table[i]; property_class = glade_property_class_new (handle); property_class->pspec = glade_param_spec_objects (relation_tab->id, _(relation_tab->name), _(relation_tab->tooltip), ATK_TYPE_IMPLEMENTOR, G_PARAM_READWRITE); property_class->pspec->owner_type = owner_type; property_class->id = g_strdup (relation_tab->id); property_class->name = g_strdup (_(relation_tab->name)); property_class->tooltip = g_strdup (_(relation_tab->tooltip)); property_class->type = GPC_ATK_RELATION; property_class->visible_lines = 2; property_class->ignore = TRUE; property_class->def = glade_property_class_make_gvalue_from_string (property_class, "", NULL); property_class->orig_def = glade_property_class_make_gvalue_from_string (property_class, "", NULL); list = g_list_prepend (list, property_class); } return g_list_reverse (list); } /** * glade_property_class_accel_property: * @handle: A generic pointer (i.e. a #GladeWidgetClass) * @owner_type: The #GType of the owning widget class. * * Returns: a newly created #GladePropertyClass for accelerators * of the prescribed @owner_type. */ GladePropertyClass * glade_property_class_accel_property (gpointer handle, GType owner_type) { GladePropertyClass *property_class; GValue *def_value; property_class = glade_property_class_new (handle); property_class->pspec = glade_param_spec_accel ("accelerators", _("Accelerators"), _("A list of accelerator keys"), owner_type, G_PARAM_READWRITE); property_class->pspec->owner_type = owner_type; property_class->id = g_strdup (g_param_spec_get_name (property_class->pspec)); property_class->name = g_strdup (g_param_spec_get_nick (property_class->pspec)); property_class->tooltip = g_strdup (g_param_spec_get_blurb (property_class->pspec)); property_class->type = GPC_ACCEL_PROPERTY; property_class->ignore = TRUE; property_class->common = TRUE; /* Setup default */ def_value = g_new0 (GValue, 1); g_value_init (def_value, GLADE_TYPE_ACCEL_GLIST); g_value_set_boxed (def_value, NULL); property_class->def = def_value; /* Setup original default */ def_value = g_new0 (GValue, 1); g_value_init (def_value, GLADE_TYPE_ACCEL_GLIST); g_value_set_boxed (def_value, NULL); property_class->orig_def = def_value; return property_class; } /** * glade_property_class_new_from_spec: * @handle: A generic pointer (i.e. a #GladeWidgetClass) * @spec: A #GParamSpec * * Returns: a newly created #GladePropertyClass based on @spec * or %NULL if its unsupported. */ GladePropertyClass * glade_property_class_new_from_spec (gpointer handle, GParamSpec *spec) { GObjectClass *gtk_widget_class; GladePropertyClass *property_class; g_return_val_if_fail (spec != NULL, NULL); gtk_widget_class = g_type_class_ref (GTK_TYPE_WIDGET); /* Only properties that are _new_from_spec() are * not virtual properties */ property_class = glade_property_class_new (handle); property_class->virtual = FALSE; property_class->pspec = spec; /* We only use the writable properties */ if ((spec->flags & G_PARAM_WRITABLE) == 0) goto failed; /* Register only editable properties. */ if (!glade_editor_property_supported (property_class->pspec)) goto failed; property_class->id = g_strdup (spec->name); property_class->name = g_strdup (g_param_spec_get_nick (spec)); /* If its on the GtkWidgetClass, it goes in "common" * (unless stipulated otherwise in the xml file) */ if (g_object_class_find_property (gtk_widget_class, g_param_spec_get_name (spec)) != NULL) property_class->common = TRUE; /* Flag the construct only properties */ if (spec->flags & G_PARAM_CONSTRUCT_ONLY) property_class->construct_only = TRUE; if (g_type_is_a (spec->owner_type, ATK_TYPE_OBJECT)) { property_class->type = GPC_ATK_PROPERTY; property_class->ignore = TRUE; /* We only use the name and desctription props, * they are both translatable. */ property_class->translatable = TRUE; } if (!property_class->id || !property_class->name) { g_critical ("No name or id for " "glade_property_class_new_from_spec, failed."); goto failed; } property_class->tooltip = g_strdup (g_param_spec_get_blurb (spec)); property_class->orig_def = glade_property_class_get_default_from_spec (spec); property_class->def = glade_property_class_get_default_from_spec (spec); g_type_class_unref (gtk_widget_class); return property_class; failed: glade_property_class_free (property_class); g_type_class_unref (gtk_widget_class); return NULL; } /** * glade_property_class_is_visible: * @property_class: A #GladePropertyClass * * * Returns: whether or not to show this property in the editor */ gboolean glade_property_class_is_visible (GladePropertyClass *class) { g_return_val_if_fail (GLADE_IS_PROPERTY_CLASS (class), FALSE); return class->visible; } /** * glade_property_class_is_object: * @property_class: A #GladePropertyClass * * * Returns: whether or not this is an object property * that refers to another object in this project. */ gboolean glade_property_class_is_object (GladePropertyClass *class) { g_return_val_if_fail (GLADE_IS_PROPERTY_CLASS (class), FALSE); return (GLADE_IS_PARAM_SPEC_OBJECTS (class->pspec) || (G_IS_PARAM_SPEC_OBJECT(class->pspec) && class->pspec->value_type != GDK_TYPE_PIXBUF && class->pspec->value_type != GTK_TYPE_ADJUSTMENT)); } /** * glade_property_class_get_displayable_value: * @class: the property class to search in * @value: the value to search * * Search a displayable values for @value in this property class. * * Returns: a (gchar *) if a diplayable value was found, otherwise NULL. */ const gchar * glade_property_class_get_displayable_value(GladePropertyClass *class, gint value) { gint i, len; GArray *disp_val = class->displayable_values; if (disp_val == NULL) return NULL; len = disp_val->len; for (i = 0; i < len; i++) if (g_array_index (disp_val, GEnumValue, i).value == value) return g_array_index (disp_val, GEnumValue, i).value_name; return NULL; } /** * gpc_get_displayable_values_from_node: * @node: a GLADE_TAG_DISPLAYABLE_VALUES node * @values: an array of the values wich node overrides. * @n_values: the size of @values * * Returns: a (GArray *) of GEnumValue of the overridden fields. */ static GArray * gpc_get_displayable_values_from_node (GladeXmlNode *node, GEnumValue *values, gint n_values, const gchar *domain) { GArray *array; GladeXmlNode *child; if ((child = glade_xml_search_child (node, GLADE_TAG_VALUE)) == NULL) return NULL; array = g_array_new (FALSE, TRUE, sizeof(GEnumValue)); child = glade_xml_node_get_children (node); while (child != NULL) { gint i; gchar *id, *name, *nick; GEnumValue val; id = glade_xml_get_property_string_required (child, GLADE_TAG_ID, NULL); name = glade_xml_get_property_string (child, GLADE_TAG_NAME); nick = glade_xml_get_property_string (child, GLADE_TAG_NICK); for(i=0; i < n_values; i++) { if(strcmp (id, values[i].value_name) == 0) { val=values[i]; /* Tedious memory handleing; if gettext doesn't return * a translation, dont free the untranslated string. */ if(name) { val.value_name = dgettext (domain, name); if (name != val.value_name) g_free (name); } if(nick) { val.value_nick = dgettext (domain, nick); if (nick != val.value_nick) g_free (nick); } g_array_append_val(array, val); break; } } g_free(id); child = glade_xml_node_next (child); } return array; } /** * glade_property_class_make_adjustment: * @property_class: a pointer to the property class * * Creates and appropriate GtkAdjustment for use in the editor * * Returns: An appropriate #GtkAdjustment for use in the Property editor */ GtkAdjustment * glade_property_class_make_adjustment (GladePropertyClass *property_class) { gdouble min = 0, max = 0, def = 0; gboolean float_range = FALSE; g_return_val_if_fail (property_class != NULL, NULL); g_return_val_if_fail (property_class->pspec != NULL, NULL); if (G_IS_PARAM_SPEC_INT(property_class->pspec)) { min = (gdouble)((GParamSpecInt *) property_class->pspec)->minimum; max = (gdouble)((GParamSpecInt *) property_class->pspec)->maximum; def = (gdouble)((GParamSpecInt *) property_class->pspec)->default_value; } else if (G_IS_PARAM_SPEC_UINT(property_class->pspec)) { min = (gdouble)((GParamSpecUInt *) property_class->pspec)->minimum; max = (gdouble)((GParamSpecUInt *) property_class->pspec)->maximum; def = (gdouble)((GParamSpecUInt *) property_class->pspec)->default_value; } else if (G_IS_PARAM_SPEC_LONG(property_class->pspec)) { min = (gdouble)((GParamSpecLong *) property_class->pspec)->minimum; max = (gdouble)((GParamSpecLong *) property_class->pspec)->maximum; def = (gdouble)((GParamSpecLong *) property_class->pspec)->default_value; } else if (G_IS_PARAM_SPEC_ULONG(property_class->pspec)) { min = (gdouble)((GParamSpecULong *) property_class->pspec)->minimum; max = (gdouble)((GParamSpecULong *) property_class->pspec)->maximum; def = (gdouble)((GParamSpecULong *) property_class->pspec)->default_value; } else if (G_IS_PARAM_SPEC_INT64(property_class->pspec)) { min = (gdouble)((GParamSpecInt64 *) property_class->pspec)->minimum; max = (gdouble)((GParamSpecInt64 *) property_class->pspec)->maximum; def = (gdouble)((GParamSpecInt64 *) property_class->pspec)->default_value; } else if (G_IS_PARAM_SPEC_UINT64(property_class->pspec)) { min = (gdouble)((GParamSpecUInt64 *) property_class->pspec)->minimum; max = (gdouble)((GParamSpecUInt64 *) property_class->pspec)->maximum; def = (gdouble)((GParamSpecUInt64 *) property_class->pspec)->default_value; } else if (G_IS_PARAM_SPEC_FLOAT(property_class->pspec)) { float_range = TRUE; min = (gdouble)((GParamSpecFloat *) property_class->pspec)->minimum; max = (gdouble)((GParamSpecFloat *) property_class->pspec)->maximum; def = (gdouble)((GParamSpecFloat *) property_class->pspec)->default_value; } else if (G_IS_PARAM_SPEC_DOUBLE(property_class->pspec)) { float_range = TRUE; min = (gdouble)((GParamSpecDouble *) property_class->pspec)->minimum; max = (gdouble)((GParamSpecDouble *) property_class->pspec)->maximum; def = (gdouble)((GParamSpecDouble *) property_class->pspec)->default_value; } else { g_critical ("Can't make adjustment for pspec type %s", g_type_name(G_PARAM_SPEC_TYPE (property_class->pspec))); } return (GtkAdjustment *)gtk_adjustment_new (def, min, max, float_range ? GLADE_FLOATING_STEP_INCREMENT : GLADE_NUMERICAL_STEP_INCREMENT, GLADE_NUMERICAL_PAGE_INCREMENT, GLADE_NUMERICAL_PAGE_SIZE); } /** * glade_property_class_update_from_node: * @node: the property node * @module: a #GModule to lookup symbols from the plugin * @object_type: the #GType of the owning object * @property_class: a pointer to the property class * @domain: the domain to translate catalog strings from * * Updates the @property_class with the contents of the node in the xml * file. Only the values found in the xml file are overridden. * * Returns: %TRUE on success. @property_class is set to NULL if the property * has Disabled="TRUE". */ gboolean glade_property_class_update_from_node (GladeXmlNode *node, GModule *module, GType object_type, GladePropertyClass **property_class, const gchar *domain) { GladePropertyClass *class; gchar *buff; GladeXmlNode *child; g_return_val_if_fail (property_class != NULL, FALSE); /* for code cleanliness... */ class = *property_class; g_return_val_if_fail (GLADE_IS_PROPERTY_CLASS (class), FALSE); g_return_val_if_fail (glade_xml_node_verify (node, GLADE_TAG_PROPERTY), FALSE); /* check the id */ buff = glade_xml_get_property_string_required (node, GLADE_TAG_ID, NULL); if (!buff) return FALSE; g_free (buff); /* If Disabled="TRUE" we set *property_class to NULL, but we return TRUE. * The caller may want to remove this property from its list. */ if (glade_xml_get_property_boolean (node, GLADE_TAG_DISABLED, FALSE)) { glade_property_class_free (class); *property_class = NULL; return TRUE; } /* ...the spec... */ buff = glade_xml_get_value_string (node, GLADE_TAG_SPEC); if (buff) { /* ... get the tooltip from the pspec ... */ if ((class->pspec = glade_utils_get_pspec_from_funcname (buff)) != NULL) { /* Make sure we can tell properties apart by there * owning class. */ class->pspec->owner_type = object_type; if (class->tooltip) g_free (class->tooltip); if (class->name) g_free (class->name); class->tooltip = g_strdup (g_param_spec_get_blurb (class->pspec)); class->name = g_strdup (g_param_spec_get_nick (class->pspec)); if (class->pspec->flags & G_PARAM_CONSTRUCT_ONLY) class->construct_only = TRUE; if (class->def) { g_value_unset (class->def); g_free (class->def); } class->def = glade_property_class_get_default_from_spec (class->pspec); if (class->orig_def == NULL) class->orig_def = glade_property_class_get_default_from_spec (class->pspec); } g_free (buff); } else if (!class->pspec) { /* If catalog file didn't specify a pspec function * and this property isn't found by introspection * we simply handle it as a property that has been * disabled. */ glade_property_class_free (class); *property_class = NULL; return TRUE; } /* Get the default */ if ((buff = glade_xml_get_property_string (node, GLADE_TAG_DEFAULT)) != NULL) { if (class->def) { g_value_unset (class->def); g_free (class->def); } class->def = glade_property_class_make_gvalue_from_string (class, buff, NULL); g_free (buff); } /* If needed, update the name... */ if ((buff = glade_xml_get_property_string (node, GLADE_TAG_NAME)) != NULL) { g_free (class->name); class->name = g_strdup (dgettext (domain, buff)); } /* ...and the tooltip */ if ((buff = glade_xml_get_value_string (node, GLADE_TAG_TOOLTIP)) != NULL) { g_free (class->tooltip); class->tooltip = g_strdup (dgettext (domain, buff)); } /* If this property's value is an enumeration then we try to get the displayable values */ if (G_IS_PARAM_SPEC_ENUM(class->pspec)) { GEnumClass *eclass = g_type_class_ref(class->pspec->value_type); child = glade_xml_search_child (node, GLADE_TAG_DISPLAYABLE_VALUES); if (child) class->displayable_values = gpc_get_displayable_values_from_node (child, eclass->values, eclass->n_values, domain); g_type_class_unref(eclass); } /* the same way if it is a Flags property */ if (G_IS_PARAM_SPEC_FLAGS(class->pspec)) { GFlagsClass *fclass = g_type_class_ref(class->pspec->value_type); child = glade_xml_search_child (node, GLADE_TAG_DISPLAYABLE_VALUES); if (child) class->displayable_values = gpc_get_displayable_values_from_node (child, (GEnumValue*)fclass->values, fclass->n_values, domain); g_type_class_unref(fclass); } /* Visible lines */ glade_xml_get_value_int (node, GLADE_TAG_VISIBLE_LINES, &class->visible_lines); /* Get the Parameters */ if ((child = glade_xml_search_child (node, GLADE_TAG_PARAMETERS)) != NULL) class->parameters = glade_parameter_list_new_from_node (class->parameters, child); /* Whether or not the property is translatable. This is only used for * string properties. */ class->translatable = glade_xml_get_property_boolean (node, GLADE_TAG_TRANSLATABLE, class->translatable); /* common, optional, etc */ class->common = glade_xml_get_property_boolean (node, GLADE_TAG_COMMON, class->common); class->optional = glade_xml_get_property_boolean (node, GLADE_TAG_OPTIONAL, class->optional); class->query = glade_xml_get_property_boolean (node, GLADE_TAG_QUERY, class->query); class->save = glade_xml_get_property_boolean (node, GLADE_TAG_SAVE, class->save); class->visible = glade_xml_get_property_boolean (node, GLADE_TAG_VISIBLE, class->visible); class->ignore = glade_xml_get_property_boolean (node, GLADE_TAG_IGNORE, class->ignore); class->resource = glade_xml_get_property_boolean (node, GLADE_TAG_RESOURCE, class->resource); class->weight = glade_xml_get_property_double (node, GLADE_TAG_WEIGHT, class->weight); class->transfer_on_paste = glade_xml_get_property_boolean (node, GLADE_TAG_TRANSFER_ON_PASTE, class->transfer_on_paste); /* No atk introspection here. */ if (glade_xml_get_property_boolean (node, GLADE_TAG_ATK_ACTION, FALSE)) class->type = GPC_ATK_ACTION; else if (glade_xml_get_property_boolean (node, GLADE_TAG_ATK_PROPERTY, FALSE)) class->type = GPC_ATK_PROPERTY; /* Special case pixbuf here. */ if (class->pspec->value_type == GDK_TYPE_PIXBUF) class->resource = TRUE; if (class->optional) class->optional_default = glade_xml_get_property_boolean (node, GLADE_TAG_OPTIONAL_DEFAULT, class->optional_default); /* Get any delagate functions for accessing this property */ glade_xml_load_sym_from_node (node, module, GLADE_TAG_SET_FUNCTION, (gpointer *)&class->set_function); glade_xml_load_sym_from_node (node, module, GLADE_TAG_GET_FUNCTION, (gpointer *)&class->get_function); glade_xml_load_sym_from_node (node, module, GLADE_TAG_VERIFY_FUNCTION, (gpointer *)&class->verify_function); /* notify that we changed the property class */ class->is_modified = TRUE; return TRUE; } /** * glade_property_class_match: * @class: a #GladePropertyClass * @comp: a #GladePropertyClass * * Returns: whether @class and @comp are a match or not * (properties in seperate decendant heirarchies that * have the same name are not matches). */ gboolean glade_property_class_match (GladePropertyClass *class, GladePropertyClass *comp) { g_return_val_if_fail (class != NULL, FALSE); g_return_val_if_fail (comp != NULL, FALSE); return (strcmp (class->id, comp->id) == 0 && class->packing == comp->packing && class->pspec->owner_type == comp->pspec->owner_type); } /** * glade_property_class_void_value: * @class: a #GladePropertyClass * * Returns: Whether @value for this @class is voided; a voided value * can be a %NULL value for boxed or object type param specs. */ gboolean glade_property_class_void_value (GladePropertyClass *class, GValue *value) { g_return_val_if_fail (GLADE_IS_PROPERTY_CLASS (class), FALSE); if (G_IS_PARAM_SPEC_OBJECT (class->pspec) && g_value_get_object (value) == NULL) return TRUE; else if (G_IS_PARAM_SPEC_BOXED (class->pspec) && g_value_get_boxed (value) == NULL) return TRUE; return FALSE; }