forked from AuroraMiddleware/gtk
stringsorter: Implement GtkSortKeys
This commit is contained in:
parent
814c88fbc1
commit
0970077af9
@ -22,6 +22,7 @@
|
||||
#include "gtkstringsorter.h"
|
||||
|
||||
#include "gtkintl.h"
|
||||
#include "gtksorterprivate.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
|
||||
/**
|
||||
@ -58,70 +59,58 @@ G_DEFINE_TYPE (GtkStringSorter, gtk_string_sorter, GTK_TYPE_SORTER)
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
|
||||
|
||||
static char *
|
||||
gtk_string_sorter_get_key (GtkExpression *expression,
|
||||
gboolean ignore_case,
|
||||
gpointer item1)
|
||||
{
|
||||
GValue value = G_VALUE_INIT;
|
||||
char *s;
|
||||
|
||||
if (expression == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!gtk_expression_evaluate (expression, item1, &value))
|
||||
return NULL;
|
||||
|
||||
/* If strings are NULL, order them before "". */
|
||||
if (ignore_case)
|
||||
{
|
||||
char *t;
|
||||
|
||||
t = g_utf8_casefold (g_value_get_string (&value), -1);
|
||||
s = g_utf8_collate_key (t, -1);
|
||||
g_free (t);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = g_utf8_collate_key (g_value_get_string (&value), -1);
|
||||
}
|
||||
|
||||
g_value_unset (&value);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static GtkOrdering
|
||||
gtk_string_sorter_compare (GtkSorter *sorter,
|
||||
gpointer item1,
|
||||
gpointer item2)
|
||||
{
|
||||
GtkStringSorter *self = GTK_STRING_SORTER (sorter);
|
||||
GValue value1 = G_VALUE_INIT;
|
||||
GValue value2 = G_VALUE_INIT;
|
||||
const char *s1, *s2;
|
||||
gboolean res1, res2;
|
||||
char *s1, *s2;
|
||||
GtkOrdering result;
|
||||
|
||||
if (self->expression == NULL)
|
||||
return GTK_ORDERING_EQUAL;
|
||||
|
||||
res1 = gtk_expression_evaluate (self->expression, item1, &value1);
|
||||
res2 = gtk_expression_evaluate (self->expression, item2, &value2);
|
||||
s1 = gtk_string_sorter_get_key (self->expression, self->ignore_case, item1);
|
||||
s2 = gtk_string_sorter_get_key (self->expression, self->ignore_case, item2);
|
||||
|
||||
/* If items don't evaluate, order them at the end, so they aren't
|
||||
* in the way. */
|
||||
if (!res1)
|
||||
{
|
||||
result = res2 ? GTK_ORDERING_LARGER : GTK_ORDERING_EQUAL;
|
||||
goto out;
|
||||
}
|
||||
else if (!res2)
|
||||
{
|
||||
result = GTK_ORDERING_SMALLER;
|
||||
goto out;
|
||||
}
|
||||
result = gtk_ordering_from_cmpfunc (g_strcmp0 (s1, s2));
|
||||
|
||||
s1 = g_value_get_string (&value1);
|
||||
s2 = g_value_get_string (&value2);
|
||||
|
||||
/* If strings are NULL, order them before "". */
|
||||
if (s1 == NULL)
|
||||
{
|
||||
result = s2 == NULL ? GTK_ORDERING_EQUAL : GTK_ORDERING_SMALLER;
|
||||
goto out;
|
||||
}
|
||||
else if (s2 == NULL)
|
||||
{
|
||||
result = GTK_ORDERING_LARGER;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (self->ignore_case)
|
||||
{
|
||||
char *t1, *t2;
|
||||
|
||||
t1 = g_utf8_casefold (s1, -1);
|
||||
t2 = g_utf8_casefold (s2, -1);
|
||||
|
||||
result = gtk_ordering_from_cmpfunc (g_utf8_collate (t1, t2));
|
||||
|
||||
g_free (t1);
|
||||
g_free (t2);
|
||||
}
|
||||
else
|
||||
result = gtk_ordering_from_cmpfunc (g_utf8_collate (s1, s2));
|
||||
|
||||
out:
|
||||
g_value_unset (&value1);
|
||||
g_value_unset (&value2);
|
||||
g_free (s1);
|
||||
g_free (s2);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -137,6 +126,95 @@ gtk_string_sorter_get_order (GtkSorter *sorter)
|
||||
return GTK_SORTER_ORDER_PARTIAL;
|
||||
}
|
||||
|
||||
typedef struct _GtkStringSortKeys GtkStringSortKeys;
|
||||
struct _GtkStringSortKeys
|
||||
{
|
||||
GtkSortKeys keys;
|
||||
|
||||
GtkExpression *expression;
|
||||
gboolean ignore_case;
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_string_sort_keys_free (GtkSortKeys *keys)
|
||||
{
|
||||
GtkStringSortKeys *self = (GtkStringSortKeys *) keys;
|
||||
|
||||
gtk_expression_unref (self->expression);
|
||||
g_slice_free (GtkStringSortKeys, self);
|
||||
}
|
||||
|
||||
static int
|
||||
gtk_string_sort_keys_compare (gconstpointer a,
|
||||
gconstpointer b,
|
||||
gpointer unused)
|
||||
{
|
||||
const char *sa = *(const char **) a;
|
||||
const char *sb = *(const char **) b;
|
||||
|
||||
if (sa == NULL)
|
||||
return sb == NULL ? GTK_ORDERING_EQUAL : GTK_ORDERING_LARGER;
|
||||
else if (sb == NULL)
|
||||
return GTK_ORDERING_SMALLER;
|
||||
|
||||
return gtk_ordering_from_cmpfunc (strcmp (sa, sb));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_string_sort_keys_is_compatible (GtkSortKeys *keys,
|
||||
GtkSortKeys *other)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_string_sort_keys_init_key (GtkSortKeys *keys,
|
||||
gpointer item,
|
||||
gpointer key_memory)
|
||||
{
|
||||
GtkStringSortKeys *self = (GtkStringSortKeys *) keys;
|
||||
char **key = (char **) key_memory;
|
||||
|
||||
*key = gtk_string_sorter_get_key (self->expression, self->ignore_case, item);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_string_sort_keys_clear_key (GtkSortKeys *keys,
|
||||
gpointer key_memory)
|
||||
{
|
||||
char **key = (char **) key_memory;
|
||||
|
||||
g_free (*key);
|
||||
}
|
||||
|
||||
static const GtkSortKeysClass GTK_STRING_SORT_KEYS_CLASS =
|
||||
{
|
||||
gtk_string_sort_keys_free,
|
||||
gtk_string_sort_keys_compare,
|
||||
gtk_string_sort_keys_is_compatible,
|
||||
gtk_string_sort_keys_init_key,
|
||||
gtk_string_sort_keys_clear_key,
|
||||
};
|
||||
|
||||
static GtkSortKeys *
|
||||
gtk_string_sort_keys_new (GtkStringSorter *self)
|
||||
{
|
||||
GtkStringSortKeys *result;
|
||||
|
||||
if (self->expression == NULL)
|
||||
return gtk_sort_keys_new_equal ();
|
||||
|
||||
result = gtk_sort_keys_new (GtkStringSortKeys,
|
||||
>K_STRING_SORT_KEYS_CLASS,
|
||||
sizeof (char *),
|
||||
sizeof (char *));
|
||||
|
||||
result->expression = gtk_expression_ref (self->expression);
|
||||
result->ignore_case = self->ignore_case;
|
||||
|
||||
return (GtkSortKeys *) result;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_string_sorter_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
@ -239,6 +317,10 @@ static void
|
||||
gtk_string_sorter_init (GtkStringSorter *self)
|
||||
{
|
||||
self->ignore_case = TRUE;
|
||||
|
||||
gtk_sorter_changed_with_keys (GTK_SORTER (self),
|
||||
GTK_SORTER_CHANGE_DIFFERENT,
|
||||
gtk_string_sort_keys_new (self));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -306,7 +388,9 @@ gtk_string_sorter_set_expression (GtkStringSorter *self,
|
||||
if (expression)
|
||||
self->expression = gtk_expression_ref (expression);
|
||||
|
||||
gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
|
||||
gtk_sorter_changed_with_keys (GTK_SORTER (self),
|
||||
GTK_SORTER_CHANGE_DIFFERENT,
|
||||
gtk_string_sort_keys_new (self));
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_EXPRESSION]);
|
||||
}
|
||||
@ -345,7 +429,9 @@ gtk_string_sorter_set_ignore_case (GtkStringSorter *self,
|
||||
|
||||
self->ignore_case = ignore_case;
|
||||
|
||||
gtk_sorter_changed (GTK_SORTER (self), ignore_case ? GTK_SORTER_CHANGE_LESS_STRICT : GTK_SORTER_CHANGE_MORE_STRICT);
|
||||
gtk_sorter_changed_with_keys (GTK_SORTER (self),
|
||||
ignore_case ? GTK_SORTER_CHANGE_LESS_STRICT : GTK_SORTER_CHANGE_MORE_STRICT,
|
||||
gtk_string_sort_keys_new (self));
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_IGNORE_CASE]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user