1 #include "eggtreeviewstate.h"
27 GtkTreeViewColumn
*column
;
29 GtkCellRenderer
*cell
;
32 GSList
*cell_attributes
;
36 set_error (GError
**err
,
37 GMarkupParseContext
*context
,
47 g_markup_parse_context_get_position (context
, &line
, &ch
);
49 va_start (args
, format
);
50 str
= g_strdup_vprintf (format
, args
);
53 g_set_error (err
, error_domain
, error_code
,
54 _("Line %d character %d: %s"),
61 peek_state (ParseInfo
*info
)
63 g_return_val_if_fail (info
->states
!= NULL
, STATE_START
);
65 return GPOINTER_TO_INT (info
->states
->data
);
69 push_state (ParseInfo
*info
,
72 info
->states
= g_slist_prepend (info
->states
, GINT_TO_POINTER (state
));
76 pop_state (ParseInfo
*info
)
78 g_return_if_fail (info
->states
!= NULL
);
80 info
->states
= g_slist_remove (info
->states
, info
->states
->data
);
84 parse_info_init (ParseInfo
*info
)
86 info
->states
= g_slist_prepend (NULL
, GINT_TO_POINTER (STATE_START
));
87 info
->cell_attributes
= NULL
;
91 #define MAX_REASONABLE 4096
93 parse_integer (const char *str
,
95 GMarkupParseContext
*context
,
103 l
= strtol (str
, &end
, 10);
105 if (end
== NULL
|| end
== str
)
107 set_error (error
, context
, G_MARKUP_ERROR
,
108 G_MARKUP_ERROR_PARSE
,
109 _("Could not parse \"%s\" as an integer"),
116 set_error (error
, context
, G_MARKUP_ERROR
,
117 G_MARKUP_ERROR_PARSE
,
118 _("Did not understand trailing characters \"%s\" in string \"%s\""),
125 set_error (error
, context
, G_MARKUP_ERROR
,
126 G_MARKUP_ERROR_PARSE
,
127 _("Integer %ld must be positive"), l
);
131 if (l
> MAX_REASONABLE
)
133 set_error (error
, context
, G_MARKUP_ERROR
,
134 G_MARKUP_ERROR_PARSE
,
135 _("Integer %ld is too large, current max is %d"),
140 g_value_init (value
, G_TYPE_INT
);
141 g_value_set_int (value
, (int)l
);
147 parse_string (const char *str
,
149 GMarkupParseContext
*context
,
155 g_value_init (value
, G_TYPE_STRING
);
156 g_value_set_string (value
, str
);
162 parse_boolean (const char *str
,
164 GMarkupParseContext
*context
,
167 if (strcmp ("true", str
) == 0)
169 g_value_init (value
, G_TYPE_BOOLEAN
);
170 g_value_set_boolean (value
, TRUE
);
172 else if (strcmp ("false", str
) == 0)
174 g_value_init (value
, G_TYPE_BOOLEAN
);
175 g_value_set_boolean (value
, FALSE
);
179 set_error (error
, context
, G_MARKUP_ERROR
,
180 G_MARKUP_ERROR_PARSE
,
181 _("Boolean values must be \"true\" or \"false\" not \"%s\""),
190 parse_enum (const gchar
*str
,
192 GParamSpecEnum
*pspec
,
193 GMarkupParseContext
*context
,
196 GEnumValue
*enum_value
;
198 enum_value
= g_enum_get_value_by_nick (pspec
->enum_class
, str
);
202 set_error (error
, context
, G_MARKUP_ERROR
,
203 G_MARKUP_ERROR_PARSE
,
204 _("The value \"%s\" is not part of the enum \"%s\""),
206 G_ENUM_CLASS_TYPE_NAME (pspec
->enum_class
));
210 g_value_init (value
, G_ENUM_CLASS_TYPE (pspec
->enum_class
));
211 g_value_set_enum (value
, enum_value
->value
);
218 parse_value (const gchar
*string
,
221 GMarkupParseContext
*context
,
224 if (G_IS_PARAM_SPEC_BOOLEAN (pspec
))
225 return parse_boolean (string
, value
, context
, error
);
226 else if (G_IS_PARAM_SPEC_INT (pspec
))
227 return parse_integer (string
, value
, context
, error
);
228 else if (G_IS_PARAM_SPEC_STRING (pspec
))
229 return parse_string (string
, value
, context
, error
);
230 else if (G_IS_PARAM_SPEC_ENUM (pspec
))
231 return parse_enum (string
, value
, G_PARAM_SPEC_ENUM (pspec
), context
, error
);
233 set_error (error
, context
, G_MARKUP_ERROR
, G_MARKUP_ERROR_PARSE
,
234 _("The type \"%s\" can't be parsed from a string"),
235 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec
)));
240 parse_object_property (GObject
*object
,
241 const gchar
*attribute_name
,
242 const gchar
*attribute_value
,
243 GMarkupParseContext
*context
,
247 GValue value
= { 0 };
249 pspec
= g_object_class_find_property (G_OBJECT_GET_CLASS (object
), attribute_name
);
253 set_error (error
, context
, G_MARKUP_ERROR
,
254 G_MARKUP_ERROR_PARSE
,
255 _("The property \"%s\" does not exist"),
260 if (!parse_value (attribute_value
, &value
, pspec
, context
, error
))
263 g_object_set_property (object
, attribute_name
, &value
);
264 g_value_unset (&value
);
270 parse_object_properties (GObject
*object
,
271 const gchar
**attribute_names
,
272 const gchar
**attribute_values
,
273 GMarkupParseContext
*context
,
278 for (i
= 0; attribute_names
[i
] != NULL
; i
++)
280 if (!parse_object_property (object
, attribute_names
[i
], attribute_values
[i
], context
, error
))
288 parse_cell_element (GMarkupParseContext
*context
,
289 const gchar
**attribute_names
,
290 const gchar
**attribute_values
,
295 GtkCellRenderer
*cell
= NULL
;
297 info
->pack_start
= TRUE
;
300 /* We first need to traverse the attributes looking for a type */
301 for (i
= 0; attribute_names
[i
]; i
++)
303 if (strcmp (attribute_names
[i
], "type") == 0)
309 set_error (error
, context
, G_MARKUP_ERROR
, G_MARKUP_ERROR_PARSE
,
310 _("The type attribute can only be specified once."));
314 type
= g_type_from_name (attribute_values
[i
]);
316 if (type
== G_TYPE_INVALID
)
318 set_error (error
, context
, G_MARKUP_ERROR
, G_MARKUP_ERROR_PARSE
,
319 _("The type \"%s\" is not a valid type."),
320 attribute_values
[i
]);
324 if (!g_type_is_a (type
, GTK_TYPE_CELL_RENDERER
))
326 set_error (error
, context
, G_MARKUP_ERROR
, G_MARKUP_ERROR_PARSE
,
327 _("The type \"%s\" is not a cell renderer type."),
332 cell
= g_object_new (type
, NULL
);
338 set_error (error
, context
, G_MARKUP_ERROR
, G_MARKUP_ERROR_PARSE
,
339 _("No type attribute specified."));
343 for (i
= 0; attribute_names
[i
]; i
++)
345 if (strcmp (attribute_names
[i
], "type") == 0)
347 else if (strcmp (attribute_names
[i
], "pack_start") == 0)
349 GValue value
= { 0 };
351 if (!parse_boolean (attribute_values
[i
], &value
, context
, error
))
354 info
->pack_start
= g_value_get_boolean (&value
);
356 else if (strcmp (attribute_names
[i
], "expand") == 0)
358 GValue value
= { 0 };
360 if (!parse_boolean (attribute_values
[i
], &value
, context
, error
))
363 info
->expand
= g_value_get_boolean (&value
);
367 if (strstr (attribute_values
[i
], "model:") == attribute_values
[i
])
370 GValue value
= { 0 };
372 if (!parse_integer (attribute_values
[i
] + strlen ("model:"), &value
, context
, error
))
375 attr
= g_new (CellAttribute
, 1);
376 attr
->name
= g_strdup (attribute_names
[i
]);
377 attr
->column
= g_value_get_int (&value
);
378 g_value_unset (&value
);
380 info
->cell_attributes
= g_slist_prepend (info
->cell_attributes
, attr
);
384 if (!parse_object_property (G_OBJECT (cell
),
394 push_state (info
, STATE_CELL
);
399 parse_column_element (GMarkupParseContext
*context
,
400 const gchar
**attribute_names
,
401 const gchar
**attribute_values
,
405 GtkTreeViewColumn
*column
;
407 column
= gtk_tree_view_column_new ();
409 if (!parse_object_properties (G_OBJECT (column
),
416 push_state (info
, STATE_COLUMN
);
418 info
->column
= column
;
422 parse_treeview_element (GMarkupParseContext
*context
,
423 const gchar
**attribute_names
,
424 const gchar
**attribute_values
,
428 if (!parse_object_properties (G_OBJECT (info
->view
),
435 push_state (info
, STATE_TREEVIEW
);
439 start_element_handler (GMarkupParseContext
*context
,
440 const gchar
*element_name
,
441 const gchar
**attribute_names
,
442 const gchar
**attribute_values
,
446 ParseInfo
*info
= user_data
;
448 switch (peek_state (info
))
451 if (strcmp (element_name
, "treeview_state") == 0)
453 push_state (info
, STATE_TREEVIEW_STATE
);
456 set_error (error
, context
, G_MARKUP_ERROR
, G_MARKUP_ERROR_PARSE
,
457 _("Outermost element in theme must be <treeview_state> not <%s>"),
460 case STATE_TREEVIEW_STATE
:
461 if (strcmp (element_name
, "treeview") == 0)
463 parse_treeview_element (context
, attribute_names
, attribute_values
, info
, error
);
466 set_error (error
, context
, G_MARKUP_ERROR
, G_MARKUP_ERROR_PARSE
,
467 _("Element inside of <treeview_state> must be <treeview> not <%s>"),
471 if (strcmp (element_name
, "column") == 0)
473 parse_column_element (context
, attribute_names
, attribute_values
, info
, error
);
476 set_error (error
, context
, G_MARKUP_ERROR
, G_MARKUP_ERROR_PARSE
,
477 _("Element inside of <treeview> must be <column> not <%s>"),
482 if (strcmp (element_name
, "cell") == 0)
484 parse_cell_element (context
, attribute_names
, attribute_values
, info
, error
);
487 set_error (error
, context
, G_MARKUP_ERROR
, G_MARKUP_ERROR_PARSE
,
488 _("Element inside of <column> must be <cell> not <%s>"),
493 set_error (error
, context
, G_MARKUP_ERROR
, G_MARKUP_ERROR_PARSE
,
494 _("The <cell> element must not have any children."));
500 end_element_handler (GMarkupParseContext
*context
,
501 const gchar
*element_name
,
505 ParseInfo
*info
= user_data
;
508 switch (peek_state (info
))
512 case STATE_TREEVIEW_STATE
:
514 g_assert (peek_state (info
) == STATE_START
);
518 g_assert (peek_state (info
) == STATE_TREEVIEW_STATE
);
521 g_assert (info
->column
);
523 gtk_tree_view_append_column (info
->view
, info
->column
);
526 g_assert (peek_state (info
) == STATE_TREEVIEW
);
529 g_assert (info
->cell
);
531 if (info
->pack_start
)
532 gtk_tree_view_column_pack_start (info
->column
, info
->cell
,
535 gtk_tree_view_column_pack_end (info
->column
, info
->cell
,
538 for (list
= info
->cell_attributes
; list
; list
= list
->next
)
540 CellAttribute
*attr
= list
->data
;
542 gtk_tree_view_column_add_attribute (info
->column
, info
->cell
,
549 g_slist_free (info
->cell_attributes
);
550 info
->cell_attributes
= NULL
;
553 g_assert (peek_state (info
) == STATE_COLUMN
);
558 static GMarkupParser parser
=
560 start_element_handler
,
567 egg_tree_view_state_apply_from_string (GtkTreeView
*tree_view
, const gchar
*string
, GError
**err
)
569 GMarkupParseContext
*context
;
570 GError
*error
= NULL
;
574 parse_info_init (&info
);
575 info
.view
= tree_view
;
577 context
= g_markup_parse_context_new (&parser
, 0, &info
, NULL
);
579 retval
= g_markup_parse_context_parse (context
, string
, -1, &error
);
591 egg_tree_view_state_add_cell_renderer_type (GType type
)
593 /* Do nothing, this is just to have the types registered */