Make priority sorting work
[milk] / src / milk-task-model.c
index cb24974..981be2a 100644 (file)
 
 static void
 milk_task_model_tree_model_init (GtkTreeModelIface *iface);
+static void
+milk_task_model_tree_sortable_init (GtkTreeSortableIface *iface);
 
-G_DEFINE_TYPE_EXTENDED (MilkTaskModel,
-                        milk_task_model,
-                        G_TYPE_OBJECT,
-                        0,
-                        G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
-                                               milk_task_model_tree_model_init));
+G_DEFINE_TYPE_WITH_CODE (MilkTaskModel,
+                         milk_task_model,
+                         G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
+                                 milk_task_model_tree_model_init)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
+                                 milk_task_model_tree_sortable_init));
 
 /* less expensive than G_TYPE_INSTANCE_GET_PRIVATE */
 #define MILK_TASK_MODEL_PRIVATE(o) ((MILK_TASK_MODEL ((o)))->priv)
@@ -232,6 +235,59 @@ milk_task_model_iter_parent (GtkTreeModel *model,
                         GTK_TREE_MODEL (priv->store), iter, child);
 }
 
+static gboolean
+milk_task_model_get_sort_column_id (GtkTreeSortable *sortable,
+                                    gint            *column_id,
+                                    GtkSortType     *order)
+{
+        MilkTaskModel *model;
+        MilkTaskModelPrivate *priv;
+
+        g_return_if_fail (MILK_IS_TASK_MODEL (sortable));
+
+        model = MILK_TASK_MODEL (model);
+        priv = MILK_TASK_MODEL_PRIVATE (model);
+
+        return gtk_tree_sortable_get_sort_column_id (
+                        GTK_TREE_SORTABLE (priv->store), column_id, order);
+}
+
+static gboolean
+milk_task_model_set_sort_column_id (GtkTreeSortable *sortable,
+                                    gint             column_id,
+                                    GtkSortType      order)
+{
+        MilkTaskModel *model;
+        MilkTaskModelPrivate *priv;
+
+        g_return_if_fail (MILK_IS_TASK_MODEL (sortable));
+
+        model = MILK_TASK_MODEL (model);
+        priv = MILK_TASK_MODEL_PRIVATE (model);
+
+        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->store),
+                        column_id, order);
+}
+
+static void
+milk_task_model_set_default_sort_func (GtkTreeSortable        *sortable,
+                                       GtkTreeIterCompareFunc  callback,
+                                       gpointer                user_data,
+                                       GDestroyNotify          destroy_data)
+{
+        MilkTaskModel *model;
+        MilkTaskModelPrivate *priv;
+
+        g_return_if_fail (MILK_IS_TASK_MODEL (sortable));
+
+        model = MILK_TASK_MODEL (model);
+        priv = MILK_TASK_MODEL_PRIVATE (model);
+
+        gtk_tree_sortable_set_default_sort_func (
+                        GTK_TREE_SORTABLE (priv->store), callback, user_data,
+                        destroy_data);
+}
+
 typedef gchar* (*RtmTaskAttrFunc) (RtmTask*);
 
 static gboolean
@@ -324,6 +380,48 @@ rows_reordered_cb (GtkTreeModel  *model,
                         new_order);
 }
 
+static gint
+model_priority_sort_func (GtkTreeModel *model,
+                          GtkTreeIter  *a,
+                          GtkTreeIter  *b,
+                          gpointer      user_data)
+{
+        gint retval;
+        RtmTask *task_a, *task_b;
+        const char *priority_str_a, *priority_str_b;
+        gint64 priority_a, priority_b;
+        const char *name_a, *name_b;
+
+        gtk_tree_model_get (model, a,
+                        MILK_TASK_MODEL_COLUMN_TASK, &task_a,
+                        -1);
+
+        gtk_tree_model_get (model, b,
+                        MILK_TASK_MODEL_COLUMN_TASK, &task_b,
+                        -1);
+
+        priority_str_a = rtm_task_get_priority (task_a);
+        priority_str_b = rtm_task_get_priority (task_b);
+
+        /* these will be assigned 0 if they're not the well-known priorites
+         * (1-3) */
+        priority_a = g_ascii_strtoll (priority_str_a, NULL, 10);
+        priority_b = g_ascii_strtoll (priority_str_b, NULL, 10);
+
+        priority_a = (priority_a <= 0) ? G_MAXINT : priority_a;
+        priority_b = (priority_b <= 0) ? G_MAXINT : priority_b;
+
+        retval = (priority_a - priority_b);
+        if (retval != 0)
+                return retval;
+
+        /* secondary sort, by name */
+        name_a = rtm_task_get_name (task_a);
+        name_b = rtm_task_get_name (task_b);
+
+        return g_utf8_collate (name_a, name_b);
+}
+
 static void
 cache_cleared_cb (MilkCache     *cache,
                   MilkTaskModel *model)
@@ -588,6 +686,16 @@ milk_task_model_init (MilkTaskModel *self)
         priv->store = gtk_list_store_new (
                         MILK_TASK_MODEL_N_COLUMNS, RTM_TYPE_TASK);
 
+        gtk_tree_sortable_set_default_sort_func (
+                        GTK_TREE_SORTABLE (priv->store),
+                        model_priority_sort_func, g_object_ref (self),
+                        g_object_unref);
+
+        gtk_tree_sortable_set_sort_column_id (
+                        GTK_TREE_SORTABLE (priv->store),
+                        GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
+                        GTK_SORT_ASCENDING);
+
         g_signal_connect (priv->store, "row-changed",
                         G_CALLBACK (row_changed_cb), self);
 
@@ -618,6 +726,14 @@ milk_task_model_tree_model_init (GtkTreeModelIface *iface)
         iface->iter_parent     = milk_task_model_iter_parent;
 }
 
+static void
+milk_task_model_tree_sortable_init (GtkTreeSortableIface *iface)
+{
+        iface->get_sort_column_id    = milk_task_model_get_sort_column_id;
+        iface->set_sort_column_id    = milk_task_model_set_sort_column_id;
+        iface->set_default_sort_func = milk_task_model_set_default_sort_func;
+}
+
 MilkTaskModel*
 milk_task_model_new ()
 {