glade3 r1967 - in trunk: . gladeui plugins/gtk+



Author: tvb
Date: Wed Oct  1 00:10:23 2008
New Revision: 1967
URL: http://svn.gnome.org/viewvc/glade3?rev=1967&view=rev

Log:

	* gladeui/glade-property.[ch], gladeui/glade-command.[ch], 
	gladeui/glade-editor-property.c: Implemented new "context" i18n
	metadata.

	* gladeui/glade-widget.c: Fixed to hide non-window widgets in glade_widget_hide()



Modified:
   trunk/ChangeLog
   trunk/TODO
   trunk/gladeui/glade-command.c
   trunk/gladeui/glade-command.h
   trunk/gladeui/glade-editor-property.c
   trunk/gladeui/glade-editor-property.h
   trunk/gladeui/glade-property-class.c
   trunk/gladeui/glade-property.c
   trunk/gladeui/glade-property.h
   trunk/gladeui/glade-widget.c
   trunk/gladeui/glade-xml-utils.h
   trunk/plugins/gtk+/glade-column-types.c
   trunk/plugins/gtk+/glade-convert.c
   trunk/plugins/gtk+/glade-gtk.c
   trunk/plugins/gtk+/glade-model-data.c
   trunk/plugins/gtk+/glade-model-data.h
   trunk/plugins/gtk+/gtk+.xml.in

Modified: trunk/TODO
==============================================================================
--- trunk/TODO	(original)
+++ trunk/TODO	Wed Oct  1 00:10:23 2008
@@ -12,7 +12,8 @@
 Sort objects from widgets in the inspector widget.
 
 Make popup work in workspace with no-window widgets
-Take care of external object property references (sync them) at rebuild time
+Remove deleted widgets from the workspace
+Take care of external object property references (sync them) at glade_widget_rebuild time
 Liststore/Treestore data is not translatable
 store data needs improvement and cant be released as is (cant even have spaces in data, needs real new structure).
 

Modified: trunk/gladeui/glade-command.c
==============================================================================
--- trunk/gladeui/glade-command.c	(original)
+++ trunk/gladeui/glade-command.c	Wed Oct  1 00:10:23 2008
@@ -1073,7 +1073,6 @@
 	CommandData				*cdata;
 	GtkWidget                               *placeholder;
 	GList					*list, *l;
-	gchar                                   *desc;
 
 	g_return_if_fail (widgets != NULL);
 
@@ -1098,13 +1097,10 @@
 	GLADE_COMMAND (me)->description = g_strdup ("dummy");
 
 	if (g_list_length (widgets) == 1)
-		desc = g_strdup_printf (_("Remove %s"), 
-					GLADE_WIDGET (widgets->data)->name);
+		glade_command_push_group (_("Remove %s"), 
+					  GLADE_WIDGET (widgets->data)->name);
 	else
-		desc = g_strdup_printf (_("Remove multiple"));
-
-	glade_command_push_group (desc);
-	g_free (desc);
+		glade_command_push_group (_("Remove multiple"));
 
 	for (list = widgets; list && list->data; list = list->next)
 	{
@@ -1956,9 +1952,11 @@
 	GladeProperty *property;
 	gboolean       translatable;
 	gboolean       has_context;
+	gchar         *context;
 	gchar         *comment;
 	gboolean       old_translatable;
 	gboolean       old_has_context;
+	gchar         *old_context;
 	gchar         *old_comment;
 } GladeCommandSetI18n;
 
@@ -1976,6 +1974,7 @@
 	GladeCommandSetI18n *me = (GladeCommandSetI18n *)cmd;
 	gboolean  temp_translatable;
 	gboolean  temp_has_context;
+	gchar    *temp_context;
 	gchar    *temp_comment;
 	
 	/* sanity check */
@@ -1985,17 +1984,21 @@
 	/* set the new values in the property */
 	glade_property_i18n_set_translatable(me->property, me->translatable);	
 	glade_property_i18n_set_has_context(me->property, me->has_context);
+	glade_property_i18n_set_context(me->property, me->context);
 	glade_property_i18n_set_comment(me->property, me->comment);
 
 	/* swap the current values with the old values to prepare for undo */
 	temp_translatable = me->translatable;
 	temp_has_context = me->has_context;
+	temp_context = me->context;
 	temp_comment = me->comment;
 	me->translatable = me->old_translatable;
 	me->has_context = me->old_has_context;
+	me->context = me->old_context;
 	me->comment = me->old_comment;
 	me->old_translatable = temp_translatable;
 	me->old_has_context = temp_has_context;
+	me->old_context = temp_context;
 	me->old_comment = temp_comment;
 	
 	return TRUE;
@@ -2015,7 +2018,9 @@
 	g_return_if_fail(GLADE_IS_COMMAND_SET_I18N(obj));
 
 	me = GLADE_COMMAND_SET_I18N(obj);
+	g_free (me->context);
 	g_free (me->comment);
+	g_free (me->old_context);
 	g_free (me->old_comment);
 	
 	glade_command_finalize(obj);
@@ -2052,8 +2057,11 @@
 	/* adjust this command to contain, as its old values, the other command's current values */
 	this->old_translatable = other->old_translatable;
 	this->old_has_context = other->old_has_context;
+	g_free (this->old_context);
 	g_free (this->old_comment);
+	this->old_context = other->old_context;
 	this->old_comment = other->old_comment;
+	other->old_context = NULL;
 	other->old_comment = NULL;
 
 	glade_app_update_ui ();
@@ -2064,12 +2072,17 @@
  * @property: a #GladeProperty
  * @translatable: a #gboolean
  * @has_context: a #gboolean
+ * @context: a #const gchar *
  * @comment: a #const gchar *
  *
  * Sets the i18n data on the property.
  */
 void
-glade_command_set_i18n (GladeProperty *property, gboolean translatable, gboolean has_context, const gchar *comment)
+glade_command_set_i18n (GladeProperty *property, 
+			gboolean translatable, 
+			gboolean has_context, 
+			const gchar *context,
+			const gchar *comment)
 {
 	GladeCommandSetI18n *me;
 	
@@ -2077,9 +2090,11 @@
 	
 	/* check that something changed before continuing with the command */
 	if (translatable == property->i18n_translatable &&
-		has_context == property->i18n_has_context   &&
-		((comment == NULL && property->i18n_comment == NULL) ||
-		 (comment && property->i18n_comment && !strcmp(property->i18n_comment, comment))))
+	    has_context == property->i18n_has_context   &&
+	    /* XXX add context string shit herex */
+
+	    ((comment == NULL && property->i18n_comment == NULL) ||
+	     (comment && property->i18n_comment && !strcmp(property->i18n_comment, comment))))
 		return;
 
 	/* load up the command */
@@ -2087,9 +2102,11 @@
 	me->property = property;
 	me->translatable = translatable;
 	me->has_context = has_context;
+	me->context = g_strdup(context);
 	me->comment = g_strdup(comment);
 	me->old_translatable = property->i18n_translatable;
 	me->old_has_context = property->i18n_has_context;
+	me->old_context = g_strdup(property->i18n_context);
 	me->old_comment = g_strdup(property->i18n_comment);
 	GLADE_COMMAND(me)->description = g_strdup_printf(_("Setting i18n metadata"));;
 	
@@ -2228,11 +2245,13 @@
 			       GladeProjectFormat  fmt)
 {
 	GladeWidget   *widget;
-	const GList   *objects;
+	const GList   *objects, *list;
+
+	objects = glade_project_get_objects (project);
 
-	for (objects = glade_project_get_objects (project); objects; objects = objects->next)
+	for (list = objects; list; list = list->next)
 	{
-		widget = glade_widget_get_from_gobject (objects->data);
+		widget = glade_widget_get_from_gobject (list->data);
 
 		/* If libglade-only widget going in builder format ... */
 		if ((fmt == GLADE_PROJECT_FORMAT_GTKBUILDER &&
@@ -2280,11 +2299,9 @@
 	if (glade_project_get_format (project) != fmt)
 	{
 		gchar *prj_name = glade_project_get_name (project);
-		gchar *desc = g_strdup_printf (_("Converting %s to %s format"),
-					       prj_name, 
-					       fmt == GLADE_PROJECT_FORMAT_LIBGLADE ? "libglade" : "Gtk+ Builder");
-		glade_command_push_group (desc);
-		g_free (desc);
+		glade_command_push_group (_("Converting %s to %s format"),
+					  prj_name, 
+					  fmt == GLADE_PROJECT_FORMAT_LIBGLADE ? "libglade" : "Gtk+ Builder");
 		g_free (prj_name);
 
 		/* load up the command */
@@ -2305,14 +2322,13 @@
 				catalog  = glade_app_get_catalog (cat_name);
 				
 				glade_catalog_convert_project (catalog, project, fmt);
-
-				glade_command_convert_cleanup (project, fmt);
 				
 				g_free (cat_name);
 			}
 			g_list_free (req_libs);
 		}
-		
+
+		glade_command_convert_cleanup (project, fmt);
 
 		/* execute the command and push it on the stack if successful 
 		 * this sets the actual format

Modified: trunk/gladeui/glade-command.h
==============================================================================
--- trunk/gladeui/glade-command.h	(original)
+++ trunk/gladeui/glade-command.h	Wed Oct  1 00:10:23 2008
@@ -149,9 +149,10 @@
 /************************ set i18n ******************************/
 
 void           glade_command_set_i18n      (GladeProperty     *property,
-                        gboolean translatable,
-                        gboolean has_context,
-                        const gchar *comment);
+					    gboolean translatable,
+					    gboolean has_context,
+					    const gchar *context,
+					    const gchar *comment);
 
 
 G_END_DECLS

Modified: trunk/gladeui/glade-editor-property.c
==============================================================================
--- trunk/gladeui/glade-editor-property.c	(original)
+++ trunk/gladeui/glade-editor-property.c	Wed Oct  1 00:10:23 2008
@@ -1662,25 +1662,43 @@
 	g_free (text);
 }
 
-static void
-glade_eprop_text_show_i18n_dialog (GtkWidget           *entry,
-				   GladeEditorProperty *eprop)
+/**
+ * glade_editor_property_show_i18n_dialog:
+ * @parent: The parent widget for the dialog.
+ * @fmt: the #GladeProjectFormat
+ * @text: A read/write pointer to the text property
+ * @context: A read/write pointer to the translation context
+ * @comment: A read/write pointer to the translator comment
+ * @has_context: A read/write pointer to the context setting (libglade only)
+ * @translatable: A read/write pointer to the translatable setting]
+ *
+ * Runs a dialog and updates the provided values.
+ *
+ * Returns: %TRUE if OK was selected.
+ */
+gboolean
+glade_editor_property_show_i18n_dialog (GtkWidget            *parent,
+					GladeProjectFormat    fmt,
+					gchar               **text,
+					gchar               **context,
+					gchar               **comment,
+					gboolean             *has_context,
+					gboolean             *translatable)
 {
 	GtkWidget     *dialog;
 	GtkWidget     *vbox, *hbox;
 	GtkWidget     *label;
 	GtkWidget     *sw;
 	GtkWidget     *alignment;
-	GtkWidget     *text_view, *comment_view;
-	GtkTextBuffer *text_buffer, *comment_buffer;
+	GtkWidget     *text_view, *comment_view, *context_view;
+	GtkTextBuffer *text_buffer, *comment_buffer, *context_buffer = NULL;
 	GtkWidget     *translatable_button, *context_button;
-	const gchar   *text;
 	gint           res;
-	gchar         *str;
-	GParamSpec    *pspec;
+
+	g_return_val_if_fail (text && context && comment && translatable && has_context, FALSE);
 
 	dialog = gtk_dialog_new_with_buttons (_("Edit Text"),
-					      GTK_WINDOW (gtk_widget_get_toplevel (entry)),
+					      parent ? GTK_WINDOW (gtk_widget_get_toplevel (parent)) : NULL,
 					      GTK_DIALOG_MODAL,
 					      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 					      GTK_STOCK_OK, GTK_RESPONSE_OK,
@@ -1730,11 +1748,10 @@
 
 	text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
 
-	text = g_value_get_string (eprop->property->value);
-	if (text)
+	if (*text)
 	{
 		gtk_text_buffer_set_text (text_buffer,
-					  text,
+					  *text,
 					  -1);
 	}
 
@@ -1744,37 +1761,68 @@
 
 	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
 
+	/* Translatable */
 	translatable_button = gtk_check_button_new_with_mnemonic (_("T_ranslatable"));
 	gtk_widget_show (translatable_button);
 	gtk_box_pack_start (GTK_BOX (hbox), translatable_button, FALSE, FALSE, 0);
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (translatable_button),
-				      glade_property_i18n_get_translatable (eprop->property));
-
-	/* Add a cute tooltip */
-	if ((pspec =
-	     g_object_class_find_property (G_OBJECT_GET_CLASS (eprop->property),
-					   "i18n-translatable")) != NULL)
-		gtk_widget_set_tooltip_text (translatable_button,
-					       g_param_spec_get_blurb (pspec));
-
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (translatable_button), *translatable);
+	gtk_widget_set_tooltip_text (translatable_button,
+				     _("Whether this property is translatable or not"));
+	
+	/* Has Context */
 	context_button = gtk_check_button_new_with_mnemonic (_("_Has context prefix"));
-	gtk_widget_show (context_button);
 	gtk_box_pack_start (GTK_BOX (hbox), context_button, FALSE, FALSE, 0);
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (context_button),
-				      glade_property_i18n_get_has_context (eprop->property));
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (context_button), *has_context);
+	gtk_widget_set_tooltip_text (context_button,
+				     _("Whether or not the translatable string has a context prefix"));
+	if (fmt == GLADE_PROJECT_FORMAT_LIBGLADE)
+		gtk_widget_show (context_button);
 
-	/* Add a cute tooltip */
-	if ((pspec =
-	     g_object_class_find_property (G_OBJECT_GET_CLASS (eprop->property),
-					   "i18n-has-context")) != NULL)
-		gtk_widget_set_tooltip_text (context_button,
-					       g_param_spec_get_blurb (pspec));
+	/* Context. */
+	if (fmt != GLADE_PROJECT_FORMAT_LIBGLADE)
+	{
+		alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+		gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 0, 0, 0);
+		gtk_widget_show (alignment);
+		
+		label = gtk_label_new_with_mnemonic (_("Conte_xt for translation:"));
+		gtk_widget_show (label);
+		gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+		gtk_container_add (GTK_CONTAINER (alignment), label);
+		gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
+		gtk_widget_set_tooltip_text (alignment,
+					     "XXX Some explanation about translation context please ???");
+		
+		sw = gtk_scrolled_window_new (NULL, NULL);
+		gtk_widget_show (sw);
+		gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
+		gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+						GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+		gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
+		
+		context_view = gtk_text_view_new ();
+		gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (context_view), GTK_WRAP_WORD);
+		gtk_widget_show (context_view);
+		
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label), context_view);
+		
+		gtk_container_add (GTK_CONTAINER (sw), context_view);
+		
+		context_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (context_view));
+		
+		if (*context)
+		{
+			gtk_text_buffer_set_text (context_buffer,
+						  *context,
+						  -1);
+		}
+	}
 
+	/* Comments. */
 	alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
 	gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 0, 0, 0);
 	gtk_widget_show (alignment);
 
-	/* Comments. */
 	label = gtk_label_new_with_mnemonic (_("Co_mments for translators:"));
 	gtk_widget_show (label);
 	gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
@@ -1798,47 +1846,90 @@
 
 	comment_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (comment_view));
 
-	text = glade_property_i18n_get_comment (eprop->property);
-	if (text)
+	if (*comment)
 	{
 		gtk_text_buffer_set_text (comment_buffer,
-					  text,
+					  *comment,
 					  -1);
 	}
 	
 	res = gtk_dialog_run (GTK_DIALOG (dialog));
 	if (res == GTK_RESPONSE_OK) {
 		GtkTextIter start, end;
-		gboolean translatable, has_context;
 
+		g_free ((gpointer)*text);
+		g_free ((gpointer)*context);
+		g_free ((gpointer)*comment);
 
 		/* get the new values for translatable, has_context, and comment */
-		translatable = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (translatable_button));
-		has_context = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (context_button));
+		*translatable = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (translatable_button));
+		*has_context = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (context_button));
 
+		/* Comment */
 		gtk_text_buffer_get_bounds (comment_buffer, &start, &end);
-		str = gtk_text_buffer_get_text (comment_buffer, &start, &end, TRUE);
-		if (str[0] == '\0')
+		*comment = gtk_text_buffer_get_text (comment_buffer, &start, &end, TRUE);
+		if (*comment[0] == '\0')
 		{
-			g_free (str);
-			str = NULL;
+			g_free (*comment);
+			*comment = NULL;
 		}
-		
-		/* set the new i18n data via a glade command so it can be undone */
-		glade_command_set_i18n (eprop->property, translatable, has_context, str);
-		g_free (str);
-		
+
 		/* Text */
 		gtk_text_buffer_get_bounds (text_buffer, &start, &end);
-		str = gtk_text_buffer_get_text (text_buffer, &start, &end, TRUE);
-		
-		/* set the new text */
-		glade_eprop_text_changed_common (eprop, str, eprop->use_command);
-		g_free (str);
-		
+		*text = gtk_text_buffer_get_text (text_buffer, &start, &end, TRUE);
+		if (*text[0] == '\0')
+		{
+			g_free (*text);
+			*text = NULL;
+		}
+
+		/* Context */
+		if (fmt != GLADE_PROJECT_FORMAT_LIBGLADE)
+		{
+			gtk_text_buffer_get_bounds (context_buffer, &start, &end);
+			*context = gtk_text_buffer_get_text (context_buffer, &start, &end, TRUE);
+			if (*context[0] == '\0')
+			{
+				g_free (*context);
+				*context = NULL;
+			}
+		}
+
+		gtk_widget_destroy (dialog);
+		return TRUE;
 	}
 
 	gtk_widget_destroy (dialog);
+	return FALSE;
+}
+
+static void
+glade_eprop_text_show_i18n_dialog (GtkWidget           *entry,
+				   GladeEditorProperty *eprop)
+{
+	GladeProject *project;
+	GladeProjectFormat fmt;
+	gchar *text = g_value_dup_string (eprop->property->value);
+	gchar *context = g_strdup (glade_property_i18n_get_context (eprop->property));
+	gchar *comment = g_strdup (glade_property_i18n_get_comment (eprop->property));
+	gboolean translatable = glade_property_i18n_get_translatable (eprop->property);
+	gboolean has_context = glade_property_i18n_get_has_context (eprop->property);
+
+	project = eprop->property->widget->project;
+	fmt = glade_project_get_format (project);
+
+	if (glade_editor_property_show_i18n_dialog (entry, fmt, &text, &context, &comment, 
+						    &has_context, &translatable))
+	{
+		glade_command_set_i18n (eprop->property, translatable, has_context, context, comment);
+		glade_eprop_text_changed_common (eprop, text, eprop->use_command);
+
+		glade_editor_property_load (eprop, eprop->property);
+
+		g_free (text);
+		g_free (context);
+		g_free (comment);
+	}
 }
 
 static GtkWidget *
@@ -2754,15 +2845,13 @@
 					{
 						if ((old_ref = glade_widget_get_parentless_widget_ref (new_widget)))
 						{
-							gchar *desc = g_strdup_printf (_("Setting %s of %s to %s"),
-										       eprop->property->klass->name,
-										       eprop->property->widget->name, 
-										       new_widget->name);
-							glade_command_push_group (desc);
+							glade_command_push_group (_("Setting %s of %s to %s"),
+										  eprop->property->klass->name,
+										  eprop->property->widget->name, 
+										  new_widget->name);
 							glade_command_set_property (old_ref, NULL);
 							glade_editor_property_commit (eprop, value);
 							glade_command_pop_group ();
-							g_free (desc);
 						}
 						else
 							glade_editor_property_commit (eprop, value);
@@ -2780,14 +2869,13 @@
 	{
 		GValue *value;
 		GladeWidget *new_widget;
-		/* translators: Creating 'a widget' for 'a property' of 'a widget' */
-		gchar *desc = g_strdup_printf (_("Creating %s for %s of %s"),
-					       create_adaptor->name,
-					       eprop->property->klass->name, 
-					       eprop->property->widget->name);
-		glade_command_push_group (desc);
-		g_free (desc);
 
+		/* translators: Creating 'a widget' for 'a property' of 'a widget' */
+		glade_command_push_group (_("Creating %s for %s of %s"),
+					  create_adaptor->name,
+					  eprop->property->klass->name, 
+					  eprop->property->widget->name);
+		
 		/* Dont bother if the user canceled the widget */
 		if ((new_widget = glade_command_create (create_adaptor, NULL, NULL, project)) != NULL)
 		{

Modified: trunk/gladeui/glade-editor-property.h
==============================================================================
--- trunk/gladeui/glade-editor-property.h	(original)
+++ trunk/gladeui/glade-editor-property.h	Wed Oct  1 00:10:23 2008
@@ -157,6 +157,13 @@
 void                 glade_editor_property_commit_no_callback (GladeEditorProperty *eprop,
 							       GValue              *value);
 
+gboolean             glade_editor_property_show_i18n_dialog (GtkWidget            *parent,
+							     GladeProjectFormat    fmt,
+							     gchar               **text,
+							     gchar               **context,
+							     gchar               **comment,
+							     gboolean             *has_context,
+							     gboolean             *translatable);
 
 /* Generic eprops */
 #define GLADE_TYPE_EPROP_NUMERIC         (glade_eprop_numeric_get_type())

Modified: trunk/gladeui/glade-property-class.c
==============================================================================
--- trunk/gladeui/glade-property-class.c	(original)
+++ trunk/gladeui/glade-property-class.c	Wed Oct  1 00:10:23 2008
@@ -1511,6 +1511,7 @@
 	if ((child = glade_xml_search_child (node, GLADE_TAG_PARAMETERS)) != NULL)
 		klass->parameters = glade_parameter_list_new_from_node (klass->parameters, child);
 		
+	klass->construct_only = glade_xml_get_property_boolean (node, GLADE_TAG_CONSTRUCT_ONLY, klass->construct_only);
 	klass->translatable = glade_xml_get_property_boolean (node, GLADE_TAG_TRANSLATABLE, klass->translatable);
 	klass->common      = glade_xml_get_property_boolean (node, GLADE_TAG_COMMON,      klass->common);
 	klass->optional    = glade_xml_get_property_boolean (node, GLADE_TAG_OPTIONAL,    klass->optional);

Modified: trunk/gladeui/glade-property.c
==============================================================================
--- trunk/gladeui/glade-property.c	(original)
+++ trunk/gladeui/glade-property.c	Wed Oct  1 00:10:23 2008
@@ -72,6 +72,7 @@
 	PROP_SENSITIVE,
 	PROP_I18N_TRANSLATABLE,
 	PROP_I18N_HAS_CONTEXT,
+	PROP_I18N_CONTEXT,
 	PROP_I18N_COMMENT,
 	PROP_STATE
 };
@@ -91,6 +92,7 @@
 					  "class", template_prop->klass,
 					  "i18n-translatable", template_prop->i18n_translatable,
 					  "i18n-has-context", template_prop->i18n_has_context,
+					  "i18n-context", template_prop->i18n_context,
 					  "i18n-comment", template_prop->i18n_comment,
 					  NULL);
 	property->widget  = widget;
@@ -334,19 +336,32 @@
 	    property->enabled == FALSE    || 
 	    /* explicit "never sync" flag */
 	    property->klass->ignore       || 
-	    /* avoid recursion */
-	    property->syncing             ||
+	    /* recursion guards */
+	    property->syncing >= property->sync_tolerance ||
 	    /* No widget owns this property yet */
 	    property->widget == NULL)
 		return;
 
-	property->syncing = TRUE;
+	property->syncing++;
 
 	/* In the case of construct_only, the widget instance must be rebuilt
 	 * to apply the property
 	 */
-	if (property->klass->construct_only)
+	if (property->klass->construct_only && property->syncing == 1)
+	{
+		/* Virtual properties can be construct only, in which
+		 * case they are allowed to trigger a rebuild, and in
+		 * the process are allowed to get "synced" after the
+		 * instance is rebuilt.
+		 */
+		if (property->klass->virt)
+			property->sync_tolerance++;
+
 		glade_widget_rebuild (property->widget);
+
+		if (property->klass->virt)
+			property->sync_tolerance--;
+	}
 	else if (property->klass->packing)
 		glade_widget_child_set_property (glade_widget_get_parent (property->widget),
 						 property->widget, 
@@ -357,7 +372,7 @@
 						  property->klass->id, 
 						  property->value);
 
-	property->syncing = FALSE;
+	property->syncing--;
 }
 
 static void
@@ -409,6 +424,9 @@
 	case PROP_I18N_HAS_CONTEXT:
 		glade_property_i18n_set_has_context (property, g_value_get_boolean (value));
 		break;
+	case PROP_I18N_CONTEXT:
+		glade_property_i18n_set_context (property, g_value_get_string (value));
+		break;
 	case PROP_I18N_COMMENT:
 		glade_property_i18n_set_comment (property, g_value_get_string (value));
 		break;
@@ -443,6 +461,9 @@
 	case PROP_I18N_HAS_CONTEXT:
 		g_value_set_boolean (value, glade_property_i18n_get_has_context (property));
 		break;
+	case PROP_I18N_CONTEXT:
+		g_value_set_string (value, glade_property_i18n_get_context (property));
+		break;
 	case PROP_I18N_COMMENT:
 		g_value_set_string (value, glade_property_i18n_get_comment (property));
 		break;
@@ -479,6 +500,7 @@
 	property->i18n_translatable = TRUE;
 	property->i18n_has_context = FALSE;
 	property->i18n_comment = NULL;
+	property->sync_tolerance = 1;
 }
 
 static void
@@ -528,6 +550,13 @@
 		  TRUE, G_PARAM_READWRITE));
 
 	g_object_class_install_property 
+		(object_class, PROP_I18N_CONTEXT,
+		 g_param_spec_string 
+		 ("i18n-context", _("Context"), 
+		  _("Context for translation"),
+		  NULL, G_PARAM_READWRITE));
+
+	g_object_class_install_property 
 		(object_class, PROP_I18N_COMMENT,
 		 g_param_spec_string 
 		 ("i18n-comment", _("Comment"), 
@@ -1076,23 +1105,32 @@
 			if (property)
 			{
 				gint translatable, has_context;
-				gchar *comment;
+				gchar *comment = NULL, *context = NULL;
 
 				translatable = glade_xml_get_property_boolean
 					(prop, GLADE_TAG_TRANSLATABLE, FALSE);
-				has_context = glade_xml_get_property_boolean
-					(prop, GLADE_TAG_HAS_CONTEXT, FALSE);
 				comment = glade_xml_get_property_string
 					(prop, GLADE_TAG_COMMENT);
 
-				glade_property_i18n_set_translatable
-					(property, translatable);
-				glade_property_i18n_set_has_context
-					(property, has_context);
-				glade_property_i18n_set_comment
-					(property, comment);
+				if (fmt == GLADE_PROJECT_FORMAT_LIBGLADE)
+					has_context = glade_xml_get_property_boolean
+						(prop, GLADE_TAG_HAS_CONTEXT, FALSE);
+				else
+					context = glade_xml_get_property_string
+						(prop, GLADE_TAG_CONTEXT);
+
+				glade_property_i18n_set_translatable (property, translatable);
+				glade_property_i18n_set_comment (property, comment);
+
+				if (fmt == GLADE_PROJECT_FORMAT_LIBGLADE)
+					glade_property_i18n_set_has_context
+						(property, has_context);
+				else
+					glade_property_i18n_set_context
+						(property, context);
 
 				g_free (comment);
+				g_free (context);
 			}
 
 			g_free (value);
@@ -1209,18 +1247,21 @@
 							    GLADE_TAG_TRANSLATABLE, 
 							    GLADE_XML_TAG_I18N_TRUE);
 
-		if (property->i18n_has_context)
+		if (fmt == GLADE_PROJECT_FORMAT_LIBGLADE && property->i18n_has_context)
 			glade_xml_node_set_property_string (prop_node, 
 							    GLADE_TAG_HAS_CONTEXT, 
 							    GLADE_XML_TAG_I18N_TRUE);
 
+		if (fmt == GLADE_PROJECT_FORMAT_GTKBUILDER && property->i18n_context)
+			glade_xml_node_set_property_string (prop_node, 
+							    GLADE_TAG_CONTEXT, 
+							    property->i18n_context);
 
 		if (property->i18n_comment)
 			glade_xml_node_set_property_string (prop_node, 
 							    GLADE_TAG_COMMENT, 
 							    property->i18n_comment);
 	}
-
 	g_free (name);
 	g_free (value);
 }
@@ -1321,7 +1362,7 @@
 	g_object_notify (G_OBJECT (property), "i18n-comment");
 }
 
-const gchar *
+G_CONST_RETURN gchar *
 glade_property_i18n_get_comment (GladeProperty *property)
 {
 	g_return_val_if_fail (GLADE_IS_PROPERTY (property), NULL);
@@ -1329,6 +1370,25 @@
 }
 
 void
+glade_property_i18n_set_context (GladeProperty      *property, 
+				 const gchar        *str)
+{
+	g_return_if_fail (GLADE_IS_PROPERTY (property));
+	if (property->i18n_context)
+		g_free (property->i18n_context);
+
+	property->i18n_context = g_strdup (str);
+	g_object_notify (G_OBJECT (property), "i18n-context");
+}
+
+G_CONST_RETURN gchar *
+glade_property_i18n_get_context (GladeProperty *property)
+{
+	g_return_val_if_fail (GLADE_IS_PROPERTY (property), NULL);
+	return property->i18n_context;
+}
+
+void
 glade_property_i18n_set_translatable (GladeProperty *property,
 				      gboolean       translatable)
 {

Modified: trunk/gladeui/glade-property.h
==============================================================================
--- trunk/gladeui/glade-property.h	(original)
+++ trunk/gladeui/glade-property.h	Wed Oct  1 00:10:23 2008
@@ -79,10 +79,12 @@
 	/* Used only for translatable strings. */
 	gboolean  i18n_translatable;
 	gboolean  i18n_has_context;
+	gchar    *i18n_context;
 	gchar    *i18n_comment;
 		
-	gboolean     syncing;    /* Avoid recursion while synchronizing object with value.
-				  */
+	gint      syncing;    /* Avoid recursion while synchronizing object with value.
+			       */
+	gint      sync_tolerance;
 };
 
 
@@ -195,6 +197,11 @@
 
 G_CONST_RETURN gchar   *glade_property_i18n_get_comment      (GladeProperty      *property);
 
+void                    glade_property_i18n_set_context      (GladeProperty      *property, 
+							      const gchar        *str);
+
+G_CONST_RETURN gchar   *glade_property_i18n_get_context      (GladeProperty      *property);
+
 void                    glade_property_i18n_set_translatable (GladeProperty      *property,
 							      gboolean            translatable);
 

Modified: trunk/gladeui/glade-widget.c
==============================================================================
--- trunk/gladeui/glade-widget.c	(original)
+++ trunk/gladeui/glade-widget.c	Wed Oct  1 00:10:23 2008
@@ -619,15 +619,7 @@
 	{
 		GladeProperty *prop  = GLADE_PROPERTY(l->data);
 
-		/* XXX We need a better option to this hack.
-		 *
-		 * This used to be based on whether a function was
-		 * provided by the backend to treat the said property, now
-		 * that function is classwide so we dont know, so currently
-		 * we are just syncing all properties for the sake of those
-		 * properties.
-		 */
-		if (!prop->klass->construct_only)
+		if (prop->klass->virt)
 			glade_property_sync (prop);
 
 	}
@@ -1914,9 +1906,8 @@
 glade_widget_hide (GladeWidget *widget)
 {
 	g_return_if_fail (GLADE_IS_WIDGET (widget));
-	if (GTK_IS_WINDOW (widget->object))
+	if (GTK_IS_WIDGET (widget->object))
 	{
-		/* Save coordinates */
 		gtk_widget_hide (GTK_WIDGET (widget->object));
 	}
 	widget->visible = FALSE;
@@ -2154,7 +2145,7 @@
 
 typedef struct
 {
-	gchar *name;
+	GladeProperty *property;
 	GValue value;
 } PropertyData;
 
@@ -2174,8 +2165,8 @@
 	GladeWidgetAdaptor *adaptor;
 	GList              *children;
 	gboolean            reselect = FALSE, inproject;
-	GList              *npw_properties = NULL;
-	GList              *l;
+	GList              *restore_properties = NULL;
+	GList              *save_properties, *l;
 	
 	g_return_if_fail (GLADE_IS_WIDGET (gwidget));
 
@@ -2204,11 +2195,15 @@
 	/* Extract and keep the child hierarchies aside... */
 	children = glade_widget_extract_children (gwidget);
 
-	/* parentless_widget properties should be unset before transfering */
-	for (l = gwidget->properties; l; l = l->next)
+	/* parentless_widget and object properties that reffer to this widget should be unset before transfering */
+	l = g_list_copy (gwidget->properties);
+	save_properties = g_list_copy (gwidget->prop_refs);
+	save_properties = g_list_concat (l, save_properties);
+
+	for (l = save_properties; l; l = l->next)
 	{
 		GladeProperty *property = GLADE_PROPERTY (l->data);
-		if (property->klass->parentless_widget)
+		if (property->widget != gwidget || property->klass->parentless_widget)
 		{
 			PropertyData *prop_data;
 
@@ -2216,15 +2211,19 @@
 				g_warning ("Parentless widget property should be of object type");
 
 			prop_data = g_new0 (PropertyData, 1);
-			prop_data->name = g_strdup (property->klass->id);
-			g_value_init (&prop_data->value, property->value->g_type);
-			g_value_copy (property->value, &prop_data->value);
+			prop_data->property = property;
 
-			npw_properties = g_list_prepend (npw_properties,
-							 prop_data);
+			if (property->widget == gwidget)
+			{
+				g_value_init (&prop_data->value, property->value->g_type);
+				g_value_copy (property->value, &prop_data->value);
+			}
+			restore_properties = g_list_prepend (restore_properties,
+							     prop_data);
 			glade_property_set (property, NULL);
 		}
 	}
+	g_list_free (save_properties);
 
 	/* Hold a reference to the old widget while we transport properties
 	 * and children from it
@@ -2261,19 +2260,25 @@
 	 */
 	glade_widget_sync_custom_props (gwidget);
 
-	/* Setting parentless_widget properties back */
-	for (l = npw_properties; l; l = l->next)
+	/* Setting parentless_widget and prop_ref properties back */
+	for (l = restore_properties; l; l = l->next)
 	{
 		PropertyData *prop_data = l->data;
-		GladeProperty *property = glade_widget_get_property (gwidget, prop_data->name);
-
-		glade_property_set_value (property, &prop_data->value);
-
-		g_value_unset (&prop_data->value);
-		g_free (prop_data->name);
+		GladeProperty *property = prop_data->property;
+		
+		if (property->widget == gwidget)
+		{
+			glade_property_set_value (property, &prop_data->value);
+			g_value_unset (&prop_data->value);
+		}
+		else
+		{
+			/* restore property references on rebuilt objects */
+			glade_property_set (property, gwidget->object);
+		}
 		g_free (prop_data);
 	}
-	npw_properties = NULL;
+	g_list_free (restore_properties);
 
 	/* Sync packing.
 	 */

Modified: trunk/gladeui/glade-xml-utils.h
==============================================================================
--- trunk/gladeui/glade-xml-utils.h	(original)
+++ trunk/gladeui/glade-xml-utils.h	Wed Oct  1 00:10:23 2008
@@ -107,6 +107,7 @@
 #define GLADE_TAG_DEFAULT                         "default"
 #define GLADE_TAG_PARENTLESS_WIDGET               "parentless-widget"
 #define GLADE_TAG_DISABLED                        "disabled"
+#define GLADE_TAG_CONSTRUCT_ONLY                  "construct-only"
 #define GLADE_TAG_DEFAULT_PALETTE_STATE           "default-palette-state"
 #define GLADE_TAG_PROJECT_CONVERT_FUNCTION        "project-convert-function"
 #define GLADE_TAG_REPLACE_CHILD_FUNCTION          "replace-child-function"
@@ -159,6 +160,7 @@
 #define GLADE_TAG_VALUE                           "value"
 #define GLADE_TAG_TRANSLATABLE                    "translatable"
 #define GLADE_TAG_HAS_CONTEXT                     "context"
+#define GLADE_TAG_CONTEXT                         "context"
 #define GLADE_TAG_COMMENT                         "comments"
 #define GLADE_TAG_PACKING_DEFAULTS                "packing-defaults"
 #define GLADE_TAG_PARENT_CLASS                    "parent-class"

Modified: trunk/plugins/gtk+/glade-column-types.c
==============================================================================
--- trunk/plugins/gtk+/glade-column-types.c	(original)
+++ trunk/plugins/gtk+/glade-column-types.c	Wed Oct  1 00:10:23 2008
@@ -28,6 +28,7 @@
 #include <string.h>
 
 #include "glade-column-types.h"
+#include "glade-model-data.h"
 
 enum
 {
@@ -222,12 +223,14 @@
 }
 
 static void
-eprop_reload_value (GladeEPropColumnTypes *eprop)
+eprop_reload_value (GladeEPropColumnTypes *eprop_types)
 {
-	GtkTreeModel *model = GTK_TREE_MODEL (eprop->store);
+	GladeEditorProperty *eprop = GLADE_EDITOR_PROPERTY (eprop_types);
+	GtkTreeModel *model = GTK_TREE_MODEL (eprop_types->store);
 	GValue value = {0, };
 	GtkTreeIter iter;
-	GList *list = NULL;
+	GList *list = NULL, *l;
+	GNode *data_tree = NULL;
 	
 	if (gtk_tree_model_get_iter_first (model, &iter))
 	{
@@ -244,9 +247,43 @@
 		} while (gtk_tree_model_iter_next (model, &iter));
 	}
 
+	glade_widget_property_get (eprop->property->widget, "data", &data_tree);
+	if (data_tree)
+	{
+		GNode *row, *iter;
+		gint colnum;
+		data_tree = glade_model_data_tree_copy (data_tree);
+
+		glade_command_push_group (_("Setting columns of %s"), eprop->property->widget->name);
+
+		/* Remove extra columns */
+		for (row = data_tree->children; row; row = row->next)
+		{
+
+			for (colnum = 0, iter = row->children; iter; 
+			     colnum++, iter = iter->next)
+			{
+
+			}
+		}
+
+		g_value_init (&value, GLADE_TYPE_MODEL_DATA_TREE);
+		g_value_take_boxed (&value, data_tree);
+		glade_editor_property_commit (eprop, &value);
+		g_value_unset (&value);
+
+	}
+
 	g_value_init (&value, GLADE_TYPE_COLUMN_TYPE_LIST);
 	g_value_take_boxed (&value, list);
-	glade_editor_property_commit (GLADE_EDITOR_PROPERTY (eprop), &value);
+	glade_editor_property_commit (eprop, &value);
+	g_value_unset (&value);
+
+	if (data_tree)
+	{
+		glade_model_data_tree_free (data_tree);
+		glade_command_pop_group ();
+	}
 }
 
 static void

Modified: trunk/plugins/gtk+/glade-convert.c
==============================================================================
--- trunk/plugins/gtk+/glade-convert.c	(original)
+++ trunk/plugins/gtk+/glade-convert.c	Wed Oct  1 00:10:23 2008
@@ -379,9 +379,8 @@
 
 	for (i = 0; items[i]; i++)
 	{
-		GladeModelData *data = g_new0 (GladeModelData, 1);
+		GladeModelData *data = glade_model_data_new (G_TYPE_STRING);
 
-		g_value_init (&data->value, G_TYPE_STRING);
 		g_value_set_string (&data->value, items[i]);
 
 		row = g_node_new (NULL);
@@ -516,12 +515,12 @@
 			/* Cant cancel a liststore.... */
 			widget = glade_command_create (adaptor, NULL, NULL, project);
 
-			glade_command_set_property (property, widget->object);
-
 			data_tree = combos_data_tree_from_items (cdata->items);
 
 			glade_widget_property_set (widget, "columns", columns);
 			glade_widget_property_set (widget, "data", data_tree);
+
+			glade_command_set_property (property, widget->object);
 			
 			glade_column_list_free (columns);
 		}

Modified: trunk/plugins/gtk+/glade-gtk.c
==============================================================================
--- trunk/plugins/gtk+/glade-gtk.c	(original)
+++ trunk/plugins/gtk+/glade-gtk.c	Wed Oct  1 00:10:23 2008
@@ -1352,14 +1352,14 @@
 glade_gtk_widget_add2group_cb (GtkMenuItem *item, GladeWidget *gwidget)
 {
 	GladeWidget *group = g_object_get_data (G_OBJECT (item), "glade-group-widget");
-	gchar *desc = group ? g_strdup_printf (_("Adding %s to Size Group %s"), gwidget->name, group->name) : 
-		g_strdup_printf (_("Adding %s to a new Size Group"), gwidget->name);
 	GladeWidgetAdaptor *adaptor = glade_widget_adaptor_get_by_type (GTK_TYPE_SIZE_GROUP);
 	GList *widget_list = NULL, *new_list;
 	GladeProperty *property;
 
-	glade_command_push_group (desc);
-	g_free (desc);
+	if (group) 
+		glade_command_push_group (_("Adding %s to Size Group %s"), gwidget->name, group->name);
+	else
+		glade_command_push_group (_("Adding %s to a new Size Group"), gwidget->name);
 
 	if (!group)
 		/* Cant cancel a size group */
@@ -8615,15 +8615,9 @@
 	}
 
 	if (GTK_IS_LIST_STORE (object))
-	{
-		gtk_list_store_clear (GTK_LIST_STORE (object));
 		gtk_list_store_set_column_types (GTK_LIST_STORE (object), n, types);
-	}
 	else
-	{
-		gtk_tree_store_clear (GTK_TREE_STORE (object));
 		gtk_tree_store_set_column_types (GTK_TREE_STORE (object), n, types);
-	}
 }
 
 static void
@@ -8631,8 +8625,7 @@
 			  const GValue *value)
 {
 	GladeWidget     *gwidget = glade_widget_get_from_gobject (object);
-	GList           *columns = NULL, *list;
-	GladeColumnType *column;
+	GList           *columns = NULL;
 	GNode           *data_tree, *row, *iter;
 	gint             colnum;
 	GtkTreeIter      row_iter;
@@ -8785,6 +8778,8 @@
 	{
 		GladeColumnType *data = l->data;
 		GladeXmlNode  *column_node;
+
+		/* Write column names in comments... */
 			
 		column_node = glade_xml_node_new (context, GLADE_TAG_COLUMN);
 		glade_xml_node_append_child (columns_node, column_node);
@@ -8847,6 +8842,20 @@
 			glade_xml_node_set_property_string (col_node, GLADE_TAG_ID,
 							    column_number);
 			glade_xml_set_content (col_node, string);
+
+			if (data->i18n_translatable)
+				glade_xml_node_set_property_string (col_node, 
+								    GLADE_TAG_TRANSLATABLE, 
+								    GLADE_XML_TAG_I18N_TRUE);
+			if (data->i18n_context)
+				glade_xml_node_set_property_string (col_node, 
+								    GLADE_TAG_CONTEXT, 
+								    data->i18n_context);
+			if (data->i18n_comment)
+				glade_xml_node_set_property_string (col_node, 
+								    GLADE_TAG_COMMENT, 
+								    data->i18n_comment);
+
 			
 			g_free (column_number);
 			g_free (string);
@@ -8885,23 +8894,43 @@
 	GladeXmlNode *prop;
 	GList *types = NULL;
 	GValue value = {0,};
-	
+	gchar column_name[256];
+
+	column_name[0] = '\0';
+	column_name[255] = '\0';
+
 	if ((columns_node = glade_xml_search_child (node, GLADE_TAG_COLUMNS)) == NULL)
 		return;
 
-	for (prop = glade_xml_node_get_children (columns_node); prop;
-	     prop = glade_xml_node_next (prop))
+	for (prop = glade_xml_node_get_children_with_comments (columns_node); prop;
+	     prop = glade_xml_node_next_with_comments (prop))
 	{
 		GladeColumnType *data = g_new0 (GladeColumnType, 1);
-		gchar *type;
-		
-		if (!glade_xml_node_verify (prop, GLADE_TAG_COLUMN)) continue;
+		gchar *type, *comment_str, buffer[256];
+
+		if (!glade_xml_node_verify (prop, GLADE_TAG_COLUMN) &&
+		    !glade_xml_node_is_comment (prop)) continue;
+
+		if (glade_xml_node_is_comment (prop))
+		{
+			comment_str = glade_xml_get_content (prop);
+			if (sscanf (comment_str, "column-name %s", buffer) == 1)
+			{
+				strncpy (column_name, buffer, 255);
+				g_free (comment_str);
+				continue;
+			}
+			g_free (comment_str);
+		}
 
 		type = glade_xml_get_property_string_required (prop, GLADE_TAG_TYPE, NULL);
-		data->type = g_type_from_name (type);
+		data->type        = g_type_from_name (type);
+		data->column_name = g_strdup (column_name);
 		
 		types = g_list_prepend (types, data);
 		g_free (type);
+
+		column_name[0] = '\0';
 	}
 	
 	property = glade_widget_get_property (widget, "columns");
@@ -8963,12 +8992,15 @@
 			value     = glade_utils_value_from_string (column_type->type, value_str, widget->project);
 			g_free (value_str);
 
-			data = 	g_new0 (GladeModelData, 1);
-			g_value_init (&data->value, column_type->type);
+			data = glade_model_data_new (column_type->type);
 			g_value_copy (value, &data->value);
 			g_value_unset (value);
 			g_free (value);
 
+			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);
+
 			item = g_node_new (data);
 			g_node_append (row, item);
 

Modified: trunk/plugins/gtk+/glade-model-data.c
==============================================================================
--- trunk/plugins/gtk+/glade-model-data.c	(original)
+++ trunk/plugins/gtk+/glade-model-data.c	Wed Oct  1 00:10:23 2008
@@ -28,8 +28,19 @@
 #include <string.h>
 
 #include "glade-model-data.h"
+#include "glade-column-types.h"
 
+GladeModelData *
+glade_model_data_new (GType type)
+{
+	GladeModelData *data = g_new0 (GladeModelData, 1);
+	g_value_init (&data->value, type);
 
+	if (type == G_TYPE_STRING)
+		data->i18n_translatable = TRUE;
+
+	return data;
+}
 
 GladeModelData *
 glade_model_data_copy (GladeModelData *data)
@@ -45,7 +56,7 @@
 	dup->name              = g_strdup (data->name);
 
 	dup->i18n_translatable = data->i18n_translatable;
-	dup->i18n_has_context  = data->i18n_has_context;
+	dup->i18n_context      = g_strdup (data->i18n_context);
 	dup->i18n_comment      = g_strdup (data->i18n_comment);
 
 	return dup;
@@ -59,6 +70,7 @@
 		g_value_unset (&data->value);
 	
 		g_free (data->name);
+		g_free (data->i18n_context);
 		g_free (data->i18n_comment);
 		g_free (data);
 	}
@@ -88,6 +100,68 @@
 	}
 }
 
+void
+glade_model_data_insert_column (GNode          *node,
+				GType           type,
+				gint            nth)
+{
+	GNode *row, *item;
+	GladeModelData *data;
+
+	g_return_if_fail (node != NULL);
+
+	for (row = node->children; row; row = row->next)
+	{
+		g_return_if_fail (nth >= 0 && nth <= g_node_n_children (row));
+
+		data = glade_model_data_new (type);
+		item = g_node_new (data);
+		g_node_insert (row, nth, item);
+	}
+}
+
+void
+glade_model_data_remove_column (GNode          *node,
+				GType           type,
+				gint            nth)
+{
+	GNode *row, *item;
+	GladeModelData *data;
+
+	g_return_if_fail (node != NULL);
+
+	for (row = node->children; row; row = row->next)
+	{
+		g_return_if_fail (nth >= 0 && nth < g_node_n_children (row));
+
+		item = g_node_nth_child (row, nth);
+		data = item->data;
+
+		glade_model_data_free (data);
+		g_node_destroy (item);
+	}
+}
+
+void
+glade_model_data_reorder_column (GNode          *node,
+				 gint            column,
+				 gint            nth)
+{
+	GNode *row, *item;
+
+	g_return_if_fail (node != NULL);
+
+	for (row = node->children; row; row = row->next)
+	{
+		g_return_if_fail (nth >= 0 && nth < g_node_n_children (row));
+
+		item = g_node_nth_child (row, column);
+
+		g_node_unlink (item);
+		g_node_insert (row, nth, item);
+	}
+}
+
 GType
 glade_model_data_tree_get_type (void)
 {
@@ -169,12 +243,18 @@
 }
 
 /**************************** GladeEditorProperty *****************************/
+enum {
+	COLUMN_ROW = 0, /* row number */
+	NUM_COLUMNS
+};
+
 typedef struct
 {
 	GladeEditorProperty parent_instance;
 
 	GtkTreeView  *view;
 	GtkListStore *store;
+	GtkTreeSelection *selection;
 } GladeEPropModelData;
 
 GLADE_MAKE_EPROP (GladeEPropModelData, glade_eprop_model_data)
@@ -186,18 +266,65 @@
 
 
 static void
+append_row (GNode *node, GList *columns)
+{
+	GladeModelData *data;
+	GladeColumnType *column;
+	GNode *row;
+	GList *list;
+
+	g_assert (node && columns);
+
+	row = g_node_new (NULL);
+	g_node_append (node, row);
+
+	for (list = columns; list; list = list->next)
+       	{
+		column = list->data;
+		data = glade_model_data_new (column->type);
+		g_node_append_data (row, data);
+	}
+}
+
+
+/* User pressed add: append row and commit values  */
+static void
 glade_eprop_model_data_add_clicked (GtkWidget *button, 
-				    GladeEPropModelData *eprop_types)
+				    GladeEditorProperty *eprop)
 {
-	/* Add new row with default values */
+	GValue value = { 0, };
+	GNode *node = NULL;
+	GList *columns = NULL;
+
+	glade_property_get (eprop->property, &node);
+	glade_widget_property_get (eprop->property->widget, "columns", &columns);
+
+	if (!columns)
+		return;
+
+	if (!node)
+		node = g_node_new (NULL);
+	else
+		node = glade_model_data_tree_copy (node);
+
+	append_row (node, columns);
+
+	g_value_init (&value, GLADE_TYPE_MODEL_DATA_TREE);
+	g_value_take_boxed (&value, node);
+	glade_editor_property_commit (eprop, &value);
+	g_value_unset (&value);
 }
 
+/* User pressed delete: remove selected row and commit values  */
 static void
 glade_eprop_model_data_delete_clicked (GtkWidget *button, 
-					 GladeEPropModelData *eprop_types)
+				    GladeEditorProperty *eprop)
 {
-	/* User pressed delete: remove selected row and commit values from treeview to property */
-	
+	GtkTreeIter iter;
+	GladeEPropModelData *eprop_data = GLADE_EPROP_MODEL_DATA (eprop);
+	/* NOTE: This will trigger row-deleted below... */
+	if (gtk_tree_selection_get_selected (eprop_data->selection, NULL, &iter))
+		gtk_list_store_remove (GTK_LIST_STORE (eprop_data->store), &iter);
 }
  
 static void
@@ -206,6 +333,27 @@
 			    GladeEditorProperty *eprop)
 {
 	/* User deleted a row: commit values from treeview to property */
+#if 0
+	GtkTreeIter iter;
+	GladeEPropModelData *eprop_data = GLADE_EPROP_MODEL_DATA (eprop);
+	GNode *data_tree = NULL, *row;
+
+	glade_property_get (eprop->property, &data_tree);
+
+	if (gtk_tree_selection_get_selected (eprop_types->selection, NULL, &iter))
+	{
+		
+	}
+
+	for (row = data_tree->children; row; row = row->next
+
+
+	g_value_init (&value, GLADE_TYPE_MODEL_DATA_TREE);
+	g_value_take_boxed (&value, node);
+	glade_editor_property_commit (eprop, &value);
+	g_value_unset (&value);
+
+#endif
 }
 
 
@@ -231,70 +379,203 @@
 	GNode          *data_tree = NULL, *iter_node, *row_node;
 	GArray         *gtypes = g_array_new (FALSE, TRUE, sizeof (GType));
 	GtkTreeIter     iter;
-	gint            column_num;
+	gint            column_num, row_num;
+	GType           index_type = G_TYPE_INT;
 
 	glade_property_get (eprop->property, &data_tree);
 
-
 	if (!data_tree || !data_tree->children || !data_tree->children->children)
 		return NULL;
 
 	/* Generate store with tailored column types */
+	g_array_append_val (gtypes, index_type);
 	for (iter_node = data_tree->children->children; iter_node; iter_node = iter_node->next)
 	{
 		iter_data = iter_node->data;
 		g_array_append_val (gtypes, G_VALUE_TYPE (&iter_data->value));
 	}
-	store = gtk_list_store_newv (gtypes->len, (GType *)gtypes->data);
+	store = gtk_list_store_newv (NUM_COLUMNS + gtypes->len, (GType *)gtypes->data);
 	g_array_free (gtypes, TRUE);
 
 	/* Now populate the store with data */
-	for (row_node = data_tree->children; row_node; row_node = row_node->next)
+	for (row_num = 0, row_node = data_tree->children; row_node; 
+	     row_num++, row_node = row_node->next)
 	{
 		row_data = row_node->data;
 
 		gtk_list_store_append (store, &iter);
+		gtk_list_store_set (store, &iter, COLUMN_ROW, row_num, -1);
 
 		for (column_num = 0, iter_node = row_node->children; iter_node; 
 		     column_num++, iter_node = iter_node->next)
 		{
 			iter_data = iter_node->data;
-			gtk_list_store_set_value (store, &iter, column_num, &iter_data->value);
+			gtk_list_store_set_value (store, &iter, NUM_COLUMNS + column_num, &iter_data->value);
 		}
 	}
 	return store;
 }
 
+
+static void
+value_toggled (GtkCellRendererToggle *cell,
+	       gchar                 *path,
+	       GladeEditorProperty *eprop)
+{
+	GladeEPropModelData *eprop_data = GLADE_EPROP_MODEL_DATA (eprop);
+	gboolean             active;
+	GtkTreeIter          iter;
+	gint                 colnum = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column-number"));
+
+	if (!gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (eprop_data->store), &iter, path))
+		return;
+
+	gtk_tree_model_get (GTK_TREE_MODEL (eprop_data->store), &iter,
+			    NUM_COLUMNS + colnum, &active,
+			    -1);
+
+	gtk_list_store_set (eprop_data->store, &iter,
+			    NUM_COLUMNS + colnum, !active,
+			    -1);
+}
+
+static void
+value_text_edited (GtkCellRendererText *cell,
+		   const gchar         *path,
+		   const gchar         *new_text,
+		   GladeEditorProperty *eprop)
+{
+	GladeEPropModelData *eprop_data = GLADE_EPROP_MODEL_DATA (eprop);
+	GtkTreeIter          iter;
+	gint                 colnum = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column-number"));
+
+	if (!gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (eprop_data->store), &iter, path))
+		return;
+
+	gtk_list_store_set (eprop_data->store, &iter,
+			    NUM_COLUMNS + colnum, new_text,
+			    -1);
+}
+
 static GtkTreeViewColumn *
-eprop_model_generate_column (GladeEditorProperty *eprop, 
+eprop_model_generate_column (GladeEditorProperty *eprop,
+			     gint                 colnum,
 			     GladeModelData      *data)
 {
 	GtkTreeViewColumn *column = gtk_tree_view_column_new ();
-#if 0
+	GtkCellRenderer   *renderer = NULL;
+	GtkAdjustment     *adjustment;
+	GtkListStore      *store;
+	GType              type = G_VALUE_TYPE (&data->value);
+
+	gtk_tree_view_column_set_title (column, g_type_name (type));
+
 	/* Support enum and flag types, and a hardcoded list of fundamental types */
-	if (type == G_TYPE_CHAR)
-	else if (type == G_TYPE_UCHAR)
-	else if (type == G_TYPE_STRING)
+	if (type == G_TYPE_CHAR ||
+	    type == G_TYPE_UCHAR ||
+	    type == G_TYPE_STRING)
+	{
+		/* Text renderer */
+		renderer = gtk_cell_renderer_text_new ();
+		g_object_set (G_OBJECT (renderer), 
+			      "editable", TRUE, 
+			      "ellipsize", PANGO_ELLIPSIZE_END,
+			      NULL);
+		gtk_tree_view_column_pack_start (column, renderer, FALSE);
+		gtk_tree_view_column_set_attributes (column, renderer, 
+						     "text", NUM_COLUMNS + colnum,
+						     NULL);
+
+		if (type == G_TYPE_CHAR ||
+		    type == G_TYPE_UCHAR)
+		{
+			/* XXX restrict to 1 char !! */
+		}
+
+		g_signal_connect (G_OBJECT (renderer), "edited",
+				  G_CALLBACK (value_text_edited), eprop);
+
+		/* Trigger i18n dialog from here somehow ! */
+/* 		g_signal_connect (G_OBJECT (renderer), "editing-started", */
+/* 				  G_CALLBACK (value_text_editing_started), eprop); */
+	}
+
 		/* Text renderer single char */
 	else if (type == G_TYPE_BOOLEAN)
+	{
+		/* Toggle renderer */
+		renderer = gtk_cell_renderer_toggle_new ();
+		g_object_set (G_OBJECT (renderer), "activatable", TRUE, NULL);
+		gtk_tree_view_column_pack_start (column, renderer, FALSE);
+		gtk_tree_view_column_set_attributes (column, renderer, 
+						     "active", NUM_COLUMNS + colnum,
+						     NULL);
+		g_signal_connect (G_OBJECT (renderer), "toggled",
+				  G_CALLBACK (value_toggled), eprop);
+	}
 		/* Check renderer */
-	else if (type == G_TYPE_INT)
-	else if (type == G_TYPE_UINT)
-	else if (type == G_TYPE_LONG)
-	else if (type == G_TYPE_ULONG)
-	else if (type == G_TYPE_INT64)
-	else if (type == G_TYPE_UINT64)
-		/* spin renderer with customized adjustments */
-	else if (type == G_TYPE_FLOAT)
-	else if (type == G_TYPE_DOUBLE)
-		/* spin renderer with customized adjustments */
-	else if (type == G_TYPE_OBJECT || g_type_is_a (type, G_TYPE_OBJECT))
-		/* text renderer and object dialog (or raw text for pixbuf) */
+	else if (type == G_TYPE_INT ||
+		 type == G_TYPE_UINT ||
+		 type == G_TYPE_LONG ||
+		 type == G_TYPE_ULONG ||
+		 type == G_TYPE_INT64 ||
+		 type == G_TYPE_UINT64 ||
+		 type == G_TYPE_FLOAT ||
+		 type == G_TYPE_DOUBLE)
+	{
+		/* Spin renderer */
+		renderer = gtk_cell_renderer_spin_new ();
+		adjustment = (GtkAdjustment *)gtk_adjustment_new (0, -G_MAXDOUBLE, G_MAXDOUBLE, 100, 100, 100);
+		g_object_set (G_OBJECT (renderer), 
+			      "editable", TRUE, 
+			      "adjustment", adjustment, 
+			      "ellipsize", PANGO_ELLIPSIZE_END,
+			      NULL);
+
+		gtk_tree_view_column_pack_start (column, renderer, TRUE);
+		gtk_tree_view_column_set_attributes (column, renderer, 
+						     "text", NUM_COLUMNS + colnum,
+						     NULL);
+
+		if (type == G_TYPE_FLOAT ||
+		    type == G_TYPE_DOUBLE)
+			g_object_set (G_OBJECT (renderer), "digits", 2, NULL);
+
+		g_signal_connect (G_OBJECT (renderer), "edited",
+				  G_CALLBACK (value_text_edited), eprop);
+		
+	}
 	else if (G_TYPE_IS_ENUM (type))
-		/* combobox renderer */
+	{
+		/* Combo renderer */
+		renderer = gtk_cell_renderer_combo_new ();
+		store = glade_utils_liststore_from_enum_type (type, FALSE);
+		g_object_set (G_OBJECT (renderer), 
+			      "editable", TRUE, 
+			      "text-column", 0,
+			      "has-entry", FALSE,
+			      "model", store,
+			      NULL);
+		gtk_tree_view_column_pack_start (column, renderer, TRUE);
+		gtk_tree_view_column_set_attributes (column, renderer, 
+						     "text", NUM_COLUMNS + colnum,
+						     NULL);
+		g_signal_connect (G_OBJECT (renderer), "edited",
+				  G_CALLBACK (value_text_edited), eprop);
+
+	}
 	else if (G_TYPE_IS_FLAGS (type))
-#endif
-		return NULL;
+	{
+		/* Export a flags dialog from glade-editor-property... */
+	}
+	else if (type == G_TYPE_OBJECT || g_type_is_a (type, G_TYPE_OBJECT))
+	{
+		/* text renderer and object dialog (or raw text for pixbuf) */;
+	}
+
+	g_object_set_data (G_OBJECT (renderer), "column-number", GINT_TO_POINTER (colnum));
+
+	return column;
 }
 
 static void
@@ -304,6 +585,7 @@
 	GladeModelData      *iter_data;
 	GtkTreeViewColumn   *column;
 	GNode               *data_tree = NULL, *iter_node;
+	gint                 colnum;
 
 	glade_property_get (eprop->property, &data_tree);
 	
@@ -315,11 +597,12 @@
 		return;
 
 	/* Append new columns */
-	for (iter_node = data_tree->children->children; iter_node; iter_node = iter_node->next)
+	for (colnum = 0, iter_node = data_tree->children->children; iter_node; 
+	     colnum++, iter_node = iter_node->next)
 	{
 		iter_data = iter_node->data;
 
-		column = eprop_model_generate_column (eprop, iter_data);
+		column = eprop_model_generate_column (eprop, colnum, iter_data);
 		gtk_tree_view_append_column (eprop_data->view, column);
 	}
 }
@@ -339,12 +622,18 @@
 	if (eprop_data->store)
 		g_object_unref (G_OBJECT (eprop_data->store));
 		
-	eprop_data->store = eprop_model_data_generate_store (eprop);
+	if ((eprop_data->store = eprop_model_data_generate_store (eprop)) != NULL)
+	{
+		eprop_data->selection = gtk_tree_view_get_selection (eprop_data->view);
 
-	if (eprop_data->store)
+		/* Pass ownership of the store to the model */
+		gtk_tree_view_set_model (eprop_data->view, GTK_TREE_MODEL (eprop_data->store));
+		g_object_unref (G_OBJECT (eprop_data->store));
+		
 		g_signal_connect (eprop_data->store, "row-deleted",
 				  G_CALLBACK (eprop_treeview_row_deleted),
 				  eprop);
+	}
 
 	/* Clear and create new columns with renderers */
 	eprop_model_data_generate_columns (eprop);
@@ -364,15 +653,15 @@
 	swin = gtk_scrolled_window_new (NULL, NULL);
 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin), GTK_SHADOW_IN);
 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
-	gtk_box_pack_start (GTK_BOX (hbox), swin, TRUE, TRUE, 0);
+	gtk_box_pack_start (GTK_BOX (vbox), swin, TRUE, TRUE, 0);
 
 	/* hbox with add/remove row buttons on the right... */
-	gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
 	
 	button = gtk_button_new ();
 	gtk_button_set_image (GTK_BUTTON (button),
 			      gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON));
-	gtk_box_pack_start (GTK_BOX (vbox), button,  FALSE, FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (hbox), button,  FALSE, FALSE, 0);
 
 	g_signal_connect (G_OBJECT (button), "clicked",
 			  G_CALLBACK (glade_eprop_model_data_add_clicked), 
@@ -381,7 +670,7 @@
 	button = gtk_button_new ();
 	gtk_button_set_image (GTK_BUTTON (button),
 			      gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_BUTTON));
-	gtk_box_pack_start (GTK_BOX (vbox), button,  FALSE, FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (hbox), button,  FALSE, FALSE, 0);
 
 	g_signal_connect (G_OBJECT (button), "clicked",
 			  G_CALLBACK (glade_eprop_model_data_delete_clicked), 
@@ -393,6 +682,6 @@
 	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (eprop_data->view), TRUE);
 	gtk_container_add (GTK_CONTAINER (swin), GTK_WIDGET (eprop_data->view));
 	
-	gtk_widget_show_all (hbox);
-	return hbox;
+	gtk_widget_show_all (vbox);
+	return vbox;
 }

Modified: trunk/plugins/gtk+/glade-model-data.h
==============================================================================
--- trunk/plugins/gtk+/glade-model-data.h	(original)
+++ trunk/plugins/gtk+/glade-model-data.h	Wed Oct  1 00:10:23 2008
@@ -32,7 +32,7 @@
 	gchar    *name;
 	
 	gboolean  i18n_translatable;
-	gboolean  i18n_has_context;
+	gchar    *i18n_context;
 	gchar    *i18n_comment;
 };
 
@@ -55,6 +55,8 @@
 
 GParamSpec     *glade_standard_model_data_spec     (void);
 
+
+GladeModelData *glade_model_data_new               (GType           type);
 GladeModelData *glade_model_data_copy              (GladeModelData *data);
 void            glade_model_data_free              (GladeModelData *data);
 
@@ -71,6 +73,7 @@
 						    gint            column,
 						    gint            nth);
 
+
 G_END_DECLS
 
 #endif /* _GLADE_MODEL_DATA_H_ */

Modified: trunk/plugins/gtk+/gtk+.xml.in
==============================================================================
--- trunk/plugins/gtk+/gtk+.xml.in	(original)
+++ trunk/plugins/gtk+/gtk+.xml.in	Wed Oct  1 00:10:23 2008
@@ -1797,7 +1797,7 @@
       <write-widget-function>glade_gtk_store_write_widget</write-widget-function>
       <read-widget-function>glade_gtk_store_read_widget</read-widget-function>
       <properties>
-        <property id="columns" since="2.12" _name="Columns" save="False">
+        <property id="columns" since="2.12" _name="Columns" save="False" construct-only="True">
           <spec>glade_standard_column_types_spec</spec>
           <_tooltip>Set column types for this model</_tooltip>
         </property>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]