From 2677a7d5b9ec469049f63c4f99b86d95e7dd4f63 Mon Sep 17 00:00:00 2001 From: Tristan Van Berkom Date: Thu, 6 Oct 2011 11:14:38 +0200 Subject: [PATCH] GtkComboBox: Add the format-entry-text signal. This provides more control over how the selected item is shown in the entry. Bug #631167 --- gtk/gtkcombobox.c | 104 +++++++++++++++++++++++++++++++++++++---- gtk/gtkcombobox.h | 5 +- gtk/gtkmain.c | 16 +++++++ gtk/gtkmainprivate.h | 5 ++ gtk/gtkmarshalers.list | 1 + gtk/gtkscale.c | 20 +------- 6 files changed, 123 insertions(+), 28 deletions(-) diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c index eb3f319a1f..c0bf2c8bf1 100644 --- a/gtk/gtkcombobox.c +++ b/gtk/gtkcombobox.c @@ -41,6 +41,7 @@ #include "gtkseparator.h" #include "gtkwindow.h" #include "gtktypebuiltins.h" +#include "gtkmainprivate.h" #include "gtkprivate.h" #include @@ -217,6 +218,7 @@ enum { MOVE_ACTIVE, POPUP, POPDOWN, + FORMAT_ENTRY_TEXT, LAST_SIGNAL }; @@ -421,7 +423,8 @@ static void gtk_combo_box_entry_contents_changed (GtkEntry *e gpointer user_data); static void gtk_combo_box_entry_active_changed (GtkComboBox *combo_box, gpointer user_data); - +static gchar *gtk_combo_box_format_entry_text (GtkComboBox *combo_box, + const gchar *path); /* GtkBuildable method implementation */ static GtkBuildableIface *parent_buildable_iface; @@ -512,6 +515,8 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass) object_class->set_property = gtk_combo_box_set_property; object_class->get_property = gtk_combo_box_get_property; + klass->format_entry_text = gtk_combo_box_format_entry_text; + /* signals */ /** * GtkComboBox::changed: @@ -596,6 +601,58 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass) _gtk_marshal_BOOLEAN__VOID, G_TYPE_BOOLEAN, 0); + /** + * GtkComboBox::format-entry-text: + * @combo: the object which received the signal + * @path: the GtkTreePath string from the combo box's current model to format text for + * + * For combo boxes that are created with an entry (See GtkComboBox:has-entry). + * + * A signal which allows you to change how the text displayed in a combo box's + * entry is displayed. + * + * Connect a signal handler which returns an allocated string representing + * @path. That string will then be used to set the text in the combo box's entry. + * The default signal handler uses the text from the GtkComboBox::entry-text-column + * model column. + * + * Here's an example signal handler which fetches data from the model and + * displays it in the entry. + * |[ + * static gchar* + * format_entry_text_callback (GtkComboBox *combo, + * const gchar *path, + * gpointer user_data) + * { + * GtkTreeIter iter; + * GtkTreeModel model; + * gdouble value; + * + * model = gtk_combo_box_get_model (combo); + * + * gtk_tree_model_get_iter_from_string (model, &iter, path); + * gtk_tree_model_get (model, &iter, + * THE_DOUBLE_VALUE_COLUMN, &value, + * -1); + * + * return g_strdup_printf ("%g", value); + * } + * ]| + * + * Return value: (transfer full): a newly allocated string representing @path + * for the current GtkComboBox model. + * + * Since: 3.4 + */ + combo_box_signals[FORMAT_ENTRY_TEXT] = + g_signal_new (I_("format-entry-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkComboBoxClass, format_entry_text), + _gtk_single_string_accumulator, NULL, + _gtk_marshal_STRING__STRING, + G_TYPE_STRING, 1, G_TYPE_STRING); + /* key bindings */ binding_set = gtk_binding_set_by_class (widget_class); @@ -4614,7 +4671,6 @@ static void gtk_combo_box_entry_active_changed (GtkComboBox *combo_box, gpointer user_data) { - GtkComboBoxPrivate *priv = combo_box->priv; GtkTreeModel *model; GtkTreeIter iter; @@ -4624,26 +4680,58 @@ gtk_combo_box_entry_active_changed (GtkComboBox *combo_box, if (entry) { - GValue value = {0,}; + GtkTreePath *path; + gchar *path_str; + gchar *text = NULL; + + model = gtk_combo_box_get_model (combo_box); + path = gtk_tree_model_get_path (model, &iter); + path_str = gtk_tree_path_to_string (path); g_signal_handlers_block_by_func (entry, gtk_combo_box_entry_contents_changed, combo_box); - model = gtk_combo_box_get_model (combo_box); - gtk_tree_model_get_value (model, &iter, - priv->text_column, &value); - g_object_set_property (G_OBJECT (entry), "text", &value); - g_value_unset (&value); + g_signal_emit (combo_box, combo_box_signals[FORMAT_ENTRY_TEXT], 0, + path_str, &text); + + gtk_entry_set_text (entry, text); g_signal_handlers_unblock_by_func (entry, gtk_combo_box_entry_contents_changed, combo_box); + + gtk_tree_path_free (path); + g_free (text); + g_free (path_str); } } } +static gchar * +gtk_combo_box_format_entry_text (GtkComboBox *combo_box, + const gchar *path) +{ + GtkComboBoxPrivate *priv = combo_box->priv; + GtkTreeModel *model; + GtkTreeIter iter; + gchar *text = NULL; + + if (priv->text_column >= 0) + { + model = gtk_combo_box_get_model (combo_box); + gtk_tree_model_get_iter_from_string (model, &iter, path); + + gtk_tree_model_get (model, &iter, + priv->text_column, &text, + -1); + } + + return text; +} + + static GObject * gtk_combo_box_constructor (GType type, guint n_construct_properties, diff --git a/gtk/gtkcombobox.h b/gtk/gtkcombobox.h index 776d1b74be..b13834cf58 100644 --- a/gtk/gtkcombobox.h +++ b/gtk/gtkcombobox.h @@ -54,13 +54,14 @@ struct _GtkComboBoxClass GtkBinClass parent_class; /* signals */ - void (* changed) (GtkComboBox *combo_box); + void (* changed) (GtkComboBox *combo_box); + gchar *(* format_entry_text) (GtkComboBox *combo_box, + const gchar *path); /* Padding for future expansion */ void (*_gtk_reserved1) (void); void (*_gtk_reserved2) (void); void (*_gtk_reserved3) (void); - void (*_gtk_reserved4) (void); }; diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index a0ca89dfb5..84bbb5f771 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -2643,3 +2643,19 @@ _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint, return continue_emission; } + +gboolean +_gtk_single_string_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy) +{ + gboolean continue_emission; + const gchar *str; + + str = g_value_get_string (handler_return); + g_value_set_string (return_accu, str); + continue_emission = str == NULL; + + return continue_emission; +} diff --git a/gtk/gtkmainprivate.h b/gtk/gtkmainprivate.h index 56679389fc..32530126d9 100644 --- a/gtk/gtkmainprivate.h +++ b/gtk/gtkmainprivate.h @@ -28,6 +28,11 @@ gboolean _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint, const GValue *handler_return, gpointer dummy); +gboolean _gtk_single_string_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy); + gchar *_gtk_get_lc_ctype (void); gboolean _gtk_module_has_mixed_deps (GModule *module); diff --git a/gtk/gtkmarshalers.list b/gtk/gtkmarshalers.list index fa60a7c91d..e104d31263 100644 --- a/gtk/gtkmarshalers.list +++ b/gtk/gtkmarshalers.list @@ -50,6 +50,7 @@ ENUM:VOID INT:POINTER OBJECT:VOID STRING:DOUBLE +STRING:STRING VOID:DOUBLE VOID:BOOLEAN VOID:BOOLEAN,BOOLEAN,BOOLEAN diff --git a/gtk/gtkscale.c b/gtk/gtkscale.c index 979f45f66b..4effb04f0c 100644 --- a/gtk/gtkscale.c +++ b/gtk/gtkscale.c @@ -41,6 +41,7 @@ #include "gtkintl.h" #include "gtkbuildable.h" #include "gtkbuilderprivate.h" +#include "gtkmainprivate.h" #include "a11y/gtkscaleaccessible.h" @@ -166,23 +167,6 @@ G_DEFINE_TYPE_WITH_CODE (GtkScale, gtk_scale, GTK_TYPE_RANGE, gtk_scale_buildable_interface_init)) -static gboolean -single_string_accumulator (GSignalInvocationHint *ihint, - GValue *return_accu, - const GValue *handler_return, - gpointer dummy) -{ - gboolean continue_emission; - const gchar *str; - - str = g_value_get_string (handler_return); - g_value_set_string (return_accu, str); - continue_emission = str == NULL; - - return continue_emission; -} - - #define add_slider_binding(binding_set, keyval, mask, scroll) \ gtk_binding_entry_add_signal (binding_set, keyval, mask, \ I_("move-slider"), 1, \ @@ -243,7 +227,7 @@ gtk_scale_class_init (GtkScaleClass *class) G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkScaleClass, format_value), - single_string_accumulator, NULL, + _gtk_single_string_accumulator, NULL, _gtk_marshal_STRING__DOUBLE, G_TYPE_STRING, 1, G_TYPE_DOUBLE);