From: Ryan Lortie Date: Tue, 30 Nov 2010 05:07:08 +0000 (-0500) Subject: Bug 619148 - "active ID" properties (GtkComboBox) X-Git-Url: http://pileus.org/git/?a=commitdiff_plain;h=922324553be10f847d4bdc3a177e641887a2921d;p=~andy%2Fgtk Bug 619148 - "active ID" properties (GtkComboBox) Based on a patch by Matthias, add an "active-id" property for GtkComboBox and add some convenience API for GtkComboBoxText. Also, add a test case to gtk-demo. --- diff --git a/demos/gtk-demo/combobox.c b/demos/gtk-demo/combobox.c index b0f45d310..308242b10 100644 --- a/demos/gtk-demo/combobox.c +++ b/demos/gtk-demo/combobox.c @@ -437,7 +437,26 @@ do_combobox (GtkWidget *do_widget) gtk_container_remove (GTK_CONTAINER (combo), gtk_bin_get_child (GTK_BIN (combo))); gtk_container_add (GTK_CONTAINER (combo), entry); - + + /* A combobox with string IDs */ + frame = gtk_frame_new ("String IDs"); + gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); + + box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_container_set_border_width (GTK_CONTAINER (box), 5); + gtk_container_add (GTK_CONTAINER (frame), box); + + combo = gtk_combo_box_text_new (); + gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "never", "Not visible"); + gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "when-active", "Visible when active"); + gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "always", "Always visible"); + gtk_container_add (GTK_CONTAINER (box), combo); + + entry = gtk_entry_new (); + g_object_bind_property (combo, "active-id", + entry, "text", + G_BINDING_BIDIRECTIONAL); + gtk_container_add (GTK_CONTAINER (box), entry); } if (!gtk_widget_get_visible (window)) diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt index 5201e19ae..7ae2f72d8 100644 --- a/docs/reference/gtk/gtk3-sections.txt +++ b/docs/reference/gtk/gtk3-sections.txt @@ -801,6 +801,10 @@ gtk_combo_box_get_active gtk_combo_box_set_active gtk_combo_box_get_active_iter gtk_combo_box_set_active_iter +gtk_combo_box_get_id_column +gtk_combo_box_set_id_column +gtk_combo_box_get_active_id +gtk_combo_box_set_active_id gtk_combo_box_get_model gtk_combo_box_set_model gtk_combo_box_popup_for_device @@ -840,9 +844,12 @@ gtk_combo_box_get_type GtkComboBoxText gtk_combo_box_text_new gtk_combo_box_text_new_with_entry +gtk_combo_box_text_append +gtk_combo_box_text_prepend +gtk_combo_box_text_insert gtk_combo_box_text_append_text -gtk_combo_box_text_insert_text gtk_combo_box_text_prepend_text +gtk_combo_box_text_insert_text gtk_combo_box_text_remove gtk_combo_box_text_remove_all gtk_combo_box_text_get_active_text diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index b1b017265..1c86e1e85 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -490,6 +490,7 @@ gtk_color_selection_set_previous_alpha gtk_color_selection_set_previous_color gtk_color_selection_set_previous_rgba gtk_combo_box_get_active +gtk_combo_box_get_active_id gtk_combo_box_get_active_iter gtk_combo_box_get_add_tearoffs gtk_combo_box_get_button_sensitivity @@ -497,6 +498,7 @@ gtk_combo_box_get_column_span_column gtk_combo_box_get_entry_text_column gtk_combo_box_get_focus_on_click gtk_combo_box_get_has_entry +gtk_combo_box_get_id_column gtk_combo_box_get_model gtk_combo_box_get_popup_accessible gtk_combo_box_get_popup_fixed_width @@ -513,24 +515,29 @@ gtk_combo_box_popdown gtk_combo_box_popup gtk_combo_box_popup_for_device gtk_combo_box_set_active +gtk_combo_box_set_active_id gtk_combo_box_set_active_iter gtk_combo_box_set_add_tearoffs gtk_combo_box_set_button_sensitivity gtk_combo_box_set_column_span_column gtk_combo_box_set_entry_text_column gtk_combo_box_set_focus_on_click +gtk_combo_box_set_id_column gtk_combo_box_set_model gtk_combo_box_set_popup_fixed_width gtk_combo_box_set_row_separator_func gtk_combo_box_set_row_span_column gtk_combo_box_set_title gtk_combo_box_set_wrap_width +gtk_combo_box_text_append gtk_combo_box_text_append_text gtk_combo_box_text_get_active_text gtk_combo_box_text_get_type G_GNUC_CONST +gtk_combo_box_text_insert gtk_combo_box_text_insert_text gtk_combo_box_text_new gtk_combo_box_text_new_with_entry +gtk_combo_box_text_prepend gtk_combo_box_text_prepend_text gtk_combo_box_text_remove gtk_combo_box_text_remove_all diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c index 9fc50d3f7..ebdd7f5e1 100644 --- a/gtk/gtkcombobox.c +++ b/gtk/gtkcombobox.c @@ -143,6 +143,8 @@ struct _GtkComboBoxPrivate gint text_column; GtkCellRenderer *text_renderer; + gint id_column; + GSList *cells; guint popup_in_progress : 1; @@ -245,7 +247,9 @@ enum { PROP_EDITING_CANCELED, PROP_HAS_ENTRY, PROP_ENTRY_TEXT_COLUMN, - PROP_POPUP_FIXED_WIDTH + PROP_POPUP_FIXED_WIDTH, + PROP_ID_COLUMN, + PROP_ACTIVE_ID }; static guint combo_box_signals[LAST_SIGNAL] = {0,}; @@ -948,6 +952,38 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass) -1, G_MAXINT, -1, GTK_PARAM_READWRITE)); + /** + * GtkComboBox:id-column: + * + * The column in the combo box's model that provides string + * IDs for the values in the model, if != -1. + * + * Since: 3.0 + */ + g_object_class_install_property (object_class, + PROP_ID_COLUMN, + g_param_spec_int ("id-column", + P_("ID Column"), + P_("The column in the combo box's model that provides " + "string IDs for the values in the model"), + -1, G_MAXINT, -1, + GTK_PARAM_READWRITE)); + + /** + * GtkComboBox:active-id: + * + * The value of the ID column of the active row. + * + * Since: 3.0 + */ + g_object_class_install_property (object_class, + PROP_ACTIVE_ID, + g_param_spec_string ("active-id", + P_("Active id"), + P_("The value of the id column " + "for the active row"), + NULL, GTK_PARAM_READWRITE)); + /** * GtkComboBox:popup-fixed-width: * @@ -1077,6 +1113,7 @@ gtk_combo_box_init (GtkComboBox *combo_box) priv->text_column = -1; priv->text_renderer = NULL; + priv->id_column = -1; gtk_combo_box_check_appearance (combo_box); } @@ -1168,6 +1205,14 @@ gtk_combo_box_set_property (GObject *object, gtk_combo_box_set_entry_text_column (combo_box, g_value_get_int (value)); break; + case PROP_ID_COLUMN: + gtk_combo_box_set_id_column (combo_box, g_value_get_int (value)); + break; + + case PROP_ACTIVE_ID: + gtk_combo_box_set_active_id (combo_box, g_value_get_string (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1245,6 +1290,14 @@ gtk_combo_box_get_property (GObject *object, g_value_set_int (value, priv->text_column); break; + case PROP_ID_COLUMN: + g_value_set_int (value, priv->id_column); + break; + + case PROP_ACTIVE_ID: + g_value_set_string (value, gtk_combo_box_get_active_id (combo_box)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -5200,6 +5253,8 @@ gtk_combo_box_set_active_internal (GtkComboBox *combo_box, g_signal_emit (combo_box, combo_box_signals[CHANGED], 0); g_object_notify (G_OBJECT (combo_box), "active"); + if (combo_box->priv->id_column >= 0) + g_object_notify (G_OBJECT (combo_box), "active-id"); } @@ -6588,3 +6643,157 @@ gtk_combo_box_get_preferred_height_for_width (GtkWidget *widget, if (natural_size) *natural_size = nat_height; } + +/** + * gtk_combo_box_set_id_column: + * @combo_box: A #GtkComboBox + * @id_column: A column in @model to get string IDs for values from + * + * Sets the model column which @combo_box should use to get string IDs + * for values from. The column @id_column in the model of @combo_box + * must be of type %G_TYPE_STRING. + * + * Since: 3.0 + */ +void +gtk_combo_box_set_id_column (GtkComboBox *combo_box, + gint id_column) +{ + GtkComboBoxPrivate *priv = combo_box->priv; + GtkTreeModel *model; + + g_return_if_fail (GTK_IS_COMBO_BOX (combo_box)); + + if (id_column != priv->id_column) + { + model = gtk_combo_box_get_model (combo_box); + + g_return_if_fail (id_column >= 0); + g_return_if_fail (model == NULL || + id_column < gtk_tree_model_get_n_columns (model)); + + priv->id_column = id_column; + + g_object_notify (G_OBJECT (combo_box), "id-column"); + g_object_notify (G_OBJECT (combo_box), "active-id"); + } +} + +/** + * gtk_combo_box_get_id_column: + * @combo_box: A #GtkComboBox + * + * Returns the column which @combo_box is using to get string IDs + * for values from. + * + * Return value: A column in the data source model of @combo_box. + * + * Since: 3.0 + */ +gint +gtk_combo_box_get_id_column (GtkComboBox *combo_box) +{ + g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), 0); + + return combo_box->priv->id_column; +} + +/** + * gtk_combo_box_get_active_id: + * @combo_box: a #GtkComboBox + * + * Returns the ID of the active row of @combo_box. This value is taken + * from the active row and the column specified by the 'id-column' + * property of @combo_box (see gtk_combo_box_set_id_column()). + * + * The returned value is an interned string which means that you can + * compare the pointer by value to other interned strings and that you + * must not free it. + * + * If the 'id-column' property of @combo_box is not set or if no row is + * selected then %NULL is returned. + * + * Return value: the ID of the active row, or %NULL + * + * Since: 3.0 + **/ +const gchar * +gtk_combo_box_get_active_id (GtkComboBox *combo_box) +{ + GtkTreeModel *model; + GtkTreeIter iter; + gint column; + + g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), 0); + + column = combo_box->priv->id_column; + + if (column < 0) + return NULL; + + model = gtk_combo_box_get_model (combo_box); + g_return_val_if_fail (gtk_tree_model_get_column_type (model, column) == + G_TYPE_STRING, NULL); + + if (gtk_combo_box_get_active_iter (combo_box, &iter)) + { + const gchar *interned; + gchar *id; + + gtk_tree_model_get (model, &iter, column, &id, -1); + interned = g_intern_string (id); + g_free (id); + + return interned; + } + + return NULL; +} + +/** + * gtk_combo_box_set_active_id: + * @combo_box: a #GtkComboBox + * @active_id: the ID of the row to select + * + * Changes the active row of @combo_box to the one that has an ID equal to @id. + * + * If the 'id-column' property of @combo_box is unset or if no row has + * the given ID then nothing happens. + * + * Since: 3.0 + **/ +void +gtk_combo_box_set_active_id (GtkComboBox *combo_box, + const gchar *active_id) +{ + GtkTreeModel *model; + GtkTreeIter iter; + gint column; + + g_return_if_fail (GTK_IS_COMBO_BOX (combo_box)); + + column = combo_box->priv->id_column; + + if (column < 0) + return; + + model = gtk_combo_box_get_model (combo_box); + g_return_if_fail (gtk_tree_model_get_column_type (model, column) == + G_TYPE_STRING); + + if (gtk_tree_model_get_iter_first (model, &iter)) + do { + gboolean match; + gchar *id; + + gtk_tree_model_get (model, &iter, column, &id, -1); + match = strcmp (id, active_id) == 0; + g_free (id); + + if (match) + { + gtk_combo_box_set_active_iter (combo_box, &iter); + break; + } + } while (gtk_tree_model_iter_next (model, &iter)); +} diff --git a/gtk/gtkcombobox.h b/gtk/gtkcombobox.h index c8931eb3b..1c674b9c0 100644 --- a/gtk/gtkcombobox.h +++ b/gtk/gtkcombobox.h @@ -134,6 +134,12 @@ void gtk_combo_box_popup_for_device (GtkComboBox *combo_box, void gtk_combo_box_popdown (GtkComboBox *combo_box); AtkObject* gtk_combo_box_get_popup_accessible (GtkComboBox *combo_box); +gint gtk_combo_box_get_id_column (GtkComboBox *combo_box); +void gtk_combo_box_set_id_column (GtkComboBox *combo_box, + gint id_column); +const gchar * gtk_combo_box_get_active_id (GtkComboBox *combo_box); +void gtk_combo_box_set_active_id (GtkComboBox *combo_box, + const gchar *active_id); G_END_DECLS diff --git a/gtk/gtkcomboboxtext.c b/gtk/gtkcomboboxtext.c index d36d6dc25..c7b82d106 100644 --- a/gtk/gtkcomboboxtext.c +++ b/gtk/gtkcomboboxtext.c @@ -72,7 +72,7 @@ gtk_combo_box_text_init (GtkComboBoxText *combo_box) { GtkListStore *store; - store = gtk_list_store_new (1, G_TYPE_STRING); + store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (store)); g_object_unref (store); } @@ -102,6 +102,7 @@ gtk_combo_box_text_new (void) { return g_object_new (GTK_TYPE_COMBO_BOX_TEXT, "entry-text-column", 0, + "id-column", 1, NULL); } @@ -121,6 +122,7 @@ gtk_combo_box_text_new_with_entry (void) return g_object_new (GTK_TYPE_COMBO_BOX_TEXT, "has-entry", TRUE, "entry-text-column", 0, + "id-column", 1, NULL); } @@ -131,13 +133,16 @@ gtk_combo_box_text_new_with_entry (void) * * Appends @text to the list of strings stored in @combo_box. * + * This is the same as calling gtk_combo_box_text_insert_text() with a + * position of -1. + * * Since: 2.24 */ void gtk_combo_box_text_append_text (GtkComboBoxText *combo_box, const gchar *text) { - gtk_combo_box_text_insert_text (combo_box, G_MAXINT, text); + gtk_combo_box_text_insert (combo_box, -1, NULL, text); } /** @@ -147,13 +152,16 @@ gtk_combo_box_text_append_text (GtkComboBoxText *combo_box, * * Prepends @text to the list of strings stored in @combo_box. * + * This is the same as calling gtk_combo_box_text_insert_text() with a + * position of 0. + * * Since: 2.24 */ void gtk_combo_box_text_prepend_text (GtkComboBoxText *combo_box, const gchar *text) { - gtk_combo_box_text_insert_text (combo_box, 0, text); + gtk_combo_box_text_insert (combo_box, 0, NULL, text); } /** @@ -164,12 +172,84 @@ gtk_combo_box_text_prepend_text (GtkComboBoxText *combo_box, * * Inserts @text at @position in the list of strings stored in @combo_box. * + * If @position is negative then @text is appended. + * + * This is the same as calling gtk_combo_box_text_insert() with a %NULL + * ID string. + * * Since: 2.24 */ void gtk_combo_box_text_insert_text (GtkComboBoxText *combo_box, gint position, const gchar *text) +{ + gtk_combo_box_text_insert (combo_box, position, NULL, text); +} + +/** + * gtk_combo_box_text_append: + * @combo_box: A #GtkComboBoxText + * @text: A string + * + * Appends @text to the list of strings stored in @combo_box. If @id is + * non-%NULL then it is used as the ID of the row. + * + * This is the same as calling gtk_combo_box_text_insert() with a + * position of -1. + * + * Since: 2.24 + */ +void +gtk_combo_box_text_append (GtkComboBoxText *combo_box, + const gchar *id, + const gchar *text) +{ + gtk_combo_box_text_insert (combo_box, -1, id, text); +} + +/** + * gtk_combo_box_text_prepend: + * @combo_box: A #GtkComboBox + * @text: A string + * + * Prepends @text to the list of strings stored in @combo_box. If @id + * is non-%NULL then it is used as the ID of the row. + * + * This is the same as calling gtk_combo_box_text_insert() with a + * position of 0. + * + * Since: 2.24 + */ +void +gtk_combo_box_text_prepend (GtkComboBoxText *combo_box, + const gchar *id, + const gchar *text) +{ + gtk_combo_box_text_insert (combo_box, 0, id, text); +} + + +/** + * gtk_combo_box_text_insert: + * @combo_box: A #GtkComboBoxText + * @position: An index to insert @text + * @id: a string ID for this value, or %NULL + * @text: A string to display + * + * Inserts @text at @position in the list of strings stored in @combo_box. + * If @id is non-%NULL then it is used as the ID of the row. See + * #GtkComboBox::id-column. + * + * If @position is negative then @text is appended. + * + * Since: 3.0 + */ +void +gtk_combo_box_text_insert (GtkComboBoxText *combo_box, + gint position, + const gchar *id, + const gchar *text) { GtkListStore *store; GtkTreeIter iter; @@ -177,9 +257,11 @@ gtk_combo_box_text_insert_text (GtkComboBoxText *combo_box, gint column_type; g_return_if_fail (GTK_IS_COMBO_BOX_TEXT (combo_box)); - g_return_if_fail (position >= 0); g_return_if_fail (text != NULL); + if (position < 0) + position = G_MAXINT; + store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box))); g_return_if_fail (GTK_IS_LIST_STORE (store)); text_column = gtk_combo_box_get_entry_text_column (GTK_COMBO_BOX (combo_box)); @@ -188,6 +270,17 @@ gtk_combo_box_text_insert_text (GtkComboBoxText *combo_box, gtk_list_store_insert (store, &iter, position); gtk_list_store_set (store, &iter, text_column, text, -1); + + if (id != NULL) + { + gint id_column; + + id_column = gtk_combo_box_get_id_column (GTK_COMBO_BOX (combo_box)); + column_type = gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), id_column); + g_return_if_fail (column_type == G_TYPE_STRING); + + gtk_list_store_set (store, &iter, id_column, id, -1); + } } /** diff --git a/gtk/gtkcomboboxtext.h b/gtk/gtkcomboboxtext.h index ae08d2d40..d1c362f30 100644 --- a/gtk/gtkcomboboxtext.h +++ b/gtk/gtkcomboboxtext.h @@ -72,6 +72,16 @@ void gtk_combo_box_text_remove (GtkComboBoxText *combo_box void gtk_combo_box_text_remove_all (GtkComboBoxText *combo_box); gchar *gtk_combo_box_text_get_active_text (GtkComboBoxText *combo_box); +void gtk_combo_box_text_insert (GtkComboBoxText *combo_box, + gint position, + const gchar *id, + const gchar *text); +void gtk_combo_box_text_append (GtkComboBoxText *combo_box, + const gchar *id, + const gchar *text); +void gtk_combo_box_text_prepend (GtkComboBoxText *combo_box, + const gchar *id, + const gchar *text); G_END_DECLS