From f19af6f49ca75f667523b1b89ea873584fb7e7b5 Mon Sep 17 00:00:00 2001 From: Jonathan Blandford Date: Thu, 29 Mar 2001 21:30:05 +0000 Subject: Massive reordering/sorting work. Now pretty much works. Thu Mar 29 16:29:12 2001 Jonathan Blandford * gtk/gtkliststore.c (gtk_list_store_iter_changed): Massive reordering/sorting work. Now pretty much works. * gtk/gtkrbtree.c (_gtk_rbtree_reorder): Lots of work to make reorder mostly work. Still need to get the parity correct. * gtk/gtktreeviewcolumn.c: Listen for "model" property changed signal, so I can listen for the sort_column_changed signal so I can change my "sort_indicator" property. Cool. --- gtk/gtkliststore.c | 2 + gtk/gtkrbtree.c | 37 +++++-- gtk/gtktreesortable.c | 9 ++ gtk/gtktreesortable.h | 1 + gtk/gtktreeview.c | 4 +- gtk/gtktreeviewcolumn.c | 287 ++++++++++++++++++++++++++++++++++-------------- gtk/gtktreeviewcolumn.h | 5 +- 7 files changed, 249 insertions(+), 96 deletions(-) (limited to 'gtk') diff --git a/gtk/gtkliststore.c b/gtk/gtkliststore.c index 6c06a36db..68cf78b9c 100644 --- a/gtk/gtkliststore.c +++ b/gtk/gtkliststore.c @@ -1635,6 +1635,8 @@ gtk_list_store_set_sort_column_id (GtkTreeSortable *sortable, if (list_store->sort_column_id >= 0) gtk_list_store_sort (list_store); + + gtk_tree_sortable_sort_column_changed (sortable); } static void diff --git a/gtk/gtkrbtree.c b/gtk/gtkrbtree.c index 878a577a6..bae1fc249 100644 --- a/gtk/gtkrbtree.c +++ b/gtk/gtkrbtree.c @@ -720,6 +720,7 @@ typedef struct _GtkRBReorder gint height; gint flags; gint order; + gint invert_order; } GtkRBReorder; static int @@ -729,6 +730,13 @@ gtk_rbtree_reorder_sort_func (gconstpointer a, return ((GtkRBReorder *) a)->order > ((GtkRBReorder *) b)->order; } +static int +gtk_rbtree_reorder_invert_func (gconstpointer a, + gconstpointer b) +{ + return ((GtkRBReorder *) a)->invert_order > ((GtkRBReorder *) b)->invert_order; +} + static void gtk_rbtree_reorder_fixup (GtkRBTree *tree, GtkRBNode *node) @@ -768,26 +776,35 @@ _gtk_rbtree_reorder (GtkRBTree *tree, GtkRBNode *node; gint i; - node = tree->root; - while (node && node->left != tree->nil) - node = node->left; /* Sort the trees values in the new tree. */ array = g_array_sized_new (FALSE, FALSE, sizeof (GtkRBReorder), length); for (i = 0; i < length; i++) { - g_assert (node != tree->nil); - reorder.children = node->children; - reorder.flags = GTK_RBNODE_NON_COLORS & node->flags; - reorder.height = GTK_RBNODE_GET_HEIGHT (node); reorder.order = new_order[i]; + reorder.invert_order = i; g_array_append_val (array, reorder); + } + + g_array_sort(array, gtk_rbtree_reorder_sort_func); + + /* rewind node*/ + node = tree->root; + while (node && node->left != tree->nil) + node = node->left; + + for (i = 0; i < length; i++) + { + g_assert (node != tree->nil); + g_array_index (array, GtkRBReorder, i).children = node->children; + g_array_index (array, GtkRBReorder, i).flags = GTK_RBNODE_NON_COLORS & node->flags; + g_array_index (array, GtkRBReorder, i).height = GTK_RBNODE_GET_HEIGHT (node); node = _gtk_rbtree_next (tree, node); } - g_array_sort (array, gtk_rbtree_reorder_sort_func); - + g_array_sort (array, gtk_rbtree_reorder_invert_func); + /* rewind node*/ node = tree->root; while (node && node->left != tree->nil) @@ -797,14 +814,12 @@ _gtk_rbtree_reorder (GtkRBTree *tree, for (i = 0; i < length; i++) { reorder = g_array_index (array, GtkRBReorder, i); - node->children = reorder.children; node->flags = GTK_RBNODE_GET_COLOR (node) | reorder.flags; /* We temporarily set the height to this. */ node->offset = reorder.height; node = _gtk_rbtree_next (tree, node); } - gtk_rbtree_reorder_fixup (tree, tree->root); } diff --git a/gtk/gtktreesortable.c b/gtk/gtktreesortable.c index b2833af60..2eda8870e 100644 --- a/gtk/gtktreesortable.c +++ b/gtk/gtktreesortable.c @@ -67,6 +67,15 @@ gtk_tree_sortable_base_init (gpointer g_class) } } +void +gtk_tree_sortable_sort_column_changed (GtkTreeSortable *sortable) +{ + g_return_if_fail (GTK_IS_TREE_SORTABLE (sortable)); + + g_signal_emit_by_name (G_OBJECT (sortable), + "sort_column_changed"); +} + gboolean gtk_tree_sortable_get_sort_column_id (GtkTreeSortable *sortable, gint *sort_column_id, diff --git a/gtk/gtktreesortable.h b/gtk/gtktreesortable.h index b417f9aba..6f8f4dcd7 100644 --- a/gtk/gtktreesortable.h +++ b/gtk/gtktreesortable.h @@ -72,6 +72,7 @@ struct _GtkTreeSortableIface GType gtk_tree_sortable_get_type (void) G_GNUC_CONST; +void gtk_tree_sortable_sort_column_changed (GtkTreeSortable *sortable); gboolean gtk_tree_sortable_get_sort_column_id (GtkTreeSortable *sortable, gint *sort_column_id, GtkTreeSortOrder *order); diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index ad9374947..3acfc3e2a 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -3950,6 +3950,9 @@ gtk_tree_view_set_model (GtkTreeView *tree_view, { g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); + if (model == tree_view->priv->model) + return; + if (model != NULL) g_object_ref (model); @@ -3994,7 +3997,6 @@ gtk_tree_view_set_model (GtkTreeView *tree_view, tree_view->priv->tree = NULL; if (GTK_WIDGET_REALIZED (tree_view)) _gtk_tree_view_update_size (tree_view); - return; } else if (GTK_WIDGET_REALIZED (tree_view)) { diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index e97a32e3d..2ceba9ff5 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -27,7 +27,7 @@ #include "gtkhbox.h" #include "gtkarrow.h" #include "gtkintl.h" - +#include enum { PROP_0, @@ -67,6 +67,9 @@ static void gtk_tree_view_column_get_property (GObject *object GValue *value, GParamSpec *pspec); static void gtk_tree_view_column_finalize (GObject *object); +static void gtk_tree_view_column_sort_column_changed (GtkTreeSortable *sortable, + GtkTreeViewColumn *column); +static void update_button_contents (GtkTreeViewColumn *tree_column); static GtkObjectClass *parent_class = NULL; @@ -244,6 +247,7 @@ gtk_tree_view_column_init (GtkTreeViewColumn *tree_column) tree_column->width = 1; tree_column->min_width = -1; tree_column->max_width = -1; + tree_column->model_changed_signal = 0; tree_column->cell = NULL; tree_column->attributes = NULL; tree_column->column_type = GTK_TREE_VIEW_COLUMN_AUTOSIZE; @@ -252,7 +256,8 @@ gtk_tree_view_column_init (GtkTreeViewColumn *tree_column) tree_column->dirty = TRUE; tree_column->sort_order = GTK_TREE_SORT_ASCENDING; tree_column->show_sort_indicator = FALSE; - tree_column->sort_signal = 0; + tree_column->sort_clicked_signal = 0; + tree_column->sort_column_changed_signal = 0; tree_column->sort_column_id = -1; } @@ -517,6 +522,7 @@ _gtk_tree_view_column_create_button (GtkTreeViewColumn *column) gtk_widget_show (hbox); gtk_widget_show (column->alignment); + update_button_contents (column); } void @@ -572,11 +578,70 @@ _gtk_tree_view_column_unrealize_button (GtkTreeViewColumn *column) column->window = NULL; } +static void +gtk_tree_view_column_model_changed (GtkTreeView *view, + guint n_pspecs, + GParamSpec **pspecs, + GtkTreeViewColumn *column) +{ + gint i; + + for (i = 0; i < n_pspecs; i++) + { + if (! strcmp (pspecs[i]->name, "model") && + (column->sort_clicked_signal)) + { + GtkTreeModel *model; + if (column->sort_column_changed_signal) + g_signal_handler_disconnect (G_OBJECT (column), + column->sort_column_changed_signal); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (column->tree_view)); + if (model) + column->sort_column_changed_signal = + g_signal_connectc (G_OBJECT (model), "sort_column_changed", + GTK_SIGNAL_FUNC (gtk_tree_view_column_sort_column_changed), + column, FALSE); + else + column->sort_column_changed_signal = 0; + } + } +} + void _gtk_tree_view_column_set_tree_view (GtkTreeViewColumn *column, GtkTreeView *tree_view) { column->tree_view = GTK_WIDGET (tree_view); + column->model_changed_signal = + gtk_signal_connect (GTK_OBJECT (tree_view), + "properties_changed", + GTK_SIGNAL_FUNC (gtk_tree_view_column_model_changed), + column); + + if (column->sort_clicked_signal) + { + GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (column->tree_view)); + + if (GTK_IS_TREE_SORTABLE (model)) + { + gint real_sort_column_id; + GtkTreeSortOrder real_order; + + if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model), + &real_sort_column_id, + &real_order) && + (real_sort_column_id == column->sort_column_id)) + { + gtk_tree_view_column_set_sort_indicator (column, TRUE); + gtk_tree_view_column_set_sort_order (column, real_order); + } + column->sort_column_changed_signal = + g_signal_connectc (G_OBJECT (model), "sort_column_changed", + GTK_SIGNAL_FUNC (gtk_tree_view_column_sort_column_changed), + column, FALSE); + + } + } } void @@ -586,7 +651,9 @@ _gtk_tree_view_column_unset_tree_view (GtkTreeViewColumn *column) { gtk_container_remove (GTK_CONTAINER (column->tree_view), column->button); } - + g_signal_handler_disconnect (G_OBJECT (column->tree_view), + column->model_changed_signal); + column->model_changed_signal = 0; column->tree_view = NULL; column->button = NULL; } @@ -1201,93 +1268,98 @@ gtk_tree_view_column_clicked (GtkTreeViewColumn *tree_column) static void update_button_contents (GtkTreeViewColumn *tree_column) { - if (tree_column->button) - { - GtkWidget *hbox = GTK_BIN (tree_column->button)->child; - GtkWidget *alignment = tree_column->alignment; - GtkWidget *arrow = tree_column->arrow; - GtkWidget *current_child = GTK_BIN (alignment)->child; + GtkWidget *hbox; + GtkWidget *alignment; + GtkWidget *arrow; + GtkWidget *current_child; - gtk_alignment_set (GTK_ALIGNMENT (alignment), tree_column->xalign, - 0.5, 0.0, 0.0); + if (! tree_column->button) + return; + + hbox = GTK_BIN (tree_column->button)->child; + alignment = tree_column->alignment; + arrow = tree_column->arrow; + current_child = GTK_BIN (alignment)->child; + + gtk_alignment_set (GTK_ALIGNMENT (alignment), tree_column->xalign, + 0.5, 0.0, 0.0); - if (tree_column->child) - { - if (current_child != tree_column->child) - { - gtk_container_remove (GTK_CONTAINER (alignment), - current_child); - - gtk_container_add (GTK_CONTAINER (alignment), - tree_column->child); - } - } - else - { - if (current_child == NULL) - { - current_child = gtk_label_new (NULL); + if (tree_column->child) + { + if (current_child != tree_column->child) + { + gtk_container_remove (GTK_CONTAINER (alignment), + current_child); + + gtk_container_add (GTK_CONTAINER (alignment), + tree_column->child); + } + } + else + { + if (current_child == NULL) + { + current_child = gtk_label_new (NULL); - gtk_widget_show (current_child); + gtk_widget_show (current_child); - gtk_container_add (GTK_CONTAINER (alignment), - current_child); - } - - g_return_if_fail (GTK_IS_LABEL (current_child)); - - if (tree_column->title) - gtk_label_set_text (GTK_LABEL (current_child), - tree_column->title); - else - gtk_label_set_text (GTK_LABEL (current_child), - ""); - } + gtk_container_add (GTK_CONTAINER (alignment), + current_child); + } - switch (tree_column->sort_order) - { - case GTK_TREE_SORT_ASCENDING: - gtk_arrow_set (GTK_ARROW (arrow), - GTK_ARROW_DOWN, - GTK_SHADOW_IN); - break; - - case GTK_TREE_SORT_DESCENDING: - gtk_arrow_set (GTK_ARROW (arrow), - GTK_ARROW_UP, - GTK_SHADOW_IN); - break; + g_return_if_fail (GTK_IS_LABEL (current_child)); + + if (tree_column->title) + gtk_label_set_text (GTK_LABEL (current_child), + tree_column->title); + else + gtk_label_set_text (GTK_LABEL (current_child), + ""); + } + + switch (tree_column->sort_order) + { + case GTK_TREE_SORT_ASCENDING: + gtk_arrow_set (GTK_ARROW (arrow), + GTK_ARROW_DOWN, + GTK_SHADOW_IN); + break; + + case GTK_TREE_SORT_DESCENDING: + gtk_arrow_set (GTK_ARROW (arrow), + GTK_ARROW_UP, + GTK_SHADOW_IN); + break; - default: - g_warning (G_STRLOC": bad sort order"); - break; - } + default: + g_warning (G_STRLOC": bad sort order"); + break; + } - /* Put arrow on the right if the text is left-or-center justified, + /* Put arrow on the right if the text is left-or-center justified, * and on the left otherwise; do this by packing boxes, so flipping * text direction will reverse things */ - gtk_widget_ref (arrow); - gtk_container_remove (GTK_CONTAINER (hbox), arrow); + gtk_widget_ref (arrow); + gtk_container_remove (GTK_CONTAINER (hbox), arrow); - if (tree_column->xalign <= 0.5) - { - gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0); - } - else - { - gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0); - /* move it to the front */ - gtk_box_reorder_child (GTK_BOX (hbox), arrow, 0); - } + if (tree_column->xalign <= 0.5) + { + gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0); + } + else + { + gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0); + /* move it to the front */ + gtk_box_reorder_child (GTK_BOX (hbox), arrow, 0); + } - gtk_widget_unref (arrow); + gtk_widget_unref (arrow); - if (tree_column->show_sort_indicator) - gtk_widget_show (arrow); - else - gtk_widget_hide (arrow); - } + if (tree_column->show_sort_indicator) + gtk_widget_show (arrow); + else + gtk_widget_hide (arrow); } /** @@ -1480,6 +1552,28 @@ gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column) return tree_column->xalign; } +static void +gtk_tree_view_column_sort_column_changed (GtkTreeSortable *sortable, + GtkTreeViewColumn *column) +{ + gint sort_column_id; + GtkTreeSortOrder order; + + if (gtk_tree_sortable_get_sort_column_id (sortable, + &sort_column_id, + &order)) + { + if (sort_column_id == column->sort_column_id) + { + gtk_tree_view_column_set_sort_indicator (column, TRUE); + gtk_tree_view_column_set_sort_order (column, order); + } + else + { + gtk_tree_view_column_set_sort_indicator (column, FALSE); + } + } +} static void sort_clicked_func (GtkTreeViewColumn *tree_column, @@ -1538,17 +1632,46 @@ gtk_tree_view_column_set_sort_column_id (GtkTreeViewColumn *tree_column, if (sort_column_id == -1) { - if (tree_column->sort_signal) - g_signal_handler_disconnect (G_OBJECT (tree_column), tree_column->sort_signal); + if (tree_column->sort_clicked_signal) + g_signal_handler_disconnect (G_OBJECT (tree_column), tree_column->sort_clicked_signal); return; } - if (! tree_column->sort_signal) - tree_column->sort_signal = g_signal_connectc (G_OBJECT (tree_column), + if (! tree_column->sort_clicked_signal) + tree_column->sort_clicked_signal = g_signal_connectc (G_OBJECT (tree_column), "clicked", G_CALLBACK (sort_clicked_func), NULL, FALSE); tree_column->sort_column_id = sort_column_id; + + if (tree_column->tree_view) + { + GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_column->tree_view)); + + if (GTK_IS_TREE_SORTABLE (model)) + { + gint real_sort_column_id; + GtkTreeSortOrder real_order; + + if (tree_column->sort_column_changed_signal == 0) + tree_column->sort_column_changed_signal = + g_signal_connectc (G_OBJECT (model), "sort_column_changed", + GTK_SIGNAL_FUNC (gtk_tree_view_column_sort_column_changed), + tree_column, FALSE); + + if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model), + &real_sort_column_id, + &real_order) && + (real_sort_column_id == sort_column_id)) + { + gtk_tree_view_column_set_sort_indicator (tree_column, TRUE); + gtk_tree_view_column_set_sort_order (tree_column, real_order); + + return; + } + } + } + gtk_tree_view_column_set_sort_indicator (tree_column, FALSE); gtk_tree_view_column_set_sort_order (tree_column, GTK_TREE_SORT_ASCENDING); } @@ -1577,7 +1700,7 @@ gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn *tree_column, tree_column->show_sort_indicator = setting; update_button_contents (tree_column); - + g_object_notify (G_OBJECT (tree_column), "sort_indicator"); if (GTK_WIDGET_REALIZED (tree_column->tree_view)) gtk_widget_queue_draw (tree_column->tree_view); diff --git a/gtk/gtktreeviewcolumn.h b/gtk/gtktreeviewcolumn.h index 1eaaf2d03..79987aabf 100644 --- a/gtk/gtktreeviewcolumn.h +++ b/gtk/gtktreeviewcolumn.h @@ -63,6 +63,7 @@ struct _GtkTreeViewColumn GtkWidget *alignment; GdkWindow *window; gfloat xalign; + guint model_changed_signal; gint width; gint min_width; @@ -78,11 +79,11 @@ struct _GtkTreeViewColumn GtkTreeViewColumnSizing column_type; /* Sorting */ - guint sort_signal; + guint sort_clicked_signal; + guint sort_column_changed_signal; gint sort_column_id; GtkTreeSortOrder sort_order; - guint visible : 1; guint button_active : 1; guint dirty : 1; -- cgit v1.2.1