[gtk+] Bug 619148 - "active ID" properties (GtkComboBox)



commit 922324553be10f847d4bdc3a177e641887a2921d
Author: Ryan Lortie <desrt desrt ca>
Date:   Tue Nov 30 00:07:08 2010 -0500

    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.

 demos/gtk-demo/combobox.c            |   21 +++-
 docs/reference/gtk/gtk3-sections.txt |    9 ++-
 gtk/gtk.symbols                      |    7 +
 gtk/gtkcombobox.c                    |  211 +++++++++++++++++++++++++++++++++-
 gtk/gtkcombobox.h                    |    6 +
 gtk/gtkcomboboxtext.c                |  101 ++++++++++++++++-
 gtk/gtkcomboboxtext.h                |   10 ++
 7 files changed, 358 insertions(+), 7 deletions(-)
---
diff --git a/demos/gtk-demo/combobox.c b/demos/gtk-demo/combobox.c
index b0f45d3..308242b 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 5201e19..7ae2f72 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 b1b0172..1c86e1e 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 9fc50d3..ebdd7f5 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,};
@@ -949,6 +953,38 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass)
 						      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:
     *
     * Whether the popup's width should be a fixed width matching the
@@ -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 c8931eb..1c674b9 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 d36d6dc..c7b82d1 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,6 +172,11 @@ 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
@@ -171,15 +184,84 @@ 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;
   gint text_column;
   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 ae08d2d..d1c362f 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
 



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