[gnome-todo] panels: Use GtdListModelFilter and GtdListModelSort



commit b3a8691da0f6f0216db4b4046b51066473e08ac2
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Wed Sep 12 15:02:26 2018 -0300

    panels: Use GtdListModelFilter and GtdListModelSort

 plugins/all-tasks-panel/gtd-all-tasks-panel.c | 151 ++++++++---------------
 plugins/next-week-panel/gtd-next-week-panel.c | 117 +++++++++---------
 plugins/scheduled-panel/gtd-panel-scheduled.c | 143 ++++++++++------------
 plugins/today-panel/gtd-panel-today.c         | 165 ++++++++++++--------------
 4 files changed, 246 insertions(+), 330 deletions(-)
---
diff --git a/plugins/all-tasks-panel/gtd-all-tasks-panel.c b/plugins/all-tasks-panel/gtd-all-tasks-panel.c
index a8ffbd3..9ecd426 100644
--- a/plugins/all-tasks-panel/gtd-all-tasks-panel.c
+++ b/plugins/all-tasks-panel/gtd-all-tasks-panel.c
@@ -41,7 +41,8 @@ struct _GtdAllTasksPanel
   guint               number_of_tasks;
   GtdTaskListView    *view;
 
-  GListStore         *model;
+  GtdListModelFilter *filter_model;
+  GtdListModelSort   *sort_model;
 };
 
 static void          gtd_panel_iface_init                        (GtdPanelInterface  *iface);
@@ -196,6 +197,11 @@ compare_by_date (GDateTime *d1,
   return g_date_time_get_day_of_year (d1) - g_date_time_get_day_of_year (d2);
 }
 
+
+/*
+ * Callbacks
+ */
+
 static GtkWidget*
 header_func (GtdTask          *task,
              GtdTask          *previous_task,
@@ -227,106 +233,48 @@ header_func (GtdTask          *task,
 }
 
 static gint
-sort_func (gconstpointer a,
-           gconstpointer b,
-           gpointer      user_data)
+sort_func (GObject  *a,
+           GObject  *b,
+           gpointer  user_data)
 {
-  GDateTime *dt1;
-  GDateTime *dt2;
-  GtdTask *task1;
-  GtdTask *task2;
-  gint retval;
-  gchar *t1;
-  gchar *t2;
-
-  task1 = (GtdTask*) a;
-  task2 = (GtdTask*) b;
-
-  /* First, compare by ::due-date. */
-  dt1 = gtd_task_get_due_date (task1);
-  dt2 = gtd_task_get_due_date (task2);
-
-  retval = compare_by_date (dt1, dt2);
-
-  g_clear_pointer (&dt1, g_date_time_unref);
-  g_clear_pointer (&dt2, g_date_time_unref);
-
-  if (retval != 0)
-    return retval;
-
-  /* Third, compare by ::creation-date. */
-  dt1 = gtd_task_get_creation_date (task1);
-  dt2 = gtd_task_get_creation_date (task2);
-
-  if (!dt1 && !dt2)
-    retval =  0;
-  else if (!dt1)
-    retval =  1;
-  else if (!dt2)
-    retval = -1;
-  else
-    retval = g_date_time_compare (dt1, dt2);
-
-  g_clear_pointer (&dt1, g_date_time_unref);
-  g_clear_pointer (&dt2, g_date_time_unref);
-
-  if (retval != 0)
-    return retval;
-
-  /* Finally, compare by ::title. */
-  t1 = t2 = NULL;
+  GtdTask *task_a = (GtdTask*) a;
+  GtdTask *task_b = (GtdTask*) b;
 
-  t1 = g_utf8_casefold (gtd_task_get_title (task1), -1);
-  t2 = g_utf8_casefold (gtd_task_get_title (task2), -1);
+  return gtd_task_compare (task_a, task_b);
+}
 
-  retval = g_strcmp0 (t1, t2);
+static gboolean
+filter_func (GObject  *object,
+             gpointer  user_data)
+{
+  GtdTask *task = (GtdTask*) object;
+  return !gtd_task_get_complete (task);
+}
 
-  g_free (t1);
-  g_free (t2);
+static void
+on_model_items_changed_cb (GListModel       *model,
+                           guint             position,
+                           guint             n_removed,
+                           guint             n_added,
+                           GtdAllTasksPanel *self)
+{
+  if (self->number_of_tasks == g_list_model_get_n_items (model))
+    return;
 
-  return retval;
+  self->number_of_tasks = g_list_model_get_n_items (model);
+  g_object_notify (G_OBJECT (self), "subtitle");
 }
 
 static void
-update_tasks (GtdAllTasksPanel *self)
+on_timer_updated_cb (GtdTimer         *timer,
+                     GtdAllTasksPanel *self)
 {
   g_autoptr (GDateTime) now = NULL;
-  g_autoptr (GList) tasklists = NULL;
-  GtdManager *manager;
-  GList *l;
 
   now = g_date_time_new_now_local ();
-  manager = gtd_manager_get_default ();
-  tasklists = gtd_manager_get_task_lists (manager);
-
-  g_list_store_remove_all (self->model);
-
-  /* Recount tasks */
-  for (l = tasklists; l != NULL; l = l->next)
-    {
-      guint i;
-
-      for (i = 0; i < g_list_model_get_n_items (l->data); i++)
-        {
-          GtdTask *task;
-
-          task = g_list_model_get_item (l->data, i);
-
-          if (gtd_task_get_complete (task))
-            continue;
-
-          g_list_store_insert_sorted (self->model, task, sort_func, self);
-        }
-    }
-
-  /* Add the tasks to the view */
   gtd_task_list_view_set_default_date (self->view, now);
 
-  if (self->number_of_tasks != g_list_model_get_n_items (G_LIST_MODEL (self->model)))
-    {
-      self->number_of_tasks = g_list_model_get_n_items (G_LIST_MODEL (self->model));
-      g_object_notify (G_OBJECT (self), "subtitle");
-    }
+  gtd_list_model_filter_invalidate (self->filter_model);
 }
 
 /*
@@ -400,7 +348,8 @@ gtd_all_tasks_panel_finalize (GObject *object)
   GtdAllTasksPanel *self = (GtdAllTasksPanel *)object;
 
   g_clear_object (&self->icon);
-  g_clear_object (&self->model);
+  g_clear_object (&self->filter_model);
+  g_clear_object (&self->sort_model);
 
   G_OBJECT_CLASS (gtd_all_tasks_panel_parent_class)->finalize (object);
 }
@@ -473,14 +422,19 @@ gtd_all_tasks_panel_class_init (GtdAllTasksPanelClass *klass)
 static void
 gtd_all_tasks_panel_init (GtdAllTasksPanel *self)
 {
-  GtdManager *manager;
+  GtdManager *manager = gtd_manager_get_default ();
 
   self->icon = g_themed_icon_new ("view-tasks-all-symbolic");
-  self->model = g_list_store_new (GTD_TYPE_TASK);
+
+  self->filter_model = gtd_list_model_filter_new (gtd_manager_get_tasks_model (manager));
+  gtd_list_model_filter_set_filter_func (self->filter_model, filter_func, self, NULL);
+
+  self->sort_model = gtd_list_model_sort_new (G_LIST_MODEL (self->filter_model));
+  gtd_list_model_sort_set_sort_func (self->sort_model, sort_func, self, NULL);
 
   /* The main view */
   self->view = GTD_TASK_LIST_VIEW (gtd_task_list_view_new ());
-  gtd_task_list_view_set_model (GTD_TASK_LIST_VIEW (self->view), G_LIST_MODEL (self->model));
+  gtd_task_list_view_set_model (GTD_TASK_LIST_VIEW (self->view), G_LIST_MODEL (self->sort_model));
   gtd_task_list_view_set_handle_subtasks (GTD_TASK_LIST_VIEW (self->view), FALSE);
   gtd_task_list_view_set_show_list_name (GTD_TASK_LIST_VIEW (self->view), TRUE);
   gtd_task_list_view_set_show_due_date (GTD_TASK_LIST_VIEW (self->view), FALSE);
@@ -493,18 +447,15 @@ gtd_all_tasks_panel_init (GtdAllTasksPanel *self)
                                       (GtdTaskListViewHeaderFunc) header_func,
                                       self);
 
-  /* Connect to GtdManager::list-* signals to update the title */
-  manager = gtd_manager_get_default ();
-
-  update_tasks (self);
-
-  g_signal_connect_object (manager, "list-added", G_CALLBACK (update_tasks), self, G_CONNECT_SWAPPED);
-  g_signal_connect_object (manager, "list-removed", G_CALLBACK (update_tasks), self, G_CONNECT_SWAPPED);
-  g_signal_connect_object (manager, "list-changed", G_CALLBACK (update_tasks), self, G_CONNECT_SWAPPED);
+  g_signal_connect_object (self->sort_model,
+                           "items-changed",
+                           G_CALLBACK (on_model_items_changed_cb),
+                           self,
+                           0);
 
   g_signal_connect_object (gtd_manager_get_timer (manager),
                            "update",
-                           G_CALLBACK (update_tasks),
+                           G_CALLBACK (on_timer_updated_cb),
                            self,
                            G_CONNECT_SWAPPED);
 }
diff --git a/plugins/next-week-panel/gtd-next-week-panel.c b/plugins/next-week-panel/gtd-next-week-panel.c
index 8379eae..aa560c1 100644
--- a/plugins/next-week-panel/gtd-next-week-panel.c
+++ b/plugins/next-week-panel/gtd-next-week-panel.c
@@ -41,7 +41,8 @@ struct _GtdNextWeekPanel
   guint               number_of_tasks;
   GtdTaskListView    *view;
 
-  GListStore         *model;
+  GtdListModelFilter *filter_model;
+  GtdListModelSort   *sort_model;
 };
 
 static void          gtd_panel_iface_init                        (GtdPanelInterface  *iface);
@@ -66,7 +67,7 @@ enum
  * Auxiliary methods
  */
 
-static void
+static gboolean
 get_date_offset (GDateTime *dt,
                  gint      *days_diff,
                  gint      *years_diff)
@@ -94,6 +95,8 @@ get_date_offset (GDateTime *dt,
 
   if (years_diff)
     *years_diff = g_date_time_get_year (dt) - g_date_time_get_year (now);
+
+  return TRUE;
 }
 
 static gchar*
@@ -216,9 +219,9 @@ header_func (GtdTask          *task,
 }
 
 static gint
-sort_func (gconstpointer a,
-           gconstpointer b,
-           gpointer      user_data)
+sort_func (GObject  *a,
+           GObject  *b,
+           gpointer  user_data)
 {
   GDateTime *dt1;
   GDateTime *dt2;
@@ -283,58 +286,47 @@ sort_func (gconstpointer a,
   return retval;
 }
 
-static void
-update_tasks (GtdNextWeekPanel *self)
+static gboolean
+filter_func (GObject  *object,
+             gpointer  user_data)
 {
-  g_autoptr (GDateTime) now = NULL;
-  g_autoptr (GList) tasklists = NULL;
-  GtdManager *manager;
-  GList *l;
+  g_autoptr (GDateTime) task_dt = NULL;
+  GtdTask *task;
+  gint days_offset;
 
-  now = g_date_time_new_now_local ();
-  manager = gtd_manager_get_default ();
-  tasklists = gtd_manager_get_task_lists (manager);
-
-  g_list_store_remove_all (self->model);
-
-  /* Recount tasks */
-  for (l = tasklists; l != NULL; l = l->next)
-    {
-      guint i;
+  task = (GtdTask*) object;
+  task_dt = gtd_task_get_due_date (task);
 
-      for (i = 0; i < g_list_model_get_n_items (l->data); i++)
-        {
-          g_autoptr (GDateTime) task_dt = NULL;
-          GtdTask *task;
-          gint days_offset;
-
-          task = g_list_model_get_item (l->data, i);
-
-          if (gtd_task_get_complete (task))
-            continue;
-
-          task_dt = gtd_task_get_due_date (task);
-
-          if (!task_dt)
-              continue;
+  return !gtd_task_get_complete (task) &&
+         task_dt != NULL &&
+         get_date_offset (task_dt, &days_offset, NULL) &&
+         days_offset < 7;
+}
 
-          get_date_offset (task_dt, &days_offset, NULL);
+static void
+on_model_items_changed_cb (GListModel       *model,
+                           guint             position,
+                           guint             n_removed,
+                           guint             n_added,
+                           GtdNextWeekPanel *self)
+{
+  if (self->number_of_tasks == g_list_model_get_n_items (model))
+    return;
 
-          if (days_offset >= 7)
-            continue;
+  self->number_of_tasks = g_list_model_get_n_items (model);
+  g_object_notify (G_OBJECT (self), "subtitle");
+}
 
-          g_list_store_insert_sorted (self->model, task, sort_func, self);
-        }
-    }
+static void
+on_timer_updated_cb (GtdTimer         *timer,
+                     GtdNextWeekPanel *self)
+{
+  g_autoptr (GDateTime) now = NULL;
 
-  /* Add the tasks to the view */
+  now = g_date_time_new_now_local ();
   gtd_task_list_view_set_default_date (self->view, now);
 
-  if (self->number_of_tasks != g_list_model_get_n_items (G_LIST_MODEL (self->model)))
-    {
-      self->number_of_tasks = g_list_model_get_n_items (G_LIST_MODEL (self->model));
-      g_object_notify (G_OBJECT (self), "subtitle");
-    }
+  gtd_list_model_filter_invalidate (self->filter_model);
 }
 
 /*
@@ -408,7 +400,8 @@ gtd_next_week_panel_finalize (GObject *object)
   GtdNextWeekPanel *self = (GtdNextWeekPanel *)object;
 
   g_clear_object (&self->icon);
-  g_clear_object (&self->model);
+  g_clear_object (&self->filter_model);
+  g_clear_object (&self->sort_model);
 
   G_OBJECT_CLASS (gtd_next_week_panel_parent_class)->finalize (object);
 }
@@ -481,14 +474,19 @@ gtd_next_week_panel_class_init (GtdNextWeekPanelClass *klass)
 static void
 gtd_next_week_panel_init (GtdNextWeekPanel *self)
 {
-  GtdManager *manager;
+  GtdManager *manager = gtd_manager_get_default ();
 
   self->icon = g_themed_icon_new ("view-tasks-week-symbolic");
-  self->model = g_list_store_new (GTD_TYPE_TASK);
+
+  self->filter_model = gtd_list_model_filter_new (gtd_manager_get_tasks_model (manager));
+  gtd_list_model_filter_set_filter_func (self->filter_model, filter_func, self, NULL);
+
+  self->sort_model = gtd_list_model_sort_new (G_LIST_MODEL (self->filter_model));
+  gtd_list_model_sort_set_sort_func (self->sort_model, sort_func, self, NULL);
 
   /* The main view */
   self->view = GTD_TASK_LIST_VIEW (gtd_task_list_view_new ());
-  gtd_task_list_view_set_model (GTD_TASK_LIST_VIEW (self->view), G_LIST_MODEL (self->model));
+  gtd_task_list_view_set_model (GTD_TASK_LIST_VIEW (self->view), G_LIST_MODEL (self->sort_model));
   gtd_task_list_view_set_handle_subtasks (GTD_TASK_LIST_VIEW (self->view), FALSE);
   gtd_task_list_view_set_show_list_name (GTD_TASK_LIST_VIEW (self->view), TRUE);
   gtd_task_list_view_set_show_due_date (GTD_TASK_LIST_VIEW (self->view), FALSE);
@@ -501,18 +499,15 @@ gtd_next_week_panel_init (GtdNextWeekPanel *self)
                                       (GtdTaskListViewHeaderFunc) header_func,
                                       self);
 
-  /* Connect to GtdManager::list-* signals to update the title */
-  manager = gtd_manager_get_default ();
-
-  update_tasks (self);
-
-  g_signal_connect_object (manager, "list-added", G_CALLBACK (update_tasks), self, G_CONNECT_SWAPPED);
-  g_signal_connect_object (manager, "list-removed", G_CALLBACK (update_tasks), self, G_CONNECT_SWAPPED);
-  g_signal_connect_object (manager, "list-changed", G_CALLBACK (update_tasks), self, G_CONNECT_SWAPPED);
+  g_signal_connect_object (self->sort_model,
+                           "items-changed",
+                           G_CALLBACK (on_model_items_changed_cb),
+                           self,
+                           0);
 
   g_signal_connect_object (gtd_manager_get_timer (manager),
                            "update",
-                           G_CALLBACK (update_tasks),
+                           G_CALLBACK (on_timer_updated_cb),
                            self,
                            G_CONNECT_SWAPPED);
 }
diff --git a/plugins/scheduled-panel/gtd-panel-scheduled.c b/plugins/scheduled-panel/gtd-panel-scheduled.c
index 196cc5c..73e7b4e 100644
--- a/plugins/scheduled-panel/gtd-panel-scheduled.c
+++ b/plugins/scheduled-panel/gtd-panel-scheduled.c
@@ -32,8 +32,10 @@ struct _GtdPanelScheduled
   GIcon              *icon;
 
   guint               number_of_tasks;
-  GListStore         *model;
-  GtkWidget          *view;
+  GtdTaskListView    *view;
+
+  GtdListModelFilter *filter_model;
+  GtdListModelSort   *sort_model;
 };
 
 static void          gtd_panel_iface_init                        (GtdPanelInterface  *iface);
@@ -213,9 +215,9 @@ header_func (GtdTask           *task,
 }
 
 static gint
-sort_func (gconstpointer  a,
-           gconstpointer  b,
-           gpointer       user_data)
+sort_func (GObject  *a,
+           GObject  *b,
+           gpointer  user_data)
 {
   GDateTime *dt1;
   GDateTime *dt2;
@@ -286,56 +288,46 @@ sort_func (gconstpointer  a,
   return retval;
 }
 
-static void
-gtd_panel_scheduled_count_tasks (GtdPanelScheduled *panel)
+static gboolean
+filter_func (GObject  *object,
+             gpointer  user_data)
 {
-  g_autoptr (GDateTime) now;
-  GtdManager *manager;
-  GList *tasklists;
-  GList *l;
-  guint number_of_tasks;
-
-  now = g_date_time_new_now_local ();
-  manager = gtd_manager_get_default ();
-  tasklists = gtd_manager_get_task_lists (manager);
-  number_of_tasks = 0;
-
-  g_list_store_remove_all (panel->model);
-
-  /* Recount tasks */
-  for (l = tasklists; l != NULL; l = l->next)
-    {
-      guint i;
-
-      for (i = 0; i < g_list_model_get_n_items (l->data); i++)
-        {
-          g_autoptr (GDateTime) task_dt = NULL;
-          GtdTask *task;
+  g_autoptr (GDateTime) task_dt = NULL;
+  GtdTask *task;
 
-          task = g_list_model_get_item (l->data, i);
-          task_dt = gtd_task_get_due_date (task);
+  task = (GtdTask*) object;
+  task_dt = gtd_task_get_due_date (task);
 
-          if (gtd_task_get_complete (task) || !task_dt)
-            continue;
+  return !gtd_task_get_complete (task) && task_dt != NULL;
+}
 
-          g_list_store_insert_sorted (panel->model, task, sort_func, NULL);
+static void
+on_model_items_changed_cb (GListModel        *model,
+                           guint              position,
+                           guint              n_removed,
+                           guint              n_added,
+                           GtdPanelScheduled *self)
+{
+  if (self->number_of_tasks == g_list_model_get_n_items (model))
+    return;
 
-          number_of_tasks++;
-        }
-    }
+  self->number_of_tasks = g_list_model_get_n_items (model);
+  g_object_notify (G_OBJECT (self), "subtitle");
+}
 
-  /* Add the tasks to the view */
-  gtd_task_list_view_set_default_date (GTD_TASK_LIST_VIEW (panel->view), now);
+static void
+on_timer_updated_cb (GtdTimer          *timer,
+                     GtdPanelScheduled *self)
+{
+  g_autoptr (GDateTime) now = NULL;
 
-  if (number_of_tasks != panel->number_of_tasks)
-    {
-      panel->number_of_tasks = number_of_tasks;
-      g_object_notify (G_OBJECT (panel), "subtitle");
-    }
+  now = g_date_time_new_now_local ();
+  gtd_task_list_view_set_default_date (self->view, now);
 
-  g_list_free (tasklists);
+  gtd_list_model_filter_invalidate (self->filter_model);
 }
 
+
 /**********************
  * GtdPanel iface init
  **********************/
@@ -401,7 +393,8 @@ gtd_panel_scheduled_finalize (GObject *object)
   GtdPanelScheduled *self = (GtdPanelScheduled *)object;
 
   g_clear_object (&self->icon);
-  g_clear_object (&self->model);
+  g_clear_object (&self->filter_model);
+  g_clear_object (&self->sort_model);
 
   G_OBJECT_CLASS (gtd_panel_scheduled_parent_class)->finalize (object);
 }
@@ -474,48 +467,42 @@ gtd_panel_scheduled_class_init (GtdPanelScheduledClass *klass)
 static void
 gtd_panel_scheduled_init (GtdPanelScheduled *self)
 {
-  GtdManager *manager;
+  GtdManager *manager = gtd_manager_get_default ();
 
   self->icon = g_themed_icon_new ("alarm-symbolic");
-  self->model = g_list_store_new (GTD_TYPE_TASK);
-
-  /* Connect to GtdManager::list-* signals to update the title */
-  manager = gtd_manager_get_default ();
 
-  g_signal_connect_swapped (manager,
-                            "list-added",
-                            G_CALLBACK (gtd_panel_scheduled_count_tasks),
-                            self);
+  self->filter_model = gtd_list_model_filter_new (gtd_manager_get_tasks_model (manager));
+  gtd_list_model_filter_set_filter_func (self->filter_model, filter_func, self, NULL);
 
-  g_signal_connect_swapped (manager,
-                            "list-removed",
-                            G_CALLBACK (gtd_panel_scheduled_count_tasks),
-                            self);
-
-  g_signal_connect_swapped (manager,
-                            "list-changed",
-                            G_CALLBACK (gtd_panel_scheduled_count_tasks),
-                            self);
-
-  g_signal_connect_swapped (gtd_manager_get_timer (manager),
-                            "update",
-                            G_CALLBACK (gtd_panel_scheduled_count_tasks),
-                            self);
+  self->sort_model = gtd_list_model_sort_new (G_LIST_MODEL (self->filter_model));
+  gtd_list_model_sort_set_sort_func (self->sort_model, sort_func, self, NULL);
 
   /* The main view */
-  self->view = gtd_task_list_view_new ();
-  gtd_task_list_view_set_model (GTD_TASK_LIST_VIEW (self->view), G_LIST_MODEL (self->model));
-  gtd_task_list_view_set_handle_subtasks (GTD_TASK_LIST_VIEW (self->view), FALSE);
-  gtd_task_list_view_set_show_list_name (GTD_TASK_LIST_VIEW (self->view), TRUE);
-  gtd_task_list_view_set_show_due_date (GTD_TASK_LIST_VIEW (self->view), FALSE);
+  self->view = GTD_TASK_LIST_VIEW (gtd_task_list_view_new ());
+  gtd_task_list_view_set_model (self->view, G_LIST_MODEL (self->sort_model));
+  gtd_task_list_view_set_handle_subtasks (self->view, FALSE);
+  gtd_task_list_view_set_show_list_name (self->view, TRUE);
+  gtd_task_list_view_set_show_due_date (self->view, FALSE);
 
-  gtk_widget_set_hexpand (self->view, TRUE);
-  gtk_widget_set_vexpand (self->view, TRUE);
-  gtk_container_add (GTK_CONTAINER (self), self->view);
+  gtk_widget_set_hexpand (GTK_WIDGET (self->view), TRUE);
+  gtk_widget_set_vexpand (GTK_WIDGET (self->view), TRUE);
+  gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->view));
 
-  gtd_task_list_view_set_header_func (GTD_TASK_LIST_VIEW (self->view),
+  gtd_task_list_view_set_header_func (self->view,
                                       (GtdTaskListViewHeaderFunc) header_func,
                                       self);
+
+  g_signal_connect_object (self->sort_model,
+                           "items-changed",
+                           G_CALLBACK (on_model_items_changed_cb),
+                           self,
+                           0);
+
+  g_signal_connect_object (gtd_manager_get_timer (manager),
+                           "update",
+                           G_CALLBACK (on_timer_updated_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
 }
 
 GtkWidget*
diff --git a/plugins/today-panel/gtd-panel-today.c b/plugins/today-panel/gtd-panel-today.c
index 7d97899..444d8f3 100644
--- a/plugins/today-panel/gtd-panel-today.c
+++ b/plugins/today-panel/gtd-panel-today.c
@@ -27,14 +27,15 @@ struct _GtdPanelToday
 {
   GtkBox              parent;
 
-  GtkWidget          *view;
   GIcon              *icon;
 
-  GListStore         *model;
-
   gint                day_change_callback_id;
 
   guint               number_of_tasks;
+  GtdTaskListView    *view;
+
+  GtdListModelFilter *filter_model;
+  GtdListModelSort   *sort_model;
 };
 
 static void          gtd_panel_iface_init                        (GtdPanelInterface  *iface);
@@ -105,9 +106,9 @@ should_be_added (GDateTime *today,
 }
 
 static gint
-sort_func (gconstpointer a,
-           gconstpointer b,
-           gpointer      user_data)
+sort_func (GObject  *a,
+           GObject  *b,
+           gpointer  user_data)
 {
   g_autoptr (GDateTime) dt1 = NULL;
   g_autoptr (GDateTime) dt2 = NULL;
@@ -142,56 +143,6 @@ sort_func (gconstpointer a,
   return gtd_task_compare (task1, task2);
 }
 
-static void
-update_tasks (GtdPanelToday *panel)
-{
-  g_autoptr (GDateTime) now = NULL;
-  g_autoptr (GList) tasklists = NULL;
-  GtdManager *manager;
-  GList *l;
-  guint number_of_tasks;
-
-  now = g_date_time_new_now_local ();
-  manager = gtd_manager_get_default ();
-  tasklists = gtd_manager_get_task_lists (manager);
-  number_of_tasks = 0;
-
-  g_list_store_remove_all (panel->model);
-
-  /* Recount tasks */
-  for (l = tasklists; l != NULL; l = l->next)
-    {
-      guint i;
-
-      for (i = 0; i < g_list_model_get_n_items (l->data); i++)
-        {
-          g_autoptr (GDateTime) task_dt = NULL;
-          GtdTask *task;
-
-          task = g_list_model_get_item (l->data, i);
-          task_dt = gtd_task_get_due_date (task);
-
-          /* Ignore completed tasks, and tasks in the future */
-          if (gtd_task_get_complete (task) || !should_be_added (now, task_dt))
-            continue;
-
-          g_list_store_insert_sorted (panel->model, task, sort_func, NULL);
-
-          if (!gtd_task_get_complete (task))
-            number_of_tasks++;
-        }
-    }
-
-  /* Add the tasks to the view */
-  gtd_task_list_view_set_default_date (GTD_TASK_LIST_VIEW (panel->view), now);
-
-  if (number_of_tasks != panel->number_of_tasks)
-    {
-      panel->number_of_tasks = number_of_tasks;
-      g_object_notify (G_OBJECT (panel), "subtitle");
-    }
-}
-
 static GtkWidget*
 create_label (const gchar *text,
               gboolean     overdue)
@@ -249,12 +200,48 @@ header_func (GtdTask  *task,
  * Callbacks
  */
 
+static gboolean
+filter_func (GObject  *object,
+             gpointer  user_data)
+{
+  g_autoptr (GDateTime) task_dt = NULL;
+  g_autoptr (GDateTime) now = NULL;
+  GtdTask *task;
+
+  task = (GtdTask*) object;
+  now = g_date_time_new_now_local ();
+  task_dt = gtd_task_get_due_date (task);
+
+  return !gtd_task_get_complete (task) && should_be_added (now, task_dt);
+}
+
+static void
+on_model_items_changed_cb (GListModel    *model,
+                           guint          position,
+                           guint          n_removed,
+                           guint          n_added,
+                           GtdPanelToday *self)
+{
+  if (self->number_of_tasks == g_list_model_get_n_items (model))
+    return;
+
+  self->number_of_tasks = g_list_model_get_n_items (model);
+  g_object_notify (G_OBJECT (self), "subtitle");
+}
+
 static void
-on_manager_task_list_changed_cb (GtdPanelToday *self)
+on_timer_updated_cb (GtdTimer      *timer,
+                     GtdPanelToday *self)
 {
-  update_tasks (self);
+  g_autoptr (GDateTime) now = NULL;
+
+  now = g_date_time_new_now_local ();
+  gtd_task_list_view_set_default_date (self->view, now);
+
+  gtd_list_model_filter_invalidate (self->filter_model);
 }
 
+
 /*
  * GtdPanel iface
  */
@@ -321,7 +308,8 @@ gtd_panel_today_finalize (GObject *object)
   GtdPanelToday *self = (GtdPanelToday *)object;
 
   g_clear_object (&self->icon);
-  g_clear_object (&self->model);
+  g_clear_object (&self->filter_model);
+  g_clear_object (&self->sort_model);
 
   G_OBJECT_CLASS (gtd_panel_today_parent_class)->finalize (object);
 }
@@ -397,48 +385,43 @@ gtd_panel_today_init (GtdPanelToday *self)
   g_autoptr (GDateTime) now = NULL;
   GtdManager *manager;
 
+  manager = gtd_manager_get_default ();
+
   self->icon = g_themed_icon_new ("view-tasks-today-symbolic");
-  self->model = g_list_store_new (GTD_TYPE_TASK);
+
+  self->filter_model = gtd_list_model_filter_new (gtd_manager_get_tasks_model (manager));
+  gtd_list_model_filter_set_filter_func (self->filter_model, filter_func, self, NULL);
+
+  self->sort_model = gtd_list_model_sort_new (G_LIST_MODEL (self->filter_model));
+  gtd_list_model_sort_set_sort_func (self->sort_model, sort_func, self, NULL);
 
   /* Connect to GtdManager::list-* signals to update the title */
   manager = gtd_manager_get_default ();
   now = g_date_time_new_now_local ();
 
-  g_signal_connect_object (manager,
-                           "list-added",
-                           G_CALLBACK (on_manager_task_list_changed_cb),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-  g_signal_connect_object (manager,
-                           "list-removed",
-                           G_CALLBACK (on_manager_task_list_changed_cb),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-  g_signal_connect_object (manager,
-                           "list-changed",
-                           G_CALLBACK (on_manager_task_list_changed_cb),
+  /* The main view */
+  self->view = GTD_TASK_LIST_VIEW (gtd_task_list_view_new ());
+  gtd_task_list_view_set_model (self->view, G_LIST_MODEL (self->sort_model));
+  gtd_task_list_view_set_handle_subtasks (self->view, FALSE);
+  gtd_task_list_view_set_show_list_name (self->view, TRUE);
+  gtd_task_list_view_set_show_due_date (self->view, FALSE);
+  gtd_task_list_view_set_default_date (self->view, FALSE);
+
+  gtk_widget_set_hexpand (GTK_WIDGET (self->view), TRUE);
+  gtk_widget_set_vexpand (GTK_WIDGET (self->view), TRUE);
+  gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->view));
+
+  gtd_task_list_view_set_header_func (self->view, header_func, self);
+
+  g_signal_connect_object (self->sort_model,
+                           "items-changed",
+                           G_CALLBACK (on_model_items_changed_cb),
                            self,
-                           G_CONNECT_SWAPPED);
+                           0);
 
-  /* The main view */
-  self->view = gtd_task_list_view_new ();
-  gtd_task_list_view_set_model (GTD_TASK_LIST_VIEW (self->view), G_LIST_MODEL (self->model));
-  gtd_task_list_view_set_handle_subtasks (GTD_TASK_LIST_VIEW (self->view), FALSE);
-  gtd_task_list_view_set_show_list_name (GTD_TASK_LIST_VIEW (self->view), TRUE);
-  gtd_task_list_view_set_show_due_date (GTD_TASK_LIST_VIEW (self->view), FALSE);
-  gtd_task_list_view_set_default_date (GTD_TASK_LIST_VIEW (self->view), now);
-  gtd_task_list_view_set_header_func (GTD_TASK_LIST_VIEW (self->view), header_func, self);
-
-  gtk_widget_set_hexpand (self->view, TRUE);
-  gtk_widget_set_vexpand (self->view, TRUE);
-  gtk_container_add (GTK_CONTAINER (self), self->view);
-
-  /* Start timer */
   g_signal_connect_object (gtd_manager_get_timer (manager),
                            "update",
-                           G_CALLBACK (on_manager_task_list_changed_cb),
+                           G_CALLBACK (on_timer_updated_cb),
                            self,
                            G_CONNECT_SWAPPED);
 }


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