From c337e2af1880b2833b8bd7180c02eac192f9d86b Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Sun, 30 Jun 2013 11:07:02 -0400 Subject: Reimplement e_table_specification_load_from_string(). New parser implementation that uses GMarkupParser instead of libxml2. --- e-util/e-table-specification.c | 390 ++++++++++++++++++++++++++++++++++++++++- e-util/e-table-specification.h | 20 +-- 2 files changed, 392 insertions(+), 18 deletions(-) (limited to 'e-util') diff --git a/e-util/e-table-specification.c b/e-util/e-table-specification.c index 40d4a54d63..ff02d3b08e 100644 --- a/e-util/e-table-specification.c +++ b/e-util/e-table-specification.c @@ -42,6 +42,368 @@ G_DEFINE_TYPE ( e_table_specification, G_TYPE_OBJECT) +static void +table_specification_start_specification (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + ETableSpecification *specification, + GError **error) +{ + const gchar *cursor_mode = NULL; + const gchar *selection_mode = NULL; + gboolean fallback_draw_grid = FALSE; + gboolean missing; + + g_free (specification->click_to_add_message); + specification->click_to_add_message = NULL; + + g_free (specification->domain); + specification->domain = NULL; + + /* Use G_MARKUP_COLLECT_TRISTATE to identify + * missing attributes that default to TRUE. */ + g_markup_collect_attributes ( + element_name, + attribute_names, + attribute_values, + error, + + G_MARKUP_COLLECT_TRISTATE, + "alternating-row-colors", + &specification->alternating_row_colors, + + G_MARKUP_COLLECT_BOOLEAN | + G_MARKUP_COLLECT_OPTIONAL, + "no-headers", + &specification->no_headers, + + G_MARKUP_COLLECT_BOOLEAN | + G_MARKUP_COLLECT_OPTIONAL, + "click-to-add", + &specification->click_to_add, + + G_MARKUP_COLLECT_BOOLEAN | + G_MARKUP_COLLECT_OPTIONAL, + "click-to-add-end", + &specification->click_to_add_end, + + G_MARKUP_COLLECT_TRISTATE, + "horizontal-draw-grid", + &specification->horizontal_draw_grid, + + G_MARKUP_COLLECT_TRISTATE, + "vertical-draw-grid", + &specification->vertical_draw_grid, + + G_MARKUP_COLLECT_BOOLEAN | + G_MARKUP_COLLECT_OPTIONAL, + "draw-grid", + &fallback_draw_grid, + + G_MARKUP_COLLECT_TRISTATE, + "draw-focus", + &specification->draw_focus, + + G_MARKUP_COLLECT_BOOLEAN | + G_MARKUP_COLLECT_OPTIONAL, + "horizontal-scrolling", + &specification->horizontal_scrolling, + + G_MARKUP_COLLECT_BOOLEAN | + G_MARKUP_COLLECT_OPTIONAL, + "horizontal-resize", + &specification->horizontal_resize, + + G_MARKUP_COLLECT_TRISTATE, + "allow-grouping", + &specification->allow_grouping, + + G_MARKUP_COLLECT_STRING | + G_MARKUP_COLLECT_OPTIONAL, + "selection-mode", + &selection_mode, + + G_MARKUP_COLLECT_STRING | + G_MARKUP_COLLECT_OPTIONAL, + "cursor-mode", + &cursor_mode, + + G_MARKUP_COLLECT_STRDUP | + G_MARKUP_COLLECT_OPTIONAL, + "_click-to-add-message", + &specification->click_to_add_message, + + G_MARKUP_COLLECT_STRDUP | + G_MARKUP_COLLECT_OPTIONAL, + "gettext-domain", + &specification->domain, + + G_MARKUP_COLLECT_INVALID); + + /* Additional tweaks. */ + + missing = + (specification->alternating_row_colors != TRUE) && + (specification->alternating_row_colors != FALSE); + if (missing) + specification->alternating_row_colors = TRUE; + + if (!specification->click_to_add) + specification->click_to_add_end = FALSE; + + missing = + (specification->horizontal_draw_grid != TRUE) && + (specification->horizontal_draw_grid != FALSE); + if (missing) + specification->horizontal_draw_grid = fallback_draw_grid; + + missing = + (specification->vertical_draw_grid != TRUE) && + (specification->vertical_draw_grid != FALSE); + if (missing) + specification->vertical_draw_grid = fallback_draw_grid; + + missing = + (specification->draw_focus != TRUE) && + (specification->draw_focus != FALSE); + if (missing) + specification->draw_focus = TRUE; + + missing = + (specification->allow_grouping != TRUE) && + (specification->allow_grouping != FALSE); + if (missing) + specification->allow_grouping = TRUE; + + if (selection_mode == NULL) /* attribute missing */ + specification->selection_mode = GTK_SELECTION_MULTIPLE; + else if (g_ascii_strcasecmp (selection_mode, "single") == 0) + specification->selection_mode = GTK_SELECTION_SINGLE; + else if (g_ascii_strcasecmp (selection_mode, "browse") == 0) + specification->selection_mode = GTK_SELECTION_BROWSE; + else if (g_ascii_strcasecmp (selection_mode, "extended") == 0) + specification->selection_mode = GTK_SELECTION_MULTIPLE; + else /* unrecognized attribute value */ + specification->selection_mode = GTK_SELECTION_MULTIPLE; + + if (cursor_mode == NULL) /* attribute missing */ + specification->cursor_mode = E_CURSOR_SIMPLE; + else if (g_ascii_strcasecmp (cursor_mode, "line") == 0) + specification->cursor_mode = E_CURSOR_LINE; + else if (g_ascii_strcasecmp (cursor_mode, "spreadsheet") == 0) + specification->cursor_mode = E_CURSOR_SPREADSHEET; + else /* unrecognized attribute value */ + specification->cursor_mode = E_CURSOR_SIMPLE; + + if (specification->domain != NULL && *specification->domain == '\0') { + g_free (specification->domain); + specification->domain = NULL; + } +} + +static void +table_specification_start_column (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + GPtrArray *columns, + GError **error) +{ + ETableColumnSpecification *column_spec; + const gchar *model_col_str = NULL; + const gchar *compare_col_str = NULL; + const gchar *expansion_str = NULL; + const gchar *minimum_width_str = NULL; + const gchar *priority_str = NULL; + gint64 int_value; + gboolean missing; + + column_spec = e_table_column_specification_new (); + + /* Use G_MARKUP_COLLECT_TRISTATE to identify + * missing attributes that default to TRUE. */ + g_markup_collect_attributes ( + element_name, + attribute_names, + attribute_values, + error, + + G_MARKUP_COLLECT_STRING | + G_MARKUP_COLLECT_OPTIONAL, + "model_col", + &model_col_str, + + G_MARKUP_COLLECT_STRING | + G_MARKUP_COLLECT_OPTIONAL, + "compare_col", + &compare_col_str, + + G_MARKUP_COLLECT_STRDUP | + G_MARKUP_COLLECT_OPTIONAL, + "_title", + &column_spec->title, + + G_MARKUP_COLLECT_STRDUP | + G_MARKUP_COLLECT_OPTIONAL, + "pixbuf", + &column_spec->pixbuf, + + G_MARKUP_COLLECT_STRING | + G_MARKUP_COLLECT_OPTIONAL, + "expansion", + &expansion_str, + + G_MARKUP_COLLECT_STRING | + G_MARKUP_COLLECT_OPTIONAL, + "minimum_width", + &minimum_width_str, + + G_MARKUP_COLLECT_BOOLEAN | + G_MARKUP_COLLECT_OPTIONAL, + "resizable", + &column_spec->resizable, + + G_MARKUP_COLLECT_BOOLEAN | + G_MARKUP_COLLECT_OPTIONAL, + "disabled", + &column_spec->disabled, + + G_MARKUP_COLLECT_STRDUP | + G_MARKUP_COLLECT_OPTIONAL, + "cell", + &column_spec->cell, + + G_MARKUP_COLLECT_STRDUP | + G_MARKUP_COLLECT_OPTIONAL, + "compare", + &column_spec->compare, + + G_MARKUP_COLLECT_STRDUP | + G_MARKUP_COLLECT_OPTIONAL, + "search", + &column_spec->search, + + G_MARKUP_COLLECT_TRISTATE, + "sortable", + &column_spec->sortable, + + G_MARKUP_COLLECT_STRING | + G_MARKUP_COLLECT_OPTIONAL, + "priority", + &priority_str, + + G_MARKUP_COLLECT_INVALID); + + /* Additional tweaks. */ + + if (model_col_str != NULL) { + int_value = g_ascii_strtoll (model_col_str, NULL, 10); + column_spec->model_col = (gint) int_value; + column_spec->compare_col = (gint) int_value; + } + + if (compare_col_str != NULL) { + int_value = g_ascii_strtoll (compare_col_str, NULL, 10); + column_spec->compare_col = (gint) int_value; + } + + if (column_spec->title == NULL) + column_spec->title = g_strdup (""); + + if (expansion_str != NULL) + column_spec->expansion = g_ascii_strtod (expansion_str, NULL); + + if (minimum_width_str != NULL) { + int_value = g_ascii_strtoll (minimum_width_str, NULL, 10); + column_spec->minimum_width = (gint) int_value; + } + + if (priority_str != NULL) { + int_value = g_ascii_strtoll (priority_str, NULL, 10); + column_spec->priority = (gint) int_value; + } + + missing = + (column_spec->sortable != TRUE) && + (column_spec->sortable != FALSE); + if (missing) + column_spec->sortable = TRUE; + + g_ptr_array_add (columns, g_object_ref (column_spec)); + + g_object_unref (column_spec); +} + +static void +table_specification_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + ETableSpecification *specification; + GPtrArray *columns; + + specification = E_TABLE_SPECIFICATION (user_data); + columns = e_table_specification_ref_columns (specification); + + if (g_str_equal (element_name, "ETableSpecification")) + table_specification_start_specification ( + context, + element_name, + attribute_names, + attribute_values, + specification, + error); + + if (g_str_equal (element_name, "ETableColumn")) + table_specification_start_column ( + context, + element_name, + attribute_names, + attribute_values, + columns, + error); + + if (g_str_equal (element_name, "ETableState")) + e_table_state_parse_context_push (context, specification); + + g_ptr_array_unref (columns); +} + +static void +table_specification_end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + ETableSpecification *specification; + + specification = E_TABLE_SPECIFICATION (user_data); + + if (g_str_equal (element_name, "ETableState")) { + ETableState *state; + + state = e_table_state_parse_context_pop (context); + g_return_if_fail (E_IS_TABLE_STATE (state)); + + g_clear_object (&specification->state); + specification->state = g_object_ref (state); + + g_object_unref (state); + } +} + +static const GMarkupParser table_specification_parser = { + table_specification_start_element, + table_specification_end_element, + NULL, + NULL, + NULL +}; + static void table_specification_dispose (GObject *object) { @@ -229,19 +591,31 @@ gboolean e_table_specification_load_from_string (ETableSpecification *specification, const gchar *xml) { - xmlDoc *doc; + GMarkupParseContext *context; gboolean success = FALSE; g_return_val_if_fail (E_IS_TABLE_SPECIFICATION (specification), FALSE); g_return_val_if_fail (xml != NULL, FALSE); - doc = xmlParseMemory ((gchar *) xml, strlen (xml)); - if (doc != NULL) { - xmlNode *node = xmlDocGetRootElement (doc); - e_table_specification_load_from_node (specification, node); - xmlFreeDoc (doc); - success = TRUE; - } + g_ptr_array_set_size (specification->priv->columns, 0); + g_clear_object (&specification->state); + + context = g_markup_parse_context_new ( + &table_specification_parser, 0, + g_object_ref (specification), + (GDestroyNotify) g_object_unref); + + if (g_markup_parse_context_parse (context, xml, -1, NULL)) + success = g_markup_parse_context_end_parse (context, NULL); + + g_markup_parse_context_free (context); + + if (specification->state == NULL) + specification->state = e_table_state_vanilla (specification); + + e_table_sort_info_set_can_group ( + specification->state->sort_info, + specification->allow_grouping); return success; } diff --git a/e-util/e-table-specification.h b/e-util/e-table-specification.h index 09b86c3791..bce9c38f6a 100644 --- a/e-util/e-table-specification.h +++ b/e-util/e-table-specification.h @@ -61,16 +61,16 @@ struct _ETableSpecification { ETableState *state; - guint alternating_row_colors : 1; - guint no_headers : 1; - guint click_to_add : 1; - guint click_to_add_end : 1; - guint horizontal_draw_grid : 1; - guint vertical_draw_grid : 1; - guint draw_focus : 1; - guint horizontal_scrolling : 1; - guint horizontal_resize : 1; - guint allow_grouping : 1; + gboolean alternating_row_colors; + gboolean no_headers; + gboolean click_to_add; + gboolean click_to_add_end; + gboolean horizontal_draw_grid; + gboolean vertical_draw_grid; + gboolean draw_focus; + gboolean horizontal_scrolling; + gboolean horizontal_resize; + gboolean allow_grouping; GtkSelectionMode selection_mode; ECursorMode cursor_mode; -- cgit v1.2.3