Commit f1bcd418 authored by Tristan Van Berkom's avatar Tristan Van Berkom
Browse files

* plugins/gtk+/glade-gtk.c:

	  - Check for type compatibility before setting cell renderer attributes
	  - Clear cell renderer attributes before setting liststore column types and resync them after
	    (Avoids cricital warnings where the underlying data types changed and dont match the properties
	    of the renderers)
	  - Fill in the gaps in model data while loading some columns with non serializable types
	    (fixes severe bug: model data was loaded with missing columns of data).

	* plugins/gtk+/glade-column-types.c, plugins/gtk+/glade-model-data.c:
	  allow model data with explicitly G_TYPE_INVALID types.
parent 799a017d
......@@ -14,6 +14,12 @@
- Substitute the old manual evaluation with GPC_VERSION_CHECK()
- Avoid critical warnings when setting GtkColorButton properties to NULL
- Avoid critical warnings when setting GtkComboBoxEntry::text-column < 0
- Check for type compatibility before setting cell renderer attributes
- Clear cell renderer attributes before setting liststore column types and resync them after
(Avoids cricital warnings where the underlying data types changed and dont match the properties
of the renderers)
- Fill in the gaps in model data while loading some columns with non serializable types
(fixes severe bug: model data was loaded with missing columns of data).
* gladeui/glade-property-class.h: Created convenience macro GPC_VERSION_CHECK
......@@ -22,6 +28,9 @@
assume a path that is: ${prefix}/lib/glade3/modules/../../ and search it after the initial
module search path.
* plugins/gtk+/glade-column-types.c, plugins/gtk+/glade-model-data.c:
allow model data with explicitly G_TYPE_INVALID types.
2010-03-26 Tristan Van Berkom <tvb@gnome.org>
* gladeui/glade-palette.c: Left aligned and ellipsize end widget group titles (restored normal
......
......@@ -145,7 +145,7 @@ glade_column_list_copy (GList *list)
for (l = list; l; l = g_list_next (l))
{
GladeColumnType *new_data = g_new0(GladeColumnType, 1);
GladeColumnType *new_data = g_slice_new0 (GladeColumnType);
GladeColumnType *data = l->data;
new_data->type_name = g_strdup (data->type_name);
......@@ -162,7 +162,7 @@ glade_column_type_free (GladeColumnType *column)
{
g_free (column->type_name);
g_free (column->column_name);
g_free (column);
g_slice_free (GladeColumnType, column);
}
void
......@@ -286,8 +286,7 @@ eprop_column_adjust_rows (GladeEditorProperty *eprop, GList *columns)
column = list->data;
if ((data_type = g_type_from_name (column->type_name)) == G_TYPE_INVALID)
data_type = G_TYPE_POINTER;
data_type = g_type_from_name (column->type_name);
if ((idx = glade_model_data_column_index (data_tree, column->column_name)) < 0)
{
......@@ -324,7 +323,7 @@ eprop_column_append (GladeEditorProperty *eprop,
if (columns)
columns = glade_column_list_copy (columns);
data = g_new0 (GladeColumnType, 1);
data = g_slice_new0 (GladeColumnType);
data->column_name = g_strdup (column_name);
data->type_name = g_strdup (type_name);
......
......@@ -10139,15 +10139,167 @@ glade_gtk_icon_factory_create_editable (GladeWidgetAdaptor *adaptor,
#define GLADE_TAG_DATA "data"
#define GLADE_TAG_COL "col"
static gboolean
glade_gtk_cell_layout_has_renderer (GtkCellLayout *layout,
GtkCellRenderer *renderer)
{
GList *cells = gtk_cell_layout_get_cells (layout);
gboolean has_renderer;
has_renderer = (g_list_find (cells, renderer) != NULL);
g_list_free (cells);
return has_renderer;
}
static gboolean
glade_gtk_cell_renderer_sync_attributes (GObject *object)
{
GtkCellLayout *layout;
GtkCellRenderer *cell;
GladeWidget *widget = glade_widget_get_from_gobject (object);
GladeWidget *gmodel;
GladeProperty *property;
gchar *attr_prop_name;
GList *l, *column_list = NULL;
gint columns = 0;
static gint attr_len = 0;
if (!attr_len)
attr_len = strlen ("attr-");
/* Apply attributes to renderer when bound to a model in runtime */
widget = glade_widget_get_from_gobject (object);
if (widget->parent == NULL) return FALSE;
/* When creating widgets, sometimes the parent is set before parenting happens,
* here we have to be careful for that..
*/
layout = GTK_CELL_LAYOUT (widget->parent->object);
cell = GTK_CELL_RENDERER (object);
if (!glade_gtk_cell_layout_has_renderer (layout, cell))
return FALSE;
if ((gmodel = glade_cell_renderer_get_model (widget)) == NULL)
return FALSE;
glade_widget_property_get (gmodel, "columns", &column_list);
columns = g_list_length (column_list);
gtk_cell_layout_clear_attributes (layout, cell);
for (l = widget->properties; l; l = l->next)
{
property = l->data;
if (strncmp (property->klass->id, "attr-", attr_len) == 0)
{
GladeProperty *attr_prop;
gint column = g_value_get_int (property->value);
attr_prop_name = &property->klass->id[attr_len];
attr_prop = glade_widget_get_property (widget, attr_prop_name);
if (column >= 0 && column < columns)
{
GladeColumnType *column_type = (GladeColumnType *)g_list_nth_data (column_list, column);
GType column_gtype = g_type_from_name (column_type->type_name);
if (column_gtype &&
g_value_type_transformable (column_gtype, attr_prop->klass->pspec->value_type))
gtk_cell_layout_add_attribute (layout, cell, attr_prop_name, column);
}
}
}
return FALSE;
}
static gboolean
glade_gtk_cell_layout_sync_attributes (GObject *layout)
{
GladeWidget *gwidget = glade_widget_get_from_gobject (layout);
GObject *cell;
GList *children, *l;
children = glade_widget_adaptor_get_children (gwidget->adaptor, layout);
for (l = children; l; l = l->next)
{
cell = l->data;
if (!GTK_IS_CELL_RENDERER (cell))
continue;
glade_gtk_cell_renderer_sync_attributes (cell);
}
g_list_free (children);
return FALSE;
}
static gboolean
glade_gtk_cell_layout_clear_attributes (GObject *layout)
{
GladeWidget *gwidget = glade_widget_get_from_gobject (layout);
GObject *cell;
GList *children, *l;
children = glade_widget_adaptor_get_children (gwidget->adaptor, layout);
for (l = children; l; l = l->next)
{
cell = l->data;
if (!GTK_IS_CELL_RENDERER (cell))
continue;
gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (layout),
GTK_CELL_RENDERER (cell));
}
g_list_free (children);
return FALSE;
}
static void
glade_gtk_store_set_columns (GObject *object,
const GValue *value)
{
GList *l = g_value_get_boxed (value);
gint i, n = g_list_length (l);
GType *types = g_new (GType, n);
GladeWidget *widget = glade_widget_get_from_gobject (object);
GList *l;
gint i, n;
GType *types;
/* Clear the attributes for all cell renderers referring to this store */
for (l = widget->prop_refs; l; l = l->next)
{
GladeWidget *referring_widget = GLADE_PROPERTY (l->data)->widget;
if (GTK_IS_CELL_LAYOUT (referring_widget->object))
glade_gtk_cell_layout_clear_attributes (referring_widget->object);
else if (GTK_IS_TREE_VIEW (referring_widget->object))
{
GList *list, *children =
glade_widget_adaptor_get_children (referring_widget->adaptor,
referring_widget->object);
for (list = children; list; list = list->next)
{
/* Clear the GtkTreeViewColumns... */
if (GTK_IS_CELL_LAYOUT (l->data))
glade_gtk_cell_layout_clear_attributes (G_OBJECT (l->data));
}
g_list_free (children);
}
}
for (i = 0; l; l = g_list_next (l), i++)
/* Apply new column types */
for (i = 0, l = g_value_get_boxed (value), n = g_list_length (l), types = g_new (GType, n);
l; l = g_list_next (l), i++)
{
GladeColumnType *data = l->data;
......@@ -10161,6 +10313,33 @@ glade_gtk_store_set_columns (GObject *object,
gtk_list_store_set_column_types (GTK_LIST_STORE (object), n, types);
else
gtk_tree_store_set_column_types (GTK_TREE_STORE (object), n, types);
g_free (types);
/* Reset the attributes for all cell renderers referring to this store */
for (l = widget->prop_refs; l; l = l->next)
{
GladeWidget *referring_widget = GLADE_PROPERTY (l->data)->widget;
if (GTK_IS_CELL_LAYOUT (referring_widget->object))
glade_gtk_cell_layout_sync_attributes (referring_widget->object);
else if (GTK_IS_TREE_VIEW (referring_widget->object))
{
GList *list, *children =
glade_widget_adaptor_get_children (referring_widget->adaptor,
referring_widget->object);
for (list = children; list; list = list->next)
{
/* Clear the GtkTreeViewColumns... */
if (GTK_IS_CELL_LAYOUT (l->data))
glade_gtk_cell_layout_sync_attributes (G_OBJECT (l->data));
}
g_list_free (children);
}
}
}
static void
......@@ -10207,8 +10386,8 @@ glade_gtk_store_set_data (GObject *object,
* and a sync will come soon with the right values
*/
column_type = gtk_tree_model_get_column_type (GTK_TREE_MODEL (object), colnum);
if (!g_type_is_a (G_VALUE_TYPE (&data->value), column_type))
break;
if (G_VALUE_TYPE (&data->value) != column_type)
continue;
if (GTK_IS_LIST_STORE (object))
gtk_list_store_set_value (GTK_LIST_STORE (object),
......@@ -10327,7 +10506,10 @@ glade_gtk_store_string_from_value (GladeWidgetAdaptor *adaptor,
{
data = iter->data;
if (G_VALUE_TYPE (&data->value) != G_TYPE_POINTER)
if (!G_VALUE_TYPE (&data->value) ||
G_VALUE_TYPE (&data->value) == G_TYPE_INVALID)
str = g_strdup ("(virtual)");
else if (G_VALUE_TYPE (&data->value) != G_TYPE_POINTER)
str = glade_utils_string_from_value (&data->value, fmt);
else
str = g_strdup ("(null)");
......@@ -10430,8 +10612,9 @@ glade_gtk_store_write_data (GladeWidget *widget,
data = iter->data;
/* Skip inserializable data */
if (G_VALUE_TYPE (&data->value) == G_TYPE_POINTER)
/* Skip non-serializable data */
if (G_VALUE_TYPE (&data->value) == 0 ||
G_VALUE_TYPE (&data->value) == G_TYPE_POINTER)
continue;
string = glade_utils_string_from_value (&data->value,
......@@ -10562,7 +10745,7 @@ glade_gtk_store_read_data (GladeWidget *widget, GladeXmlNode *node)
GNode *data_tree, *row, *item;
GladeModelData *data;
GValue *value;
GList *column_types = NULL, *list;
GList *column_types = NULL;
GladeColumnType *column_type;
gint colnum;
......@@ -10591,15 +10774,34 @@ glade_gtk_store_read_data (GladeWidget *widget, GladeXmlNode *node)
for (colnum = 0, col_node = glade_xml_node_get_children (row_node); col_node;
col_node = glade_xml_node_next (col_node))
{
gint read_column;
if (!glade_xml_node_verify (col_node, GLADE_TAG_COL))
continue;
if (!(list = g_list_nth (column_types, colnum)))
/* XXX Log this too... */
read_column = glade_xml_get_property_int (col_node, GLADE_TAG_ID, -1);
if (read_column < 0)
{
g_critical ("Parsed negative column id");
continue;
}
/* Catch up for gaps in the list where unserializable types are involved */
while (colnum < read_column)
{
column_type = g_list_nth_data (column_types, colnum);
column_type = list->data;
data = glade_model_data_new (G_TYPE_INVALID, column_type->column_name);
item = g_node_new (data);
g_node_append (row, item);
colnum++;
}
if (!(column_type = g_list_nth_data (column_types, colnum)))
/* XXX Log this too... */
continue;
/* Ignore unloaded column types for the workspace */
if (g_type_from_name (column_type->type_name) != G_TYPE_INVALID)
......@@ -10612,7 +10814,8 @@ glade_gtk_store_read_data (GladeWidget *widget, GladeXmlNode *node)
(g_type_from_name (column_type->type_name), value_str, widget->project, widget);
g_free (value_str);
data = glade_model_data_new (g_type_from_name (column_type->type_name), column_type->column_name);
data = glade_model_data_new (g_type_from_name (column_type->type_name),
column_type->column_name);
g_value_copy (value, &data->value);
g_value_unset (value);
......@@ -10620,10 +10823,9 @@ glade_gtk_store_read_data (GladeWidget *widget, GladeXmlNode *node)
}
else
{
data = glade_model_data_new (G_TYPE_POINTER, column_type->column_name);
data = glade_model_data_new (G_TYPE_INVALID, column_type->column_name);
}
data->name = g_strdup (column_type->column_name);
data->i18n_translatable = glade_xml_get_property_boolean (col_node, GLADE_TAG_TRANSLATABLE, FALSE);
data->i18n_context = glade_xml_get_property_string (col_node, GLADE_TAG_CONTEXT);
data->i18n_comment = glade_xml_get_property_string (col_node, GLADE_TAG_COMMENT);
......@@ -10688,97 +10890,13 @@ glade_gtk_cell_renderer_action_activate (GladeWidgetAdaptor *adaptor,
}
static gboolean
glade_gtk_cell_layout_has_renderer (GtkCellLayout *layout,
GtkCellRenderer *renderer)
{
GList *cells = gtk_cell_layout_get_cells (layout);
gboolean has_renderer;
has_renderer = (g_list_find (cells, renderer) != NULL);
g_list_free (cells);
return has_renderer;
}
static void
glade_gtk_cell_renderer_sync_attributes (GObject *object)
{
GtkCellLayout *layout;
GtkCellRenderer *cell;
GladeWidget *widget = glade_widget_get_from_gobject (object);
GladeWidget *gmodel;
GladeProperty *property;
gchar *attr_prop_name;
GList *l;
gint columns = 0;
static gint attr_len = 0;
if (!attr_len)
attr_len = strlen ("attr-");
/* Apply attributes to renderer when bound to a model in runtime */
widget = glade_widget_get_from_gobject (object);
if (widget->parent == NULL) return;
/* When creating widgets, sometimes the parent is set before parenting happens,
* here we have to be careful for that..
*/
layout = GTK_CELL_LAYOUT (widget->parent->object);
cell = GTK_CELL_RENDERER (object);
if (!glade_gtk_cell_layout_has_renderer (layout, cell))
return;
if ((gmodel = glade_cell_renderer_get_model (widget)) != NULL)
{
GList *column_list = NULL;
glade_widget_property_get (gmodel, "columns", &column_list);
columns = g_list_length (column_list);
}
gtk_cell_layout_clear_attributes (layout, cell);
for (l = widget->properties; l; l = l->next)
{
property = l->data;
if (strncmp (property->klass->id, "attr-", attr_len) == 0)
{
attr_prop_name = &property->klass->id[attr_len];
/* XXX TODO: Check that the cell supports the data type in the indexed column.
*
* use: gtk_tree_model_get_column_type (icon_view->priv->model, column)
*/
if (g_value_get_int (property->value) >= 0 &&
/* We have to set attributes before parenting when loading */
(glade_widget_superuser () || g_value_get_int (property->value) < columns))
gtk_cell_layout_add_attribute (layout, cell,
attr_prop_name,
g_value_get_int (property->value));
}
}
}
static gboolean
sync_attributes_idle (GladeWidget *gwidget)
{
glade_gtk_cell_renderer_sync_attributes (gwidget->object);
return FALSE;
}
static void
renderer_format_changed (GladeProject *project,
GParamSpec *pspec,
GladeWidget *gwidget)
{
if (glade_project_get_format (project) == GLADE_PROJECT_FORMAT_GTKBUILDER)
g_idle_add ((GSourceFunc)sync_attributes_idle, gwidget);
g_idle_add ((GSourceFunc)glade_gtk_cell_renderer_sync_attributes, gwidget->object);
}
static void
......@@ -11231,6 +11349,8 @@ glade_gtk_cell_layout_read_child (GladeWidgetAdaptor *adaptor,
glade_widget_add_child (widget, child_widget, FALSE);
glade_gtk_cell_renderer_read_attributes (child_widget, node);
g_idle_add ((GSourceFunc)glade_gtk_cell_renderer_sync_attributes, child_widget->object);
}
}
}
......@@ -11303,25 +11423,6 @@ glade_gtk_cell_layout_write_child (GladeWidgetAdaptor *adaptor,
glade_gtk_cell_renderer_write_attributes (widget, context, child_node);
}
static void
glade_gtk_cell_layout_sync_attributes (GObject *layout)
{
GladeWidget *gwidget = glade_widget_get_from_gobject (layout);
GObject *cell;
GList *children, *l;
children = glade_widget_adaptor_get_children (gwidget->adaptor, layout);
for (l = children; l; l = l->next)
{
cell = l->data;
if (!GTK_IS_CELL_RENDERER (cell))
continue;
glade_gtk_cell_renderer_sync_attributes (cell);
}
g_list_free (children);
}
static gchar *
glade_gtk_cell_layout_get_display_name (GladeBaseEditor *editor,
GladeWidget *gchild,
......
......@@ -37,7 +37,8 @@ glade_model_data_new (GType type, const gchar *column_name)
{
GladeModelData *data = g_new0 (GladeModelData, 1);
g_value_init (&data->value, type);
if (type != 0)
g_value_init (&data->value, type);
if (type == G_TYPE_STRING)
data->i18n_translatable = TRUE;
......@@ -55,8 +56,11 @@ glade_model_data_copy (GladeModelData *data)
GladeModelData *dup = g_new0 (GladeModelData, 1);
g_value_init (&dup->value, G_VALUE_TYPE (&data->value));
g_value_copy (&data->value, &dup->value);
if (G_VALUE_TYPE (&data->value) != 0)
{
g_value_init (&dup->value, G_VALUE_TYPE (&data->value));
g_value_copy (&data->value, &dup->value);
}
dup->name = g_strdup (data->name);
......@@ -72,7 +76,8 @@ glade_model_data_free (GladeModelData *data)
{
if (data)
{
g_value_unset (&data->value);
if (G_VALUE_TYPE (&data->value) != 0)
g_value_unset (&data->value);
g_free (data->name);
g_free (data->i18n_context);
......@@ -561,7 +566,7 @@ eprop_model_data_generate_store (GladeEditorProperty *eprop)
GArray *gtypes = g_array_new (FALSE, TRUE, sizeof (GType));
GtkTreeIter iter;
gint column_num, row_num;
GType index_type = G_TYPE_INT, string_type = G_TYPE_STRING;
GType index_type = G_TYPE_INT, string_type = G_TYPE_STRING, pointer_type = G_TYPE_POINTER;
glade_property_get (eprop->property, &data_tree);
......@@ -573,7 +578,9 @@ eprop_model_data_generate_store (GladeEditorProperty *eprop)
for (iter_node = data_tree->children->children; iter_node; iter_node = iter_node->next)
{
iter_data = iter_node->data;
if (G_VALUE_TYPE (&iter_data->value) == GDK_TYPE_PIXBUF)
if (G_VALUE_TYPE (&iter_data->value) == 0)
g_array_append_val (gtypes, pointer_type);
else if (G_VALUE_TYPE (&iter_data->value) == GDK_TYPE_PIXBUF)
g_array_append_val (gtypes, string_type);
else
g_array_append_val (gtypes, G_VALUE_TYPE (&iter_data->value));
......@@ -595,6 +602,9 @@ eprop_model_data_generate_store (GladeEditorProperty *eprop)
{
iter_data = iter_node->data;
if (G_VALUE_TYPE (&iter_data->value) == 0)
continue;
/* Special case, show the filename in the cellrenderertext */
if (G_VALUE_TYPE (&iter_data->value) == GDK_TYPE_PIXBUF)
{
......@@ -838,12 +848,14 @@ eprop_model_generate_column (GladeEditorProperty *eprop,
GtkCellRenderer *renderer = NULL;
GtkAdjustment *adjustment;
GtkListStore *store;
GType type = G_VALUE_TYPE (&data->value);
GType type = G_TYPE_INVALID;
gtk_tree_view_column_set_title (column, data->name);
gtk_tree_view_column_set_resizable (column, TRUE);
gtk_tree_view_column_set_expand (column, TRUE);
type = G_VALUE_TYPE (&data->value);
/* Support enum and flag types, and a hardcoded list of fundamental types */
if (type == G_TYPE_CHAR ||
type == G_TYPE_UCHAR ||
......
......@@ -30,7 +30,7 @@ struct _GladeModelData
{
GValue value;
gchar *name;
gboolean i18n_translatable;
gchar *i18n_context;
gchar *i18n_comment;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment