Implemented new "context" i18n metadata.

* 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()


svn path=/trunk/; revision=1967
This commit is contained in:
Tristan Van Berkom 2008-10-01 00:10:23 +00:00
parent 54ddfac5b7
commit 4f74b453ae
17 changed files with 777 additions and 216 deletions

View File

@ -1,9 +1,16 @@
2008-09-30 Tristan Van Berkom <tvb@gnome.org>
* 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()
2008-09-29 Tristan Van Berkom <tvb@gnome.org>
* plugins/gtk+/glade-column-types.[ch]: Exported glade_column_list_copy/free()
* plugins/gtk+/glade-model-data.[ch], plugins/gtk+/Makefile.am: Added model data
pspec, editor not compĺete yet...
pspec, editor not complete yet...
* plugins/gtk+/glade-gtk.c, plugins/gtk+/gtk+.xml.in: Implemented new pspec as
list/treestore's "data" property with load/save support.
@ -13,6 +20,12 @@
* gladeui/glade-utils.[ch]: Added glade_utils_liststore_from_enum_type()
* gladeui/glade-widget.c: glade_widget_rebuild() updates prop_refs now
* gladeui/glade-property-class.c, gladeui/glade-xml-utils.h, gladeui/glade-property.c:
now you can set construct-only on virtual properties, they will rebuild the object
and give you a chance to sync (you MUST handle set_property in a construct-only case)
2008-09-29 Juan Pablo Ugarte <juanpablougarte@gmail.com>
* plugins/gtk+/glade-column-types.[ch]: added missing files.

3
TODO
View File

@ -12,7 +12,8 @@ Add versioning metadata for libglade unsupported properties and widgets.
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).

View File

@ -1073,7 +1073,6 @@ glade_command_remove (GList *widgets)
CommandData *cdata;
GtkWidget *placeholder;
GList *list, *l;
gchar *desc;
g_return_if_fail (widgets != NULL);
@ -1098,13 +1097,10 @@ glade_command_remove (GList *widgets)
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 @@ typedef struct {
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 @@ glade_command_set_i18n_execute(GladeCommand *cmd)
GladeCommandSetI18n *me = (GladeCommandSetI18n *)cmd;
gboolean temp_translatable;
gboolean temp_has_context;
gchar *temp_context;
gchar *temp_comment;
/* sanity check */
@ -1985,17 +1984,21 @@ glade_command_set_i18n_execute(GladeCommand *cmd)
/* 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 @@ glade_command_set_i18n_finalize(GObject *obj)
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 @@ glade_command_set_i18n_collapse (GladeCommand *this_cmd, GladeCommand *other_cmd
/* 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 @@ glade_command_set_i18n_collapse (GladeCommand *this_cmd, GladeCommand *other_cmd
* @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 @@ glade_command_set_i18n (GladeProperty *property, gboolean translatable, gboolean
/* 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 @@ glade_command_set_i18n (GladeProperty *property, gboolean translatable, gboolean
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 @@ glade_command_convert_cleanup (GladeProject *project,
GladeProjectFormat fmt)
{
GladeWidget *widget;
const GList *objects;
const GList *objects, *list;
for (objects = glade_project_get_objects (project); objects; objects = objects->next)
objects = glade_project_get_objects (project);
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 @@ glade_command_set_project_format (GladeProject *project,
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 @@ glade_command_set_project_format (GladeProject *project,
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

View File

@ -149,9 +149,10 @@ void glade_command_change_signal (GladeWidget *glade_widget,
/************************ 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

View File

@ -1662,25 +1662,43 @@ glade_eprop_text_buffer_changed (GtkTextBuffer *buffer,
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 @@ glade_eprop_text_show_i18n_dialog (GtkWidget *entry,
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 @@ glade_eprop_text_show_i18n_dialog (GtkWidget *entry,
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 @@ glade_eprop_text_show_i18n_dialog (GtkWidget *entry,
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 @@ glade_eprop_object_show_dialog (GtkWidget *dialog_button,
{
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 @@ glade_eprop_object_show_dialog (GtkWidget *dialog_button,
{
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)
{

View File

@ -157,6 +157,13 @@ void glade_editor_property_commit (GladeEditorProperty *
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())

View File

@ -1511,6 +1511,7 @@ glade_property_class_update_from_node (GladeXmlNode *node,
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);

View File

@ -72,6 +72,7 @@ enum
PROP_SENSITIVE,
PROP_I18N_TRANSLATABLE,
PROP_I18N_HAS_CONTEXT,
PROP_I18N_CONTEXT,
PROP_I18N_COMMENT,
PROP_STATE
};
@ -91,6 +92,7 @@ glade_property_dup_impl (GladeProperty *template_prop, GladeWidget *widget)
"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 @@ glade_property_sync_impl (GladeProperty *property)
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 @@ glade_property_sync_impl (GladeProperty *property)
property->klass->id,
property->value);
property->syncing = FALSE;
property->syncing--;
}
static void
@ -409,6 +424,9 @@ glade_property_set_real_property (GObject *object,
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 @@ glade_property_get_real_property (GObject *object,
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 @@ glade_property_init (GladeProperty *property)
property->i18n_translatable = TRUE;
property->i18n_has_context = FALSE;
property->i18n_comment = NULL;
property->sync_tolerance = 1;
}
static void
@ -527,6 +549,13 @@ glade_property_klass_init (GladePropertyKlass *prop_class)
_("This gives backends control to set property sensitivity"),
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
@ -1076,23 +1105,32 @@ glade_property_read (GladeProperty *property,
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_property_write (GladeProperty *property,
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,13 +1362,32 @@ glade_property_i18n_set_comment (GladeProperty *property,
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);
return property->i18n_comment;
}
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)

View File

@ -79,10 +79,12 @@ struct _GladeProperty
/* 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 @@ void glade_property_i18n_set_comment (GladeProperty
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);

View File

@ -619,15 +619,7 @@ glade_widget_sync_custom_props (GladeWidget *widget)
{
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 @@ void
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 @@ glade_widget_dup (GladeWidget *template_widget,
typedef struct
{
gchar *name;
GladeProperty *property;
GValue value;
} PropertyData;
@ -2174,8 +2165,8 @@ glade_widget_rebuild (GladeWidget *gwidget)
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 @@ glade_widget_rebuild (GladeWidget *gwidget)
/* 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 @@ glade_widget_rebuild (GladeWidget *gwidget)
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_rebuild (GladeWidget *gwidget)
*/
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.
*/

View File

@ -107,6 +107,7 @@ typedef enum
#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 @@ typedef enum
#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"

View File

@ -28,6 +28,7 @@
#include <string.h>
#include "glade-column-types.h"
#include "glade-model-data.h"
enum
{
@ -222,12 +223,14 @@ glade_eprop_column_types_finalize (GObject *object)
}
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 @@ eprop_reload_value (GladeEPropColumnTypes *eprop)
} 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

View File

@ -379,9 +379,8 @@ combos_data_tree_from_items (gchar **items)
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 @@ convert_combos_finished (GladeProject *project,
/* 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);
}

View File

@ -1352,14 +1352,14 @@ static void
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 @@ glade_gtk_store_set_columns (GObject *object,
}
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 @@ glade_gtk_store_set_data (GObject *object,
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 @@ glade_gtk_store_write_columns (GladeWidget *widget,
{
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_gtk_store_write_data (GladeWidget *widget,
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 @@ glade_gtk_store_read_columns (GladeWidget *widget, GladeXmlNode *node)
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 @@ glade_gtk_store_read_data (GladeWidget *widget, GladeXmlNode *node)
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);

View File

@ -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 @@ glade_model_data_copy (GladeModelData *data)
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 @@ glade_model_data_free (GladeModelData *data)
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 @@ glade_model_data_tree_free (GNode *node)
}
}
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 @@ glade_standard_model_data_spec (void)
}
/**************************** 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 @@ GLADE_MAKE_EPROP (GladeEPropModelData, glade_eprop_model_data)
static void
glade_eprop_model_data_add_clicked (GtkWidget *button,
GladeEPropModelData *eprop_types)
append_row (GNode *node, GList *columns)
{
/* Add new row with default values */
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,
GladeEditorProperty *eprop)
{
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 @@ eprop_treeview_row_deleted (GtkTreeModel *tree_model,
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 @@ eprop_model_data_generate_store (GladeEditorProperty *eprop)
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 @@ eprop_model_data_generate_columns (GladeEditorProperty *eprop)
GladeModelData *iter_data;
GtkTreeViewColumn *column;
GNode *data_tree = NULL, *iter_node;
gint colnum;
glade_property_get (eprop->property, &data_tree);
@ -315,11 +597,12 @@ eprop_model_data_generate_columns (GladeEditorProperty *eprop)
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 @@ glade_eprop_model_data_load (GladeEditorProperty *eprop,
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 @@ glade_eprop_model_data_create_input (GladeEditorProperty *eprop)
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 @@ glade_eprop_model_data_create_input (GladeEditorProperty *eprop)
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 @@ glade_eprop_model_data_create_input (GladeEditorProperty *eprop)
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;
}

View File

@ -32,7 +32,7 @@ struct _GladeModelData
gchar *name;
gboolean i18n_translatable;
gboolean i18n_has_context;
gchar *i18n_context;
gchar *i18n_comment;
};
@ -55,6 +55,8 @@ GType glade_eprop_model_data_get_type (void) G_GNUC_CONST;
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 @@ void glade_model_data_reorder_column (GNode *node,
gint column,
gint nth);
G_END_DECLS
#endif /* _GLADE_MODEL_DATA_H_ */

View File

@ -1797,7 +1797,7 @@ embedded in another object</_tooltip>
<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>