summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2022-05-06 07:48:28 -0400
committerMatthias Clasen <mclasen@redhat.com>2022-05-06 09:29:44 -0400
commitc2e8604805416a60607c4655cce0ed5c54609835 (patch)
tree8780f3d06f1f85e06d787067bcad9206bc01b55f
parent1a488722faf260e34b6ccdf35bf4d85b2eaa2d33 (diff)
downloadgtk+-c2e8604805416a60607c4655cce0ed5c54609835.tar.gz
treestore: Copy liststore buildable implementation
This add support for data, but does not allow nesting yet.
-rw-r--r--gtk/gtktreestore.c253
1 files changed, 224 insertions, 29 deletions
diff --git a/gtk/gtktreestore.c b/gtk/gtktreestore.c
index 137f76a215..83c83072c1 100644
--- a/gtk/gtktreestore.c
+++ b/gtk/gtktreestore.c
@@ -177,11 +177,11 @@ static gboolean gtk_tree_store_buildable_custom_tag_start (GtkBuildable *b
const char *tagname,
GtkBuildableParser *parser,
gpointer *data);
-static void gtk_tree_store_buildable_custom_finished (GtkBuildable *buildable,
+static void gtk_tree_store_buildable_custom_tag_end (GtkBuildable *buildable,
GtkBuilder *builder,
GObject *child,
const char *tagname,
- gpointer user_data);
+ gpointer parser_data);
static void gtk_tree_store_move (GtkTreeStore *tree_store,
GtkTreeIter *iter,
@@ -275,7 +275,7 @@ void
gtk_tree_store_buildable_init (GtkBuildableIface *iface)
{
iface->custom_tag_start = gtk_tree_store_buildable_custom_tag_start;
- iface->custom_finished = gtk_tree_store_buildable_custom_finished;
+ iface->custom_tag_end = gtk_tree_store_buildable_custom_tag_end;
}
static void
@@ -3316,9 +3316,24 @@ validate_gnode (GNode* node)
* </columns>
*/
typedef struct {
+ gboolean translatable;
+ char *context;
+ int id;
+} ColInfo;
+
+typedef struct {
GtkBuilder *builder;
GObject *object;
GSList *column_type_names;
+ GType *column_types;
+ GValue *values;
+ int *colids;
+ ColInfo **columns;
+ int last_row;
+ int n_columns;
+ int row_column;
+ gboolean is_data;
+ const char *domain;
} SubParserData;
static void
@@ -3331,16 +3346,84 @@ tree_store_start_element (GtkBuildableParseContext *context,
{
SubParserData *data = (SubParserData*)user_data;
- if (strcmp (element_name, "columns") == 0)
+ if (strcmp (element_name, "col") == 0)
{
- if (!_gtk_builder_check_parent (data->builder, context, "object", error))
+ int id = -1;
+ const char *id_str;
+ const char *msg_context = NULL;
+ gboolean translatable = FALSE;
+ ColInfo *info;
+ GValue val = G_VALUE_INIT;
+
+ if (!_gtk_builder_check_parent (data->builder, context, "row", error))
+ return;
+
+ if (data->row_column >= data->n_columns)
+ {
+ g_set_error (error,
+ GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_VALUE,
+ "Too many columns, maximum is %d", data->n_columns - 1);
+ _gtk_builder_prefix_error (data->builder, context, error);
+ return;
+ }
+
+ if (!g_markup_collect_attributes (element_name, names, values, error,
+ G_MARKUP_COLLECT_STRING, "id", &id_str,
+ G_MARKUP_COLLECT_BOOLEAN|G_MARKUP_COLLECT_OPTIONAL, "translatable", &translatable,
+ G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "comments", NULL,
+ G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "context", &msg_context,
+ G_MARKUP_COLLECT_INVALID))
+ {
+ _gtk_builder_prefix_error (data->builder, context, error);
+ return;
+ }
+
+ if (!gtk_builder_value_from_string_type (data->builder, G_TYPE_INT, id_str, &val, error))
+ {
+ _gtk_builder_prefix_error (data->builder, context, error);
+ return;
+ }
+
+ id = g_value_get_int (&val);
+ if (id < 0 || id >= data->n_columns)
+ {
+ g_set_error (error,
+ GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_VALUE,
+ "id value %d out of range", id);
+ _gtk_builder_prefix_error (data->builder, context, error);
+ return;
+ }
+
+ info = g_slice_new0 (ColInfo);
+ info->translatable = translatable;
+ info->context = g_strdup (msg_context);
+ info->id = id;
+
+ data->colids[data->row_column] = id;
+ data->columns[data->row_column] = info;
+ data->row_column++;
+ data->is_data = TRUE;
+ }
+ else if (strcmp (element_name, "row") == 0)
+ {
+ if (!_gtk_builder_check_parent (data->builder, context, "data", error))
return;
if (!g_markup_collect_attributes (element_name, names, values, error,
G_MARKUP_COLLECT_INVALID, NULL, NULL,
G_MARKUP_COLLECT_INVALID))
_gtk_builder_prefix_error (data->builder, context, error);
+ }
+ else if (strcmp (element_name, "columns") == 0 ||
+ strcmp (element_name, "data") == 0)
+ {
+ if (!_gtk_builder_check_parent (data->builder, context, "object", error))
+ return;
+ if (!g_markup_collect_attributes (element_name, names, values, error,
+ G_MARKUP_COLLECT_INVALID, NULL, NULL,
+ G_MARKUP_COLLECT_INVALID))
+ _gtk_builder_prefix_error (data->builder, context, error);
}
else if (strcmp (element_name, "column") == 0)
{
@@ -3359,6 +3442,7 @@ tree_store_start_element (GtkBuildableParseContext *context,
data->column_type_names = g_slist_prepend (data->column_type_names, g_strdup (type));
}
+
else
{
_gtk_builder_error_unhandled_tag (data->builder, context,
@@ -3377,16 +3461,41 @@ tree_store_end_element (GtkBuildableParseContext *context,
g_assert(data->builder);
- if (strcmp (element_name, "columns") == 0)
+ if (strcmp (element_name, "row") == 0)
+ {
+ GtkTreeIter iter;
+ int i;
+
+ gtk_tree_store_insert_with_valuesv (GTK_TREE_STORE (data->object),
+ &iter,
+ NULL,
+ data->last_row,
+ data->colids,
+ data->values,
+ data->row_column);
+ for (i = 0; i < data->row_column; i++)
+ {
+ ColInfo *info = data->columns[i];
+ g_free (info->context);
+ g_slice_free (ColInfo, info);
+ data->columns[i] = NULL;
+ g_value_unset (&data->values[i]);
+ }
+ g_free (data->values);
+ data->values = g_new0 (GValue, data->n_columns);
+ data->last_row++;
+ data->row_column = 0;
+ }
+ else if (strcmp (element_name, "columns") == 0)
{
+ GType *column_types;
GSList *l;
- GType *types;
int i;
GType type;
data = (SubParserData*)user_data;
data->column_type_names = g_slist_reverse (data->column_type_names);
- types = g_new0 (GType, g_slist_length (data->column_type_names));
+ column_types = g_new0 (GType, g_slist_length (data->column_type_names));
for (l = data->column_type_names, i = 0; l; l = l->next, i++)
{
@@ -3398,23 +3507,72 @@ tree_store_end_element (GtkBuildableParseContext *context,
gtk_buildable_get_buildable_id (GTK_BUILDABLE (data->object)));
continue;
}
- types[i] = type;
+ column_types[i] = type;
g_free (l->data);
}
- gtk_tree_store_set_column_types (GTK_TREE_STORE (data->object), i, types);
+ gtk_tree_store_set_column_types (GTK_TREE_STORE (data->object), i, column_types);
- g_free (types);
+ g_free (column_types);
+ }
+ else if (strcmp (element_name, "col") == 0)
+ {
+ data->is_data = FALSE;
}
}
-static const GtkBuildableParser tree_store_parser =
- {
- tree_store_start_element,
- tree_store_end_element
- };
+static void
+tree_store_text (GtkBuildableParseContext *context,
+ const char *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ SubParserData *data = (SubParserData*)user_data;
+ int i;
+ char *string;
+ ColInfo *info;
+
+ if (!data->is_data)
+ return;
+
+ i = data->row_column - 1;
+ info = data->columns[i];
+
+ string = g_strndup (text, text_len);
+ if (info->translatable && text_len)
+ {
+ char *translated;
+ /* FIXME: This will not use the domain set in the .ui file,
+ * since the parser is not telling the builder about the domain.
+ * However, it will work for gtk_builder_set_translation_domain() calls.
+ */
+ translated = g_strdup (_gtk_builder_parser_translate (data->domain,
+ info->context,
+ string));
+ g_free (string);
+ string = translated;
+ }
+
+ if (!gtk_builder_value_from_string_type (data->builder,
+ data->column_types[info->id],
+ string,
+ &data->values[i],
+ error))
+ {
+ _gtk_builder_prefix_error (data->builder, context, error);
+ }
+ g_free (string);
+}
+
+static const GtkBuildableParser tree_store_parser =
+{
+ tree_store_start_element,
+ tree_store_end_element,
+ tree_store_text
+};
static gboolean
gtk_tree_store_buildable_custom_tag_start (GtkBuildable *buildable,
@@ -3441,24 +3599,61 @@ gtk_tree_store_buildable_custom_tag_start (GtkBuildable *buildable,
return TRUE;
}
+ else if (strcmp (tagname, "data") == 0)
+ {
+ int n_columns = gtk_tree_store_get_n_columns (GTK_TREE_MODEL (buildable));
+ if (n_columns == 0)
+ g_error ("Cannot append data to an empty model");
+
+ data = g_slice_new0 (SubParserData);
+ data->builder = builder;
+ data->object = G_OBJECT (buildable);
+ data->values = g_new0 (GValue, n_columns);
+ data->colids = g_new0 (int, n_columns);
+ data->columns = g_new0 (ColInfo *, n_columns);
+ data->column_types = GTK_TREE_STORE (buildable)->priv->column_headers;
+ data->n_columns = n_columns;
+ data->last_row = 0;
+ data->domain = gtk_builder_get_translation_domain (builder);
+
+ *parser = tree_store_parser;
+ *parser_data = data;
+
+ return TRUE;
+ }
return FALSE;
}
static void
-gtk_tree_store_buildable_custom_finished (GtkBuildable *buildable,
- GtkBuilder *builder,
- GObject *child,
- const char *tagname,
- gpointer user_data)
+gtk_tree_store_buildable_custom_tag_end (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const char *tagname,
+ gpointer parser_data)
{
- SubParserData *data;
-
- if (strcmp (tagname, "columns"))
- return;
+ SubParserData *data = (SubParserData*)parser_data;
- data = (SubParserData*)user_data;
-
- g_slist_free (data->column_type_names);
- g_slice_free (SubParserData, data);
+ if (strcmp (tagname, "columns") == 0)
+ {
+ g_slist_free (data->column_type_names);
+ g_slice_free (SubParserData, data);
+ }
+ else if (strcmp (tagname, "data") == 0)
+ {
+ int i;
+ for (i = 0; i < data->n_columns; i++)
+ {
+ ColInfo *info = data->columns[i];
+ if (info)
+ {
+ g_free (info->context);
+ g_slice_free (ColInfo, info);
+ }
+ }
+ g_free (data->colids);
+ g_free (data->columns);
+ g_free (data->values);
+ g_slice_free (SubParserData, data);
+ }
}