static void parse_object (GMarkupParseContext *context, ParserData *data, const gchar *element_name, const gchar **names, const gchar **values, GError **error) { ObjectInfo *object_info; ChildInfo* child_info; GType object_type = G_TYPE_INVALID; const gchar *object_class = NULL; const gchar *constructor = NULL; const gchar *type_func = NULL; const gchar *object_id = NULL; gchar *internal_id = NULL; gint line; child_info = state_peek_info (data, ChildInfo); if (child_info && strcmp (child_info->tag.name, "object") == 0) { error_invalid_tag (data, element_name, NULL, error); return; } if (!g_markup_collect_attributes (element_name, names, values, error, G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "class", &object_class, G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "constructor", &constructor, G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "type-func", &type_func, G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "id", &object_id, G_MARKUP_COLLECT_INVALID)) { _gtk_builder_prefix_error (data->builder, data->ctx, error); return; } if (type_func) { /* Call the GType function, and return the GType, it's guaranteed afterwards * that g_type_from_name on the name will return our GType */ object_type = _get_type_by_symbol (type_func); if (object_type == G_TYPE_INVALID) { g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_TYPE_FUNCTION, "Invalid type function '%s'", type_func); _gtk_builder_prefix_error (data->builder, context, error); return; } } else if (object_class) { object_type = gtk_builder_get_type_from_name (data->builder, object_class); if (object_type == G_TYPE_INVALID) { g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_VALUE, "Invalid object type '%s'", object_class); _gtk_builder_prefix_error (data->builder, context, error); return; } } else { error_missing_attribute (data, element_name, "class", error); return; } if (!object_id) { internal_id = g_strdup_printf ("___object_%d___", ++data->object_counter); object_id = internal_id; } ++data->cur_object_level; /* check if we reached a requested object (if it is specified) */ if (data->requested_objects && !data->inside_requested_object) { if (is_requested_object (object_id, data)) { data->requested_object_level = data->cur_object_level; GTK_NOTE (BUILDER, g_message ("requested object \"%s\" found at level %d", object_id, data->requested_object_level)); data->inside_requested_object = TRUE; } else { g_free (internal_id); return; } } object_info = g_slice_new0 (ObjectInfo); object_info->tag.name = element_name; object_info->type = object_type; object_info->oclass = g_type_class_ref (object_type); object_info->id = (internal_id) ? internal_id : g_strdup (object_id); object_info->constructor = g_strdup (constructor); object_info->parent = (CommonInfo*)child_info; state_push (data, object_info); line = GPOINTER_TO_INT (g_hash_table_lookup (data->object_ids, object_id)); if (line != 0) { g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_DUPLICATE_ID, "Duplicate object ID '%s' (previously on line %d)", object_id, line); _gtk_builder_prefix_error (data->builder, context, error); return; } g_markup_parse_context_get_position (context, &line, NULL); g_hash_table_insert (data->object_ids, g_strdup (object_id), GINT_TO_POINTER (line)); }
static void parse_object (GMarkupParseContext *context, ParserData *data, const gchar *element_name, const gchar **names, const gchar **values, GError **error) { ObjectInfo *object_info; ChildInfo* child_info; int i; gchar *object_class = NULL; gchar *object_id = NULL; gchar *constructor = NULL; gint line, line2; child_info = state_peek_info (data, ChildInfo); if (child_info && strcmp (child_info->tag.name, "object") == 0) { error_invalid_tag (data, element_name, NULL, error); return; } for (i = 0; names[i] != NULL; i++) { if (strcmp (names[i], "class") == 0) object_class = g_strdup (values[i]); else if (strcmp (names[i], "id") == 0) object_id = g_strdup (values[i]); else if (strcmp (names[i], "constructor") == 0) constructor = g_strdup (values[i]); else if (strcmp (names[i], "type-func") == 0) { /* Call the GType function, and return the name of the GType, * it's guaranteed afterwards that g_type_from_name on the name * will return our GType */ object_class = _get_type_by_symbol (values[i]); if (!object_class) { g_markup_parse_context_get_position (context, &line, NULL); g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_TYPE_FUNCTION, _("Invalid type function on line %d: '%s'"), line, values[i]); return; } } else { error_invalid_attribute (data, element_name, names[i], error); return; } } if (!object_class) { error_missing_attribute (data, element_name, "class", error); return; } if (!object_id) { error_missing_attribute (data, element_name, "id", error); return; } ++data->cur_object_level; /* check if we reached a requested object (if it is specified) */ if (data->requested_objects && !data->inside_requested_object) { if (is_requested_object (object_id, data)) { data->requested_object_level = data->cur_object_level; GTK_NOTE (BUILDER, g_print ("requested object \"%s\" found at level %d\n", object_id, data->requested_object_level)); data->inside_requested_object = TRUE; } else { g_free (object_class); g_free (object_id); g_free (constructor); return; } } object_info = g_slice_new0 (ObjectInfo); object_info->class_name = object_class; object_info->id = object_id; object_info->constructor = constructor; state_push (data, object_info); object_info->tag.name = element_name; if (child_info) object_info->parent = (CommonInfo*)child_info; g_markup_parse_context_get_position (context, &line, NULL); line2 = GPOINTER_TO_INT (g_hash_table_lookup (data->object_ids, object_id)); if (line2 != 0) { g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_DUPLICATE_ID, _("Duplicate object id '%s' on line %d (previously on line %d)"), object_id, line, line2); return; } g_hash_table_insert (data->object_ids, g_strdup (object_id), GINT_TO_POINTER (line)); }