[gtk/wip/otte/sortlistmodel: 109/121] stringsorter: Implement GtkSortKeys



commit adb9be3c9e2c2f83a2be37a3f4be54016f1a84f1
Author: Benjamin Otte <otte redhat com>
Date:   Wed Jul 15 20:28:45 2020 +0200

    stringsorter: Implement GtkSortKeys

 gtk/gtkstringsorter.c | 188 ++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 137 insertions(+), 51 deletions(-)
---
diff --git a/gtk/gtkstringsorter.c b/gtk/gtkstringsorter.c
index 2879faf140..f986f9a518 100644
--- a/gtk/gtkstringsorter.c
+++ b/gtk/gtkstringsorter.c
@@ -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 GtkOrdering
-gtk_string_sorter_compare (GtkSorter *sorter,
-                           gpointer   item1,
-                           gpointer   item2)
+static char *
+gtk_string_sorter_get_key (GtkExpression *expression,
+                           gboolean       ignore_case,
+                           gpointer       item1)
 {
-  GtkStringSorter *self = GTK_STRING_SORTER (sorter);
-  GValue value1 = G_VALUE_INIT;
-  GValue value2 = G_VALUE_INIT;
-  const char *s1, *s2;
-  gboolean res1, res2;
-  GtkOrdering result;
+  GValue value = G_VALUE_INIT;
+  char *s;
 
-  if (self->expression == NULL)
-    return GTK_ORDERING_EQUAL;
+  if (expression == NULL)
+    return NULL;
 
-  res1 = gtk_expression_evaluate (self->expression, item1, &value1);
-  res2 = gtk_expression_evaluate (self->expression, item2, &value2);
+  if (!gtk_expression_evaluate (expression, item1, &value))
+    return NULL;
 
-  /* If items don't evaluate, order them at the end, so they aren't
-   * in the way. */
-  if (!res1)
+  /* If strings are NULL, order them before "". */
+  if (ignore_case)
     {
-      result = res2 ? GTK_ORDERING_LARGER : GTK_ORDERING_EQUAL;
-      goto out;
+      char *t;
+
+      t = g_utf8_casefold (g_value_get_string (&value), -1);
+      s = g_utf8_collate_key (t, -1);
+      g_free (t);
     }
-  else if (!res2)
+  else
     {
-      result = GTK_ORDERING_SMALLER;
-      goto out;
+      s = g_utf8_collate_key (g_value_get_string (&value), -1);
     }
 
-  s1 = g_value_get_string (&value1);
-  s2 = g_value_get_string (&value2);
+  g_value_unset (&value);
 
-  /* 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;
-    }
+  return s;
+}
 
-  if (self->ignore_case)
-    {
-      char *t1, *t2;
+static GtkOrdering
+gtk_string_sorter_compare (GtkSorter *sorter,
+                           gpointer   item1,
+                           gpointer   item2)
+{
+  GtkStringSorter *self = GTK_STRING_SORTER (sorter);
+  char *s1, *s2;
+  GtkOrdering result;
 
-      t1 = g_utf8_casefold (s1, -1);
-      t2 = g_utf8_casefold (s2, -1);
+  if (self->expression == NULL)
+    return GTK_ORDERING_EQUAL;
 
-      result = gtk_ordering_from_cmpfunc (g_utf8_collate (t1, t2));
+  s1 = gtk_string_sorter_get_key (self->expression, self->ignore_case, item1);
+  s2 = gtk_string_sorter_get_key (self->expression, self->ignore_case, item2);
 
-      g_free (t1);
-      g_free (t2);
-    }
-  else
-    result = gtk_ordering_from_cmpfunc (g_utf8_collate (s1, s2));
+  result = g_strcmp0 (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,
+                              &GTK_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]);
 }


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