forked from AuroraMiddleware/gtk
treestore: Copy liststore buildable implementation
This add support for data, but does not allow nesting yet.
This commit is contained in:
parent
1a488722fa
commit
c2e8604805
@ -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
|
||||
@ -3315,10 +3315,25 @@ validate_gnode (GNode* node)
|
||||
* <column type="..."/>
|
||||
* </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,7 +3346,76 @@ tree_store_start_element (GtkBuildableParseContext *context,
|
||||
{
|
||||
SubParserData *data = (SubParserData*)user_data;
|
||||
|
||||
if (strcmp (element_name, "columns") == 0)
|
||||
if (strcmp (element_name, "col") == 0)
|
||||
{
|
||||
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;
|
||||
@ -3340,7 +3424,6 @@ tree_store_start_element (GtkBuildableParseContext *context,
|
||||
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,
|
||||
@ -3439,6 +3597,28 @@ gtk_tree_store_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
*parser = tree_store_parser;
|
||||
*parser_data = data;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -3446,19 +3626,34 @@ gtk_tree_store_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
}
|
||||
|
||||
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;
|
||||
SubParserData *data = (SubParserData*)parser_data;
|
||||
|
||||
if (strcmp (tagname, "columns"))
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user