static void parse_template (GMarkupParseContext *context, ParserData *data, const gchar *element_name, const gchar **names, const gchar **values, GError **error) { ObjectInfo *object_info; const gchar *object_class = NULL; const gchar *parent_class = NULL; gint line; GType template_type; GType parsed_type; template_type = _gtk_builder_get_template_type (data->builder); if (!g_markup_collect_attributes (element_name, names, values, error, G_MARKUP_COLLECT_STRING, "class", &object_class, G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "parent", &parent_class, G_MARKUP_COLLECT_INVALID)) { _gtk_builder_prefix_error (data->builder, data->ctx, error); return; } if (template_type == 0) { g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_UNHANDLED_TAG, "Not expecting to handle a template (class '%s', parent '%s')", object_class, parent_class ? parent_class : "GtkWidget"); _gtk_builder_prefix_error (data->builder, context, error); return; } else if (state_peek (data) != NULL) { error_invalid_tag (data, "template", NULL, error); return; } parsed_type = g_type_from_name (object_class); if (template_type != parsed_type) { g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_TEMPLATE_MISMATCH, "Parsed template definition for type '%s', expected type '%s'", object_class, g_type_name (template_type)); _gtk_builder_prefix_error (data->builder, context, error); return; } if (parent_class) { GType parent_type = g_type_from_name (parent_class); GType expected_type = g_type_parent (parsed_type); if (parent_type == G_TYPE_INVALID) { g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_VALUE, "Invalid template parent type '%s'", parent_class); _gtk_builder_prefix_error (data->builder, context, error); return; } if (parent_type != expected_type) { g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_TEMPLATE_MISMATCH, "Template parent type '%s' does not match instance parent type '%s'.", parent_class, g_type_name (expected_type)); _gtk_builder_prefix_error (data->builder, context, error); return; } } ++data->cur_object_level; object_info = g_slice_new0 (ObjectInfo); object_info->tag.name = element_name; object_info->type = parsed_type; object_info->oclass = g_type_class_ref (parsed_type); object_info->id = g_strdup (object_class); object_info->object = gtk_builder_get_object (data->builder, object_class); state_push (data, object_info); line = GPOINTER_TO_INT (g_hash_table_lookup (data->object_ids, object_class)); if (line != 0) { g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_DUPLICATE_ID, "Duplicate object ID '%s' (previously on line %d)", object_class, 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_class), GINT_TO_POINTER (line)); }
static void parse_template (GMarkupParseContext *context, ParserData *data, const gchar *element_name, const gchar **names, const gchar **values, GError **error) { ObjectInfo *object_info; int i; gchar *object_class = NULL; gint line, line2; GType template_type = _gtk_builder_get_template_type (data->builder); GType parsed_type; if (template_type == 0) { g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_UNHANDLED_TAG, "Encountered template definition but not parsing a template."); return; } else if (state_peek (data) != NULL) { g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_UNHANDLED_TAG, "Encountered template definition that is not at the top level."); 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], "parent") == 0) /* Ignore 'parent' attribute, however it's needed by Glade */; else { error_invalid_attribute (data, element_name, names[i], error); return; } } if (!object_class) { error_missing_attribute (data, element_name, "class", error); return; } parsed_type = g_type_from_name (object_class); if (template_type != parsed_type) { g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_TEMPLATE_MISMATCH, "Parsed template definition for type `%s', expected type `%s'.", object_class, g_type_name (template_type)); return; } ++data->cur_object_level; object_info = g_slice_new0 (ObjectInfo); object_info->class_name = object_class; object_info->id = g_strdup (object_class); object_info->object = gtk_builder_get_object (data->builder, object_class); state_push (data, object_info); object_info->tag.name = element_name; g_markup_parse_context_get_position (context, &line, NULL); line2 = GPOINTER_TO_INT (g_hash_table_lookup (data->object_ids, object_class)); 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_class, line, line2); return; } g_hash_table_insert (data->object_ids, g_strdup (object_class), GINT_TO_POINTER (line)); }