[gtk/columnview-sorter-api: 1/2] columnviewsorter: Add public API




commit e040d3663eb17f8400e667ef9d1fa045c8656f9c
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Oct 20 10:33:57 2022 -0400

    columnviewsorter: Add public API
    
    This API should be sufficient to serialize
    a columnviews sort configuration.
    
    Fixes: #5149

 gtk/gtkcolumnviewsorter.c | 269 +++++++++++++++++++++++++++++++++++++++++++++-
 gtk/gtkcolumnviewsorter.h |  13 +++
 2 files changed, 278 insertions(+), 4 deletions(-)
---
diff --git a/gtk/gtkcolumnviewsorter.c b/gtk/gtkcolumnviewsorter.c
index a90a14a292..0cd9741fcd 100644
--- a/gtk/gtkcolumnviewsorter.c
+++ b/gtk/gtkcolumnviewsorter.c
@@ -24,6 +24,8 @@
 #include "gtkcolumnviewcolumnprivate.h"
 #include "gtktypebuiltins.h"
 
+/* {{{ GObject implementation */
+
 typedef struct
 {
   GtkColumnViewColumn *column;
@@ -31,7 +33,7 @@ typedef struct
   gboolean   inverted;
   gulong     changed_id;
 } Sorter;
- 
+
 static void
 free_sorter (gpointer data)
 {
@@ -43,6 +45,44 @@ free_sorter (gpointer data)
   g_free (s);
 }
 
+/**
+ * GtkColumnViewSorter:
+ *
+ * `GtkColumnViewSorter` is a sorter implementation that
+ * is geared towards the needs of `GtkColumnView`.
+ *
+ * The sorter returned by [method@Gtk.ColumnView.get_sorter] is
+ * a `GtkColumnViewSorter`.
+ *
+ * In column views, sorting can be configured by associating
+ * sorters with columns, and users can invert sort order by clicking
+ * on column headers. The API of `GtkColumnViewSorter` is designed
+ * to allow saving and restoring this configuration.
+ *
+ * If you are only interested in the primary sort column (i.e. the
+ * column where a sort indicator is shown in the header), then
+ * you can just look at [property@Gtk.ColumnViewSorter:primary-sort-column]
+ * and [property@Gtk.ColumnViewSorter:primary-sort-order].
+ *
+ * If you want to store the full sort configuration, including
+ * secondary sort columns that are used for tie breaking, then
+ * you can use [method@Gtk.ColumnViewSorter.get_nth_sort_column].
+ * To get notified about changes, use [signal@Gtk.Sorter::changed].
+ *
+ * To restore a saved sort configuration on a `GtkColumnView`,
+ * use code like:
+ *
+ * ```
+ * sorter = gtk_column_view_get_sorter (view);
+ * for (i = gtk_column_view_sorter_get_n_sort_columns (sorter) - 1; i >= 0; i--)
+ *   {
+ *     column = gtk_column_view_sorter_get_nth_sort_column (sorter, i, &order);
+ *     gtk_column_view_sort_by_column (view, column, order);
+ *   }
+ * ```
+ *
+ * `GtkColumnViewSorter` was added in GTK 4.10
+ */
 struct _GtkColumnViewSorter
 {
   GtkSorter parent_instance;
@@ -50,6 +90,16 @@ struct _GtkColumnViewSorter
   GSequence *sorters;
 };
 
+enum
+{
+  PROP_PRIMARY_SORT_COLUMN = 1,
+  PROP_PRIMARY_SORT_ORDER,
+
+  NUM_PROPERTIES
+};
+
+static GParamSpec *properties[NUM_PROPERTIES];
+
 G_DEFINE_TYPE (GtkColumnViewSorter, gtk_column_view_sorter, GTK_TYPE_SORTER)
 
 static GtkOrdering
@@ -127,6 +177,30 @@ gtk_column_view_sorter_dispose (GObject *object)
   G_OBJECT_CLASS (gtk_column_view_sorter_parent_class)->dispose (object);
 }
 
+static void
+gtk_column_view_sorter_get_property (GObject    *object,
+                                     guint       prop_id,
+                                     GValue     *value,
+                                     GParamSpec *pspec)
+{
+  GtkColumnViewSorter *self = GTK_COLUMN_VIEW_SORTER (object);
+
+  switch (prop_id)
+    {
+    case PROP_PRIMARY_SORT_COLUMN:
+      g_value_set_object (value, gtk_column_view_sorter_get_primary_sort_column (self));
+      break;
+
+    case PROP_PRIMARY_SORT_ORDER:
+      g_value_set_enum (value, gtk_column_view_sorter_get_primary_sort_order (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
 static void
 gtk_column_view_sorter_class_init (GtkColumnViewSorterClass *class)
 {
@@ -137,6 +211,41 @@ gtk_column_view_sorter_class_init (GtkColumnViewSorterClass *class)
   sorter_class->get_order = gtk_column_view_sorter_get_order;
 
   object_class->dispose = gtk_column_view_sorter_dispose;
+  object_class->get_property = gtk_column_view_sorter_get_property;
+
+  /**
+   * GtkColumnViewSorter:primary-sort-column: (attributes 
org.gtk.Property.get=gtk_column_view_sorter_get_primary_sort_column)
+   *
+   * The primary sort column.
+   *
+   * The primary sort column is the one that displays the triangle
+   * in a column view header.
+   *
+   * Since: 4.10
+   */
+  properties[PROP_PRIMARY_SORT_COLUMN] =
+    g_param_spec_object ("primary-sort-column", NULL, NULL,
+                         GTK_TYPE_COLUMN_VIEW_COLUMN,
+                         G_PARAM_READABLE|G_PARAM_STATIC_STRINGS);
+
+  /**
+   * GtkColumnViewSorter:primary-sort-order: (attributes 
org.gtk.Property.get=gtk_column_view_sorter_get_primary_sort_order)
+   *
+   * The primary sort order.
+   *
+   * The primary sort order determines whether the triangle displayed
+   * in the column view header of the primary sort column points upwards
+   * or downwards.
+   *
+   * Since: 4.10
+   */
+  properties[PROP_PRIMARY_SORT_ORDER] =
+    g_param_spec_enum ("primary-sort-order", NULL, NULL,
+                       GTK_TYPE_SORT_TYPE,
+                       GTK_SORT_ASCENDING,
+                       G_PARAM_READABLE|G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
 }
 
 static void
@@ -145,6 +254,9 @@ gtk_column_view_sorter_init (GtkColumnViewSorter *self)
   self->sorters = g_sequence_new (free_sorter);
 }
 
+/* }}} */
+/* {{{ Private API */
+
 GtkColumnViewSorter *
 gtk_column_view_sorter_new (void)
 {
@@ -214,14 +326,17 @@ gtk_column_view_sorter_add_column (GtkColumnViewSorter *self,
   s->sorter = g_object_ref (sorter);
   s->changed_id = g_signal_connect (sorter, "changed", G_CALLBACK (gtk_column_view_sorter_changed_cb), self);
   s->inverted = FALSE;
- 
+
   g_sequence_insert_before (iter, s);
 
   /* notify the previous first column to stop drawing an arrow */
   if (first)
     gtk_column_view_column_notify_sort (first->column);
 
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PRIMARY_SORT_COLUMN]);
 out:
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PRIMARY_SORT_ORDER]);
+
   gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
 
   gtk_column_view_column_notify_sort (column);
@@ -238,6 +353,9 @@ gtk_column_view_sorter_remove_column (GtkColumnViewSorter *self,
 
   if (remove_column (self, column))
     {
+      g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PRIMARY_SORT_COLUMN]);
+      g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PRIMARY_SORT_ORDER]);
+
       gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
       gtk_column_view_column_notify_sort (column);
       return TRUE;
@@ -256,7 +374,7 @@ gtk_column_view_sorter_set_column (GtkColumnViewSorter *self,
 
   g_return_val_if_fail (GTK_IS_COLUMN_VIEW_SORTER (self), FALSE);
   g_return_val_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (column), FALSE);
-  
+
   sorter = gtk_column_view_column_get_sorter (column);
   if (sorter == NULL)
     return FALSE;
@@ -271,9 +389,12 @@ gtk_column_view_sorter_set_column (GtkColumnViewSorter *self,
   s->sorter = g_object_ref (sorter);
   s->changed_id = g_signal_connect (sorter, "changed", G_CALLBACK (gtk_column_view_sorter_changed_cb), self);
   s->inverted = inverted;
- 
+
   g_sequence_prepend (self->sorters, s);
 
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PRIMARY_SORT_COLUMN]);
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PRIMARY_SORT_ORDER]);
+
   gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
 
   gtk_column_view_column_notify_sort (column);
@@ -302,6 +423,9 @@ gtk_column_view_sorter_clear (GtkColumnViewSorter *self)
 
   g_sequence_remove_range (iter, g_sequence_get_end_iter (self->sorters));
 
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PRIMARY_SORT_COLUMN]);
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PRIMARY_SORT_ORDER]);
+
   gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
 
   gtk_column_view_column_notify_sort (column);
@@ -328,3 +452,140 @@ gtk_column_view_sorter_get_sort_column (GtkColumnViewSorter *self,
 
   return s->column;
 }
+
+/* }}} */
+/* {{{ Public API */
+
+/**
+ * gtk_column_view_sorter_get_primary_sort_column:
+ * @self: a `GtkColumnViewSorter`
+ *
+ * Returns the primary sort column.
+ *
+ * The primary sort column is the one that displays the triangle
+ * in a column view header.
+ *
+ * Returns: (nullable) (transfer none): the primary sort column
+ *
+ * Since: 4.10
+ */
+GtkColumnViewColumn *
+gtk_column_view_sorter_get_primary_sort_column (GtkColumnViewSorter *self)
+{
+  GSequenceIter *iter;
+  Sorter *s;
+
+  g_return_val_if_fail (GTK_IS_COLUMN_VIEW_SORTER (self), NULL);
+
+  iter = g_sequence_get_begin_iter (self->sorters);
+  if (g_sequence_iter_is_end (iter))
+    return NULL;
+
+  s = g_sequence_get (iter);
+
+  return s->column;
+}
+
+/**
+ * gtk_column_view_sorter_get_primary_sort_order:
+ * @self: a `GtkColumnViewSorter`
+ *
+ * Returns the primary sort order.
+ *
+ * The primary sort order determines whether the triangle displayed
+ * in the column view header of the primary sort column points upwards
+ * or downwards.
+ *
+ * If there is no primary sort column, then this function returns
+ * `GTK_SORT_ASCENDING`.
+ *
+ * Returns: the primary sort order
+ *
+ * Since: 4.10
+ */
+GtkSortType
+gtk_column_view_sorter_get_primary_sort_order (GtkColumnViewSorter *self)
+{
+  GSequenceIter *iter;
+  Sorter *s;
+
+  g_return_val_if_fail (GTK_IS_COLUMN_VIEW_SORTER (self), GTK_SORT_ASCENDING);
+
+  iter = g_sequence_get_begin_iter (self->sorters);
+  if (g_sequence_iter_is_end (iter))
+    return GTK_SORT_ASCENDING;
+
+  s = g_sequence_get (iter);
+
+  return s->inverted ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING;
+}
+
+/**
+ * gtk_column_view_sorter_get_n_sort_columns:
+ * @self: a `GtkColumnViewSorter`
+ *
+ * Returns the number of columns by which the sorter sorts.
+ *
+ * If the sorter of the primary sort column does not determine
+ * a total order, then the secondary sorters are consulted to
+ * break the ties.
+ *
+ * Use the [signal@Gtk.Sorter::changed] signal to get notified
+ * when the number of sort columns changes.
+ *
+ * Returns: the number of sort columns
+ *
+ * Since: 4.10
+ */
+guint
+gtk_column_view_sorter_get_n_sort_columns (GtkColumnViewSorter *self)
+{
+  g_return_val_if_fail (GTK_IS_COLUMN_VIEW_SORTER (self), 0);
+
+  return (guint) g_sequence_get_length (self->sorters);
+}
+
+/**
+ * gtk_column_view_sorter_get_nth_sort_column:
+ * @self: a `GtkColumnViewSorter`
+ * @position: the position of the sort column to retrieve (0 for the
+ *     primary sort column)
+ * @sort_order: (out): return location for the sort order
+ *
+ * Gets the @position'th sort column and its associated sort order.
+ *
+ * Use the [signal@Gtk.Sorter::changed] signal to get notified
+ * when sort columns change.
+ *
+ * Returns: (nullable) (transfer none): the @positions sort column
+ *
+ * Since: 4.10
+ */
+GtkColumnViewColumn *
+gtk_column_view_sorter_get_nth_sort_column (GtkColumnViewSorter *self,
+                                            guint                position,
+                                            GtkSortType         *sort_order)
+{
+  GSequenceIter *iter;
+  Sorter *s;
+
+  g_return_val_if_fail (GTK_IS_COLUMN_VIEW_SORTER (self), NULL);
+
+  iter = g_sequence_get_iter_at_pos (self->sorters, (int) position);
+
+  if (g_sequence_iter_is_end (iter))
+    {
+      *sort_order = GTK_SORT_ASCENDING;
+      return NULL;
+    }
+
+  s = g_sequence_get (iter);
+
+  *sort_order = s->inverted ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING;
+
+  return s->column;
+}
+
+/* }}} */
+
+/* vim:set foldmethod=marker expandtab: */
diff --git a/gtk/gtkcolumnviewsorter.h b/gtk/gtkcolumnviewsorter.h
index a412768e0b..ec562da87a 100644
--- a/gtk/gtkcolumnviewsorter.h
+++ b/gtk/gtkcolumnviewsorter.h
@@ -35,6 +35,19 @@ G_BEGIN_DECLS
 GDK_AVAILABLE_IN_4_10
 G_DECLARE_FINAL_TYPE (GtkColumnViewSorter, gtk_column_view_sorter, GTK, COLUMN_VIEW_SORTER, GtkSorter)
 
+GDK_AVAILABLE_IN_4_10
+GtkColumnViewColumn *   gtk_column_view_sorter_get_primary_sort_column (GtkColumnViewSorter *self);
+
+GDK_AVAILABLE_IN_4_10
+GtkSortType             gtk_column_view_sorter_get_primary_sort_order  (GtkColumnViewSorter *self);
+
+GDK_AVAILABLE_IN_4_10
+guint                   gtk_column_view_sorter_get_n_sort_columns      (GtkColumnViewSorter *self);
+
+GDK_AVAILABLE_IN_4_10
+GtkColumnViewColumn *   gtk_column_view_sorter_get_nth_sort_column     (GtkColumnViewSorter *self,
+                                                                        guint                position,
+                                                                        GtkSortType         *sort_order);
 
 G_END_DECLS
 


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