[gnome-keyring: 1/12] gcr: Add GtkTreeSortable interface to GcrCollectionModel
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring: 1/12] gcr: Add GtkTreeSortable interface to GcrCollectionModel
- Date: Mon, 19 Sep 2011 07:38:41 +0000 (UTC)
commit 76561373624e3ab976ce8b7251823e810409b6d4
Author: Stef Walter <stefw collabora co uk>
Date: Fri Sep 2 16:50:31 2011 +0200
gcr: Add GtkTreeSortable interface to GcrCollectionModel
* Can now sort based on values, which simplifies callers of
GcrCollectionModel.
* Needed for use in seahorse.
gcr/gcr-collection-model.c | 482 +++++++++++++++++++++++++++++++++++++---
gcr/gcr-collection-model.h | 7 +
gcr/gcr-tree-selector.c | 103 +---------
gcr/tests/frob-tree-selector.c | 4 +-
4 files changed, 460 insertions(+), 136 deletions(-)
---
diff --git a/gcr/gcr-collection-model.c b/gcr/gcr-collection-model.c
index 1e99b58..2ffb89d 100644
--- a/gcr/gcr-collection-model.c
+++ b/gcr/gcr-collection-model.c
@@ -75,34 +75,251 @@ enum {
PROP_COLUMNS
};
+typedef struct {
+ GtkTreeIterCompareFunc sort_func;
+ gpointer user_data;
+ GDestroyNotify destroy_func;
+} GcrCollectionSortClosure;
+
+typedef struct _GcrCollectionColumn {
+ gchar *property;
+ GType *type;
+ GtkTreeIterCompareFunc sort_func;
+ gpointer sort_data;
+ GDestroyNotify sort_destroy;
+} GcrCollectionColumn;
+
struct _GcrCollectionModelPrivate {
GcrCollection *collection;
GHashTable *selected;
- GSequence *objects;
+ GSequence *object_sequence;
+ GHashTable *object_to_sequence;
const GcrColumn *columns;
guint n_columns;
+
+ /* Sort information */
+ gint sort_column_id;
+ GtkSortType sort_order_type;
+ GcrCollectionSortClosure *column_sort_closures;
+ GcrCollectionSortClosure default_sort_closure;
+
+ /* Sequence ordering information */
+ GCompareDataFunc order_current;
+ gpointer order_argument;
};
/* Forward declarations */
static void gcr_collection_model_tree_model_init (GtkTreeModelIface *iface);
+static void gcr_collection_model_tree_sortable_init (GtkTreeSortableIface *iface);
-G_DEFINE_TYPE_WITH_CODE (GcrCollectionModel, gcr_collection_model, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, gcr_collection_model_tree_model_init);
+G_DEFINE_TYPE_EXTENDED (GcrCollectionModel, gcr_collection_model, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, gcr_collection_model_tree_model_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE, gcr_collection_model_tree_sortable_init)
);
-#define UNUSED_VALUE GINT_TO_POINTER (1)
+typedef gint (*CompareValueFunc) (const GValue *va,
+ const GValue *vb);
-static GHashTable*
-selected_hash_table_new (void)
+static gint
+compare_int_value (const GValue *va,
+ const GValue *vb)
{
- return g_hash_table_new (g_direct_hash, g_direct_equal);
+ gint a = g_value_get_int (va);
+ gint b = g_value_get_int (vb);
+ if (a > b) return 1;
+ else if (a < b) return -1;
+ return 0;
+}
+
+static gint
+compare_uint_value (const GValue *va,
+ const GValue *vb)
+{
+ guint a = g_value_get_uint (va);
+ guint b = g_value_get_uint (vb);
+ if (a > b) return 1;
+ else if (a < b) return -1;
+ return 0;
+}
+
+static gint
+compare_long_value (const GValue *va,
+ const GValue *vb)
+{
+ glong a = g_value_get_long (va);
+ glong b = g_value_get_long (vb);
+ if (a > b) return 1;
+ else if (a < b) return -1;
+ return 0;
+}
+
+static gint
+compare_ulong_value (const GValue *va,
+ const GValue *vb)
+{
+ gulong a = g_value_get_ulong (va);
+ gulong b = g_value_get_ulong (vb);
+ if (a > b) return 1;
+ else if (a < b) return -1;
+ return 0;
+}
+
+static gint
+compare_string_value (const GValue *va,
+ const GValue *vb)
+{
+ const gchar *a = g_value_get_string (va);
+ const gchar *b = g_value_get_string (vb);
+ gchar *case_a;
+ gchar *case_b;
+ gboolean ret;
+
+ if (a == b)
+ return 0;
+ else if (!a)
+ return -1;
+ else if (!b)
+ return 1;
+
+ case_a = g_utf8_casefold (a, -1);
+ case_b = g_utf8_casefold (b, -1);
+ ret = g_utf8_collate (case_a, case_b);
+ g_free (case_a);
+ g_free (case_b);
+
+ return ret;
+}
+
+static gint
+compare_date_value (const GValue *va,
+ const GValue *vb)
+{
+ GDate *a = g_value_get_boxed (va);
+ GDate *b = g_value_get_boxed (vb);
+
+ if (a == b)
+ return 0;
+ else if (!a)
+ return -1;
+ else if (!b)
+ return 1;
+ else
+ return g_date_compare (a, b);
+}
+
+static CompareValueFunc
+lookup_compare_func (GType type)
+{
+ switch (type) {
+ case G_TYPE_INT:
+ return compare_int_value;
+ case G_TYPE_UINT:
+ return compare_uint_value;
+ case G_TYPE_LONG:
+ return compare_long_value;
+ case G_TYPE_ULONG:
+ return compare_ulong_value;
+ case G_TYPE_STRING:
+ return compare_string_value;
+ }
+
+ if (type == G_TYPE_DATE)
+ return compare_date_value;
+
+ return NULL;
}
static gint
-on_sequence_compare (gconstpointer a, gconstpointer b, gpointer user_data)
+order_sequence_by_closure (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
{
- return (GObject*)a - (GObject*)b;
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (user_data);
+ GcrCollectionSortClosure *closure = self->pv->order_argument;
+ GtkTreeIter iter_a;
+ GtkTreeIter iter_b;
+
+ g_assert (closure);
+ g_assert (closure->sort_func);
+
+ if (!gcr_collection_model_iter_for_object (self, (GObject *)a, &iter_a))
+ g_return_val_if_reached (0);
+ if (!gcr_collection_model_iter_for_object (self, (GObject *)b, &iter_b))
+ g_return_val_if_reached (0);
+
+ return (closure->sort_func) (GTK_TREE_MODEL (self),
+ &iter_a, &iter_b, closure->user_data);
+}
+
+static gint
+order_sequence_by_closure_reverse (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ return 0 - order_sequence_by_closure (a, b, user_data);
+}
+
+static gint
+order_sequence_as_unsorted (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ return GPOINTER_TO_INT (a) - GPOINTER_TO_INT (b);
+}
+
+static gint
+order_sequence_as_unsorted_reverse (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ return GPOINTER_TO_INT (b) - GPOINTER_TO_INT (a);
+}
+
+static gint
+order_sequence_by_property (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (user_data);
+ const GcrColumn *column = self->pv->order_argument;
+ GValue value_a = { 0, };
+ GValue value_b = { 0, };
+ CompareValueFunc compare;
+ gint ret;
+
+ g_assert (column);
+
+ /* Sort according to property values */
+ column = &self->pv->columns[self->pv->sort_column_id];
+ g_value_init (&value_a, column->property_type);
+ g_object_get_property ((GObject *)a, column->property_name, &value_a);
+ g_value_init (&value_b, column->property_type);
+ g_object_get_property ((GObject *)b, column->property_name, &value_b);
+
+ compare = lookup_compare_func (column->property_type);
+ g_assert (compare != NULL);
+
+ ret = (compare) (&value_a, &value_b);
+
+ g_value_unset (&value_a);
+ g_value_unset (&value_b);
+
+ return ret;
+}
+
+static gint
+order_sequence_by_property_reverse (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ return 0 - order_sequence_by_property (a, b, user_data);
+}
+
+static GHashTable*
+selected_hash_table_new (void)
+{
+ return g_hash_table_new (g_direct_hash, g_direct_equal);
}
static gint
@@ -116,10 +333,10 @@ index_for_iter (GcrCollectionModel *self, const GtkTreeIter *iter)
seq = iter->user_data2;
g_return_val_if_fail (g_sequence_iter_get_sequence (seq) ==
- self->pv->objects, -1);
+ self->pv->object_sequence, -1);
index = g_sequence_iter_get_position (seq);
- g_assert (index >= 0 && index < g_sequence_get_length (self->pv->objects));
+ g_assert (index >= 0 && index < g_sequence_get_length (self->pv->object_sequence));
return index;
}
@@ -143,10 +360,10 @@ iter_for_index (GcrCollectionModel *self, gint index, GtkTreeIter *iter)
{
GSequenceIter *seq;
- if (index < 0 || index >= g_sequence_get_length (self->pv->objects))
+ if (index < 0 || index >= g_sequence_get_length (self->pv->object_sequence))
return FALSE;
- seq = g_sequence_get_iter_at_pos (self->pv->objects, index);
+ seq = g_sequence_get_iter_at_pos (self->pv->object_sequence, index);
return iter_for_seq (self, seq, iter);
}
@@ -155,8 +372,7 @@ index_for_object (GcrCollectionModel *self, GObject *object)
{
GSequenceIter *seq;
- seq = g_sequence_lookup (self->pv->objects, object,
- on_sequence_compare, NULL);
+ seq = g_hash_table_lookup (self->pv->object_to_sequence, object);
if (seq == NULL)
return -1;
@@ -211,9 +427,11 @@ on_collection_added (GcrCollection *collection, GObject *object, GcrCollectionMo
g_assert (GCR_IS_COLLECTION_MODEL (self));
g_assert (G_IS_OBJECT (object));
+ g_assert (self->pv->order_current);
- seq = g_sequence_insert_sorted (self->pv->objects, object,
- on_sequence_compare, self);
+ seq = g_sequence_insert_sorted (self->pv->object_sequence, object,
+ self->pv->order_current, self);
+ g_hash_table_insert (self->pv->object_to_sequence, object, seq);
g_object_weak_ref (G_OBJECT (object), (GWeakNotify)on_object_gone, self);
g_signal_connect (object, "notify", G_CALLBACK (on_object_notify), self);
@@ -244,7 +462,7 @@ on_collection_removed (GcrCollection *collection, GObject *object,
g_return_if_fail (GCR_COLLECTION_MODEL (self));
g_return_if_fail (G_IS_OBJECT (object));
- seq = g_sequence_lookup (self->pv->objects, object, on_sequence_compare, NULL);
+ seq = g_hash_table_lookup (self->pv->object_to_sequence, object);
g_return_if_fail (seq != NULL);
path = gtk_tree_path_new_from_indices (g_sequence_iter_get_position (seq), -1);
@@ -252,6 +470,7 @@ on_collection_removed (GcrCollection *collection, GObject *object,
disconnect_object (self, object);
g_hash_table_remove (self->pv->selected, object);
+ g_hash_table_remove (self->pv->object_to_sequence, object);
g_sequence_remove (seq);
/* Fire signal for this removed row */
@@ -412,7 +631,7 @@ gcr_collection_model_real_iter_has_child (GtkTreeModel *model, GtkTreeIter *iter
{
GcrCollectionModel *self = GCR_COLLECTION_MODEL (model);
if (iter == NULL)
- return !g_sequence_iter_is_end (g_sequence_get_begin_iter (self->pv->objects));
+ return !g_sequence_iter_is_end (g_sequence_get_begin_iter (self->pv->object_sequence));
return FALSE;
}
@@ -421,7 +640,7 @@ gcr_collection_model_real_iter_n_children (GtkTreeModel *model, GtkTreeIter *ite
{
GcrCollectionModel *self = GCR_COLLECTION_MODEL (model);
if (iter == NULL)
- return g_sequence_get_length (self->pv->objects);
+ return g_sequence_get_length (self->pv->object_sequence);
return 0;
}
@@ -473,14 +692,205 @@ gcr_collection_model_tree_model_init (GtkTreeModelIface *iface)
}
static void
+collection_resort (GcrCollectionModel *self)
+{
+ GPtrArray *previous;
+ GSequenceIter *seq;
+ gint *new_order;
+ GtkTreePath *path;
+ gint index;
+ gint i;
+
+ /* Make note of how things stand */
+ previous = g_ptr_array_new ();
+ for (seq = g_sequence_get_begin_iter (self->pv->object_sequence);
+ !g_sequence_iter_is_end (seq); seq = g_sequence_iter_next (seq))
+ g_ptr_array_add (previous, g_sequence_get (seq));
+
+ /* Actually perform the sort */
+ g_sequence_sort (self->pv->object_sequence, self->pv->order_current, self);
+
+ /* Now go through and map out how things changed */
+ new_order = g_new0 (gint, previous->len);
+ for (i = 0; i < previous->len; i++) {
+ seq = g_hash_table_lookup (self->pv->object_to_sequence,
+ previous->pdata[i]);
+ index = g_sequence_iter_get_position (seq);
+ g_assert (index >= 0 && index < previous->len);
+ new_order[index] = i;
+ }
+
+ g_ptr_array_free (previous, TRUE);
+
+ path = gtk_tree_path_new ();
+ gtk_tree_model_rows_reordered (GTK_TREE_MODEL (self), path, NULL, new_order);
+ g_free (new_order);
+}
+
+static gboolean
+gcr_collection_model_get_sort_column_id (GtkTreeSortable *sortable,
+ gint *sort_column_id,
+ GtkSortType *order)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (sortable);
+
+ if (order)
+ *order = self->pv->sort_order_type;
+ if (sort_column_id)
+ *sort_column_id = self->pv->sort_column_id;
+ return (self->pv->sort_column_id != GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID &&
+ self->pv->sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID);
+}
+
+static void
+gcr_collection_model_set_sort_column_id (GtkTreeSortable *sortable,
+ gint sort_column_id,
+ GtkSortType order)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (sortable);
+ GCompareDataFunc func;
+ gpointer argument;
+ const GcrColumn *column;
+ gboolean reverse;
+
+ reverse = (order == GTK_SORT_DESCENDING);
+
+ if (sort_column_id == GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID) {
+ func = reverse ? order_sequence_as_unsorted_reverse : order_sequence_as_unsorted;
+ argument = NULL;
+
+ } else if (sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID) {
+ func = reverse ? order_sequence_by_closure_reverse : order_sequence_by_closure;
+ argument = &self->pv->default_sort_closure;
+
+ } else if (sort_column_id >= 0 && sort_column_id < self->pv->n_columns) {
+ if (self->pv->column_sort_closures[sort_column_id].sort_func) {
+ func = reverse ? order_sequence_by_closure_reverse : order_sequence_by_closure;
+ argument = &self->pv->column_sort_closures[sort_column_id];
+ } else {
+ column = &self->pv->columns[sort_column_id];
+ if (!(column->flags & GCR_COLUMN_SORTABLE))
+ return;
+ if (!lookup_compare_func (column->property_type)) {
+ g_warning ("no sort implementation defined for type '%s' on column '%s'",
+ g_type_name (column->property_type), column->property_name);
+ return;
+ }
+
+ func = reverse ? order_sequence_by_property_reverse : order_sequence_by_property;
+ argument = (gpointer)column;
+ }
+ } else {
+ g_warning ("invalid sort_column_id passed to gtk_tree_sortable_set_sort_column_id(): %d",
+ sort_column_id);
+ return;
+ }
+
+ if (sort_column_id != self->pv->sort_column_id ||
+ order != self->pv->sort_order_type) {
+ self->pv->sort_column_id = sort_column_id;
+ self->pv->sort_order_type = order;
+ gtk_tree_sortable_sort_column_changed (sortable);
+ }
+
+ if (func != self->pv->order_current ||
+ argument != self->pv->order_argument) {
+ self->pv->order_current = func;
+ self->pv->order_argument = (gpointer)argument;
+ collection_resort (self);
+ }
+}
+
+static void
+clear_sort_closure (GcrCollectionSortClosure *closure)
+{
+ if (closure->destroy_func)
+ (closure->destroy_func) (closure->user_data);
+ closure->sort_func = NULL;
+ closure->destroy_func = NULL;
+ closure->user_data = NULL;
+}
+
+static void
+set_sort_closure (GcrCollectionSortClosure *closure,
+ GtkTreeIterCompareFunc func,
+ gpointer data,
+ GDestroyNotify destroy)
+{
+ clear_sort_closure (closure);
+ closure->sort_func = func;
+ closure->user_data = data;
+ closure->destroy_func = destroy;
+}
+
+static void
+gcr_collection_model_set_sort_func (GtkTreeSortable *sortable,
+ gint sort_column_id,
+ GtkTreeIterCompareFunc func,
+ gpointer data,
+ GDestroyNotify destroy)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (sortable);
+
+ g_return_if_fail (sort_column_id >= 0 && sort_column_id < self->pv->n_columns);
+
+ set_sort_closure (&self->pv->column_sort_closures[sort_column_id],
+ func, data, destroy);
+
+ /* Resorts if necessary */
+ if (self->pv->sort_column_id == sort_column_id) {
+ gcr_collection_model_set_sort_column_id (sortable,
+ self->pv->sort_column_id,
+ self->pv->sort_order_type);
+ }
+}
+
+static void
+gcr_collection_model_set_default_sort_func (GtkTreeSortable *sortable,
+ GtkTreeIterCompareFunc func,
+ gpointer data, GDestroyNotify destroy)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (sortable);
+
+ set_sort_closure (&self->pv->default_sort_closure,
+ func, data, destroy);
+
+ /* Resorts if necessary */
+ if (self->pv->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID) {
+ gcr_collection_model_set_sort_column_id (sortable,
+ self->pv->sort_column_id,
+ self->pv->sort_order_type);
+ }
+}
+
+static gboolean
+gcr_collection_model_has_default_sort_func (GtkTreeSortable *sortable)
+{
+ GcrCollectionModel *self = GCR_COLLECTION_MODEL (sortable);
+
+ return (self->pv->default_sort_closure.sort_func != NULL);
+}
+
+static void
+gcr_collection_model_tree_sortable_init (GtkTreeSortableIface *iface)
+{
+ iface->get_sort_column_id = gcr_collection_model_get_sort_column_id;
+ iface->set_sort_column_id = gcr_collection_model_set_sort_column_id;
+ iface->set_sort_func = gcr_collection_model_set_sort_func;
+ iface->set_default_sort_func = gcr_collection_model_set_default_sort_func;
+ iface->has_default_sort_func = gcr_collection_model_has_default_sort_func;
+}
+
+static void
gcr_collection_model_init (GcrCollectionModel *self)
{
self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_COLLECTION_MODEL, GcrCollectionModelPrivate);
- self->pv->objects = g_sequence_new (NULL);
- self->pv->selected = NULL;
- self->pv->columns = NULL;
- self->pv->n_columns = 0;
+ self->pv->object_sequence = g_sequence_new (NULL);
+ self->pv->object_to_sequence = g_hash_table_new (g_direct_hash, g_direct_equal);
+ self->pv->sort_column_id = GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID;
+ self->pv->sort_order_type = GTK_SORT_ASCENDING;
+ self->pv->order_current = order_sequence_as_unsorted;
}
static void
@@ -542,13 +952,15 @@ gcr_collection_model_dispose (GObject *object)
GSequenceIter *next;
/* Disconnect from all rows */
- for (seq = g_sequence_get_begin_iter (self->pv->objects);
+ for (seq = g_sequence_get_begin_iter (self->pv->object_sequence);
!g_sequence_iter_is_end (seq); seq = next) {
next = g_sequence_iter_next (seq);
disconnect_object (self, g_sequence_get (seq));
g_sequence_remove (seq);
}
+ g_hash_table_remove_all (self->pv->object_to_sequence);
+
/* Disconnect from the collection */
if (self->pv->collection) {
g_signal_handlers_disconnect_by_func (self->pv->collection, on_collection_added, self);
@@ -567,19 +979,24 @@ static void
gcr_collection_model_finalize (GObject *object)
{
GcrCollectionModel *self = GCR_COLLECTION_MODEL (object);
+ guint i;
g_assert (!self->pv->collection);
- g_assert (self->pv->objects);
- g_assert (g_sequence_get_length (self->pv->objects) == 0);
- g_sequence_free (self->pv->objects);
- self->pv->objects = NULL;
+ g_assert (g_sequence_get_length (self->pv->object_sequence) == 0);
+ g_sequence_free (self->pv->object_sequence);
+ g_assert (g_hash_table_size (self->pv->object_to_sequence) == 0);
+ g_hash_table_destroy (self->pv->object_to_sequence);
if (self->pv->selected)
g_hash_table_destroy (self->pv->selected);
self->pv->selected = NULL;
self->pv->columns = NULL;
+ for (i = 0; i < self->pv->n_columns; i++)
+ clear_sort_closure (&self->pv->column_sort_closures[i]);
+ g_free (self->pv->column_sort_closures);
+ clear_sort_closure (&self->pv->default_sort_closure);
G_OBJECT_CLASS (gcr_collection_model_parent_class)->finalize (object);
}
@@ -698,6 +1115,7 @@ gcr_collection_model_set_columns (GcrCollectionModel *self, const GcrColumn *col
/* We expect the columns to stay around */
self->pv->columns = columns;
self->pv->n_columns = n_columns;
+ self->pv->column_sort_closures = g_new0 (GcrCollectionSortClosure, self->pv->n_columns);
}
/**
@@ -788,7 +1206,7 @@ gcr_collection_model_toggle_selected (GcrCollectionModel *self, GtkTreeIter *ite
if (g_hash_table_lookup (self->pv->selected, object))
g_hash_table_remove (self->pv->selected, object);
else
- g_hash_table_insert (self->pv->selected, object, UNUSED_VALUE);
+ g_hash_table_insert (self->pv->selected, object, object);
}
/**
@@ -814,7 +1232,7 @@ gcr_collection_model_change_selected (GcrCollectionModel *self, GtkTreeIter *ite
self->pv->selected = g_hash_table_new (g_direct_hash, g_direct_equal);
if (selected)
- g_hash_table_insert (self->pv->selected, object, UNUSED_VALUE);
+ g_hash_table_insert (self->pv->selected, object, object);
else
g_hash_table_remove (self->pv->selected, object);
@@ -888,7 +1306,7 @@ gcr_collection_model_set_selected_objects (GcrCollectionModel *self, GList *sele
}
/* Note that we've seen this one */
- g_hash_table_insert (newly_selected, l->data, UNUSED_VALUE);
+ g_hash_table_insert (newly_selected, l->data, l->data);
}
/* Unselect all the objects which aren't supposed to be selected */
diff --git a/gcr/gcr-collection-model.h b/gcr/gcr-collection-model.h
index c8a1775..4cfc293 100644
--- a/gcr/gcr-collection-model.h
+++ b/gcr/gcr-collection-model.h
@@ -60,6 +60,13 @@ GcrCollectionModel* gcr_collection_model_new_full (GcrCollection *c
void gcr_collection_model_set_columns (GcrCollectionModel *self,
const GcrColumn *columns);
+void gcr_collection_model_get_child_property (GcrCollectionModel *self,
+ const gchar *property_name);
+
+void gcr_collection_model_set_child_property (GcrCollectionModel *self,
+ const gchar *property_name,
+ GValueTransform transformer);
+
GObject* gcr_collection_model_object_for_iter (GcrCollectionModel *self,
const GtkTreeIter *iter);
diff --git a/gcr/gcr-tree-selector.c b/gcr/gcr-tree-selector.c
index 736f840..0bcb8ec 100644
--- a/gcr/gcr-tree-selector.c
+++ b/gcr/gcr-tree-selector.c
@@ -60,7 +60,6 @@ enum {
struct _GcrTreeSelectorPrivate {
GcrCollection *collection;
const GcrColumn *columns;
- GtkTreeModel *sort;
GcrCollectionModel *model;
};
@@ -81,88 +80,6 @@ on_check_column_toggled (GtkCellRendererToggle *cell, gchar *path, GcrCollection
gcr_collection_model_toggle_selected (model, &iter);
}
-typedef gint (*SortFunc) (GValue *, GValue *);
-
-static gint
-sort_string (GValue *val_a, GValue *val_b)
-{
- const gchar *str_a = g_value_get_string (val_a);
- const gchar *str_b = g_value_get_string (val_b);
-
- if (str_a == str_b)
- return 0;
- else if (!str_a)
- return -1;
- else if (!str_b)
- return 1;
- else
- return g_utf8_collate (str_a, str_b);
-}
-
-static gint
-sort_date (GValue *val_a, GValue *val_b)
-{
- GDate *date_a = g_value_get_boxed (val_a);
- GDate *date_b = g_value_get_boxed (val_b);
-
- if (date_a == date_b)
- return 0;
- else if (!date_a)
- return -1;
- else if (!date_b)
- return 1;
- else
- return g_date_compare (date_a, date_b);
-}
-
-static inline SortFunc
-sort_implementation_for_type (GType type)
-{
- if (type == G_TYPE_STRING)
- return sort_string;
- else if (type == G_TYPE_DATE)
- return sort_date;
- else
- return NULL;
-}
-
-static gint
-on_sort_column (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b,
- gpointer user_data)
-{
- GcrColumn *column = user_data;
- SortFunc func;
- GObject *object_a;
- GObject *object_b;
- GValue val_a;
- GValue val_b;
- gint ret;
-
- object_a = gcr_collection_model_object_for_iter (GCR_COLLECTION_MODEL (model), a);
- g_return_val_if_fail (G_IS_OBJECT (object_a), 0);
- object_b = gcr_collection_model_object_for_iter (GCR_COLLECTION_MODEL (model), b);
- g_return_val_if_fail (G_IS_OBJECT (object_b), 0);
-
- memset (&val_a, 0, sizeof (val_a));
- memset (&val_b, 0, sizeof (val_b));
-
- g_value_init (&val_a, column->property_type);
- g_value_init (&val_b, column->property_type);
-
- g_object_get_property (object_a, column->property_name, &val_a);
- g_object_get_property (object_b, column->property_name, &val_b);
-
- func = sort_implementation_for_type (column->property_type);
- g_return_val_if_fail (func, 0);
-
- ret = (func) (&val_a, &val_b);
-
- g_value_unset (&val_a);
- g_value_unset (&val_b);
-
- return ret;
-}
-
static void
add_string_column (GcrTreeSelector *self, const GcrColumn *column, gint column_id)
{
@@ -226,7 +143,6 @@ gcr_tree_selector_constructor (GType type, guint n_props, GObjectConstructParam
{
GcrTreeSelector *self = GCR_TREE_SELECTOR (G_OBJECT_CLASS (gcr_tree_selector_parent_class)->constructor(type, n_props, props));
const GcrColumn *column;
- GtkTreeSortable *sortable;
guint i;
g_return_val_if_fail (self, NULL);
@@ -235,10 +151,7 @@ gcr_tree_selector_constructor (GType type, guint n_props, GObjectConstructParam
self->pv->model = gcr_collection_model_new_full (self->pv->collection,
self->pv->columns);
- self->pv->sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (self->pv->model));
- sortable = GTK_TREE_SORTABLE (self->pv->sort);
-
- gtk_tree_view_set_model (GTK_TREE_VIEW (self), GTK_TREE_MODEL (self->pv->sort));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (self), GTK_TREE_MODEL (self->pv->model));
/* First add the check mark column */
add_check_column (self, gcr_collection_model_column_for_selected (self->pv->model));
@@ -254,16 +167,6 @@ gcr_tree_selector_constructor (GType type, guint n_props, GObjectConstructParam
else
g_warning ("skipping unsupported column '%s' of type: %s",
column->property_name, g_type_name (column->column_type));
-
- /* Setup the column itself */
- if (column->flags & GCR_COLUMN_SORTABLE) {
- if (sort_implementation_for_type (column->property_type))
- gtk_tree_sortable_set_sort_func (sortable, i, on_sort_column,
- (gpointer)column, NULL);
- else
- g_warning ("no sort implementation defined for type '%s' on column '%s'",
- g_type_name (column->property_type), column->property_name);
- }
}
return G_OBJECT (self);
@@ -288,10 +191,6 @@ gcr_tree_selector_dispose (GObject *obj)
g_object_unref (self->pv->collection);
self->pv->collection = NULL;
- if (self->pv->sort)
- g_object_unref (self->pv->sort);
- self->pv->sort = NULL;
-
G_OBJECT_CLASS (gcr_tree_selector_parent_class)->dispose (obj);
}
diff --git a/gcr/tests/frob-tree-selector.c b/gcr/tests/frob-tree-selector.c
index 73765ce..d756f3d 100644
--- a/gcr/tests/frob-tree-selector.c
+++ b/gcr/tests/frob-tree-selector.c
@@ -66,7 +66,7 @@ main (int argc, char *argv[])
gtk_widget_show_all (scroll);
gtk_widget_show (GTK_WIDGET (selector));
- gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (dialog)), GTK_WIDGET (scroll));
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (dialog)), GTK_WIDGET (scroll), TRUE, TRUE, 0);
gtk_window_set_default_size (GTK_WINDOW (dialog), 550, 400);
gtk_container_set_border_width (GTK_CONTAINER (dialog), 20);
@@ -75,7 +75,7 @@ main (int argc, char *argv[])
g_signal_connect (parser, "parsed", G_CALLBACK (on_parser_parsed), collection);
if (argc == 1) {
- add_to_selector (parser, "files/ca-certificates.crt");
+ add_to_selector (parser, SRCDIR "/files/ca-certificates.crt");
} else {
for (i = 1; i < argc; ++i)
add_to_selector (parser, argv[i]);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]