ComboBox fixes for changing models
- From: Owen Taylor <otaylor redhat com>
- To: gtk-devel-list gnome org
- Cc: kris gtk org, maclas gmx de, jrb redhat com
- Subject: ComboBox fixes for changing models
- Date: Tue, 02 Mar 2004 12:01:45 -0500
The attached is what I think is the correct fix for dealing with
models that change under the GtkComboBox. So far I've done no
testing other than compilation, but I'm going to try and
write up a test case now.
I'd very much appreciate it if one or more people could review,
especially someone who knows something about GtkTreeModel.
Thanks,
Owen
Tue Mar 2 11:45:50 2004 Owen Taylor <otaylor redhat com>
* gtk/gtkcombobox.c: Always connect to the changed
signals on the model, update the active item as
appropriate when rows are inserted/deleted/reordered,
re-layout the menu on ::rows-reordered.
* gtk/gtkcellview.c (gtk_cell_view_set_displayed_row):
Allow %NULL for path to unset and leave no current
path.
Index: gtk/gtkcellview.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcellview.c,v
retrieving revision 1.13
diff -u -p -r1.13 gtkcellview.c
--- gtk/gtkcellview.c 9 Feb 2004 21:19:35 -0000 1.13
+++ gtk/gtkcellview.c 2 Mar 2004 16:58:09 -0000
@@ -877,19 +877,35 @@ gtk_cell_view_set_model (GtkCellView *c
g_object_ref (G_OBJECT (cell_view->priv->model));
}
+/**
+ * gtk_cell_view_set_displayed_row:
+ * @cell_view: a #GtkCellView
+ * @path: a #GtkTreePath or %NULL to unset.
+ *
+ * Sets the row of the model that is currently displayed
+ * by the #GtkCellView. If the path is unset, then the
+ * contents of the cellview "stick" at their last value;
+ * this is not normally a desired result, but may be
+ * a needed intermediate state if say, the model for
+ * the #GtkCellView becomes temporarily empty.
+ **/
void
gtk_cell_view_set_displayed_row (GtkCellView *cell_view,
GtkTreePath *path)
{
g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
g_return_if_fail (GTK_IS_TREE_MODEL (cell_view->priv->model));
- g_return_if_fail (path != NULL);
if (cell_view->priv->displayed_row)
gtk_tree_row_reference_free (cell_view->priv->displayed_row);
- cell_view->priv->displayed_row =
- gtk_tree_row_reference_new (cell_view->priv->model, path);
+ if (path)
+ {
+ cell_view->priv->displayed_row =
+ gtk_tree_row_reference_new (cell_view->priv->model, path);
+ }
+ else
+ cell_view->priv->displayed_row = NULL;
/* force resize and redraw */
gtk_widget_queue_resize (GTK_WIDGET (cell_view));
Index: gtk/gtkcombobox.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcombobox.c,v
retrieving revision 1.50
diff -u -p -r1.50 gtkcombobox.c
--- gtk/gtkcombobox.c 29 Feb 2004 01:33:01 -0000 1.50
+++ gtk/gtkcombobox.c 2 Mar 2004 16:58:10 -0000
@@ -91,12 +91,12 @@ struct _GtkComboBoxPrivate
guint inserted_id;
guint deleted_id;
+ guint reordered_id;
+ guint changed_id;
gint width;
GSList *cells;
- guint changed_id;
-
guint popup_in_progress : 1;
};
@@ -233,6 +233,24 @@ static gboolean gtk_combo_box_expose_eve
static gboolean gtk_combo_box_scroll_event (GtkWidget *widget,
GdkEventScroll *event);
+/* listening to the model */
+static void gtk_combo_box_model_row_inserted (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data);
+static void gtk_combo_box_model_row_deleted (GtkTreeModel *model,
+ GtkTreePath *path,
+ gpointer user_data);
+static void gtk_combo_box_model_rows_reordered (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gint *new_order,
+ gpointer user_data);
+static void gtk_combo_box_model_row_changed (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data);
+
/* list */
static void gtk_combo_box_list_position (GtkComboBox *combo_box,
gint *x,
@@ -285,6 +303,11 @@ static void gtk_combo_box_menu_row_i
static void gtk_combo_box_menu_row_deleted (GtkTreeModel *model,
GtkTreePath *path,
gpointer user_data);
+static void gtk_combo_box_menu_rows_reordered (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gint *new_order,
+ gpointer user_data);
static void gtk_combo_box_menu_row_changed (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
@@ -1244,6 +1267,12 @@ gtk_combo_box_unset_model (GtkComboBox *
combo_box->priv->deleted_id);
combo_box->priv->deleted_id = -1;
}
+ if (combo_box->priv->reordered_id != -1)
+ {
+ g_signal_handler_disconnect (combo_box->priv->model,
+ combo_box->priv->reordered_id);
+ combo_box->priv->reordered_id = -1;
+ }
if (combo_box->priv->changed_id != -1)
{
g_signal_handler_disconnect (combo_box->priv->model,
@@ -1263,32 +1292,28 @@ gtk_combo_box_unset_model (GtkComboBox *
static void
gtk_combo_box_set_model_internal (GtkComboBox *combo_box)
{
- if (!combo_box->priv->tree_view)
- {
- /* menu mode */
- combo_box->priv->inserted_id =
- g_signal_connect (combo_box->priv->model, "row_inserted",
- G_CALLBACK (gtk_combo_box_menu_row_inserted),
- combo_box);
- combo_box->priv->deleted_id =
- g_signal_connect (combo_box->priv->model, "row_deleted",
- G_CALLBACK (gtk_combo_box_menu_row_deleted),
- combo_box);
- combo_box->priv->changed_id =
- g_signal_connect (combo_box->priv->model, "row_changed",
- G_CALLBACK (gtk_combo_box_menu_row_changed),
- combo_box);
- }
- else
+ combo_box->priv->inserted_id =
+ g_signal_connect (combo_box->priv->model, "row_inserted",
+ G_CALLBACK (gtk_combo_box_model_row_inserted),
+ combo_box);
+ combo_box->priv->deleted_id =
+ g_signal_connect (combo_box->priv->model, "row_deleted",
+ G_CALLBACK (gtk_combo_box_model_row_deleted),
+ combo_box);
+ combo_box->priv->reordered_id =
+ g_signal_connect (combo_box->priv->model, "rows_reordered",
+ G_CALLBACK (gtk_combo_box_model_rows_reordered),
+ combo_box);
+ combo_box->priv->changed_id =
+ g_signal_connect (combo_box->priv->model, "row_changed",
+ G_CALLBACK (gtk_combo_box_model_row_changed),
+ combo_box);
+
+ if (combo_box->priv->tree_view)
{
/* list mode */
gtk_tree_view_set_model (GTK_TREE_VIEW (combo_box->priv->tree_view),
combo_box->priv->model);
-
- combo_box->priv->changed_id =
- g_signal_connect (combo_box->priv->model, "row_changed",
- G_CALLBACK (gtk_combo_box_list_row_changed),
- combo_box);
}
}
@@ -1767,6 +1792,89 @@ gtk_combo_box_menu_item_activate (GtkWid
}
static void
+gtk_combo_box_model_row_inserted (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ GtkComboBox *combo_box = GTK_COMBO_BOX (user_data);
+ gint index = gtk_tree_path_get_indices (path)[0];
+
+ if (combo_box->priv->active_item >= index)
+ combo_box->priv->active_item++;
+
+ if (!combo_box->priv->tree_view)
+ gtk_combo_box_menu_row_inserted (model, path, iter, user_data);
+}
+
+static void
+gtk_combo_box_model_row_deleted (GtkTreeModel *model,
+ GtkTreePath *path,
+ gpointer user_data)
+{
+ GtkComboBox *combo_box = GTK_COMBO_BOX (user_data);
+ gint index = gtk_tree_path_get_indices (path)[0];
+
+ if (index == combo_box->priv->active_item)
+ {
+ gint items = gtk_tree_model_iter_n_children (model, NULL);
+
+ if (items == 0)
+ gtk_combo_box_set_active (combo_box, -1);
+ else
+ gtk_combo_box_set_active (combo_box, (index + 1) % items);
+ }
+ else if (combo_box->priv->active_item > index)
+ combo_box->priv->active_item--;
+
+ if (!combo_box->priv->tree_view)
+ gtk_combo_box_menu_row_deleted (model, path, user_data);
+}
+
+static void
+gtk_combo_box_model_rows_reordered (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gint *new_order,
+ gpointer user_data)
+{
+ GtkComboBox *combo_box = GTK_COMBO_BOX (user_data);
+ gint items = gtk_tree_model_iter_n_children (model, NULL);
+ gint i;
+
+ for (i = 0; i < items; i++)
+ if (new_order[i] == combo_box->priv->active_item)
+ {
+ combo_box->priv->active_item = i;
+ break;
+ }
+
+ if (!combo_box->priv->tree_view)
+ gtk_combo_box_menu_rows_reordered (model, path, iter, new_order, user_data);
+
+}
+
+static void
+gtk_combo_box_model_row_changed (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ GtkComboBox *combo_box = GTK_COMBO_BOX (user_data);
+ gint index = gtk_tree_path_get_indices (path)[0];
+
+ if (index == combo_box->priv->active_item &&
+ combo_box->priv->cell_view)
+ gtk_widget_queue_resize (GTK_WIDGET (combo_box->priv->cell_view));
+
+ if (combo_box->priv->tree_view)
+ gtk_combo_box_list_row_changed (model, path, iter, user_data);
+ else
+ gtk_combo_box_menu_row_changed (model, path, iter, user_data);
+}
+
+
+static void
gtk_combo_box_menu_row_inserted (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
@@ -1799,7 +1907,7 @@ gtk_combo_box_menu_row_deleted (GtkTreeM
GtkTreePath *path,
gpointer user_data)
{
- gint index, items;
+ gint index;
GtkWidget *menu;
GtkWidget *item;
GtkComboBox *combo_box = GTK_COMBO_BOX (user_data);
@@ -1808,10 +1916,6 @@ gtk_combo_box_menu_row_deleted (GtkTreeM
return;
index = gtk_tree_path_get_indices (path)[0];
- items = gtk_tree_model_iter_n_children (model, NULL);
-
- if (gtk_combo_box_get_active (combo_box) == index)
- gtk_combo_box_set_active (combo_box, index + 1 % items);
menu = combo_box->priv->popup_widget;
g_return_if_fail (GTK_IS_MENU (menu));
@@ -1823,6 +1927,18 @@ gtk_combo_box_menu_row_deleted (GtkTreeM
}
static void
+gtk_combo_box_menu_rows_reordered (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gint *new_order,
+ gpointer user_data)
+{
+ GtkComboBox *combo_box = GTK_COMBO_BOX (user_data);
+
+ gtk_combo_box_relayout (combo_box);
+}
+
+static void
gtk_combo_box_menu_row_changed (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]