[gnome-todo/wip/gbsneto/subtasks] task: add ::complete-percentage property and API



commit d6a525f0ba4c5dc8ba43a1eb73f4cd65f6093108
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Thu Oct 20 16:59:28 2016 -0200

    task: add ::complete-percentage property and API

 src/gtd-task.c |   97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gtd-task.h |    2 +
 2 files changed, 99 insertions(+), 0 deletions(-)
---
diff --git a/src/gtd-task.c b/src/gtd-task.c
index a06e4da..e3452ac 100644
--- a/src/gtd-task.c
+++ b/src/gtd-task.c
@@ -43,6 +43,7 @@ typedef struct
   GtdTask         *parent;
   GList           *subtasks;
   gint             depth;
+  gfloat           complete_percentage;
 } GtdTaskPrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtdTask, gtd_task, GTD_TYPE_OBJECT)
@@ -51,6 +52,7 @@ enum
 {
   PROP_0,
   PROP_COMPLETE,
+  PROP_COMPLETE_PERCENTAGE,
   PROP_COMPONENT,
   PROP_DEPTH,
   PROP_DESCRIPTION,
@@ -72,6 +74,50 @@ enum
 
 static guint signals[N_SIGNALS] = { 0, };
 
+static void
+update_complete_percentage (GtdTask *self)
+{
+  GtdTaskPrivate *priv;
+  GList *l;
+  gfloat total_completion;
+  gint number_of_tasks;
+
+  priv = gtd_task_get_instance_private (self);
+  total_completion = 0;
+  number_of_tasks = 1;
+
+  /* Leaf task */
+  if (!priv->subtasks)
+    {
+      priv->complete_percentage = gtd_task_get_complete (self);
+      g_object_notify (G_OBJECT (self), "complete-percentage");
+      return;
+    }
+
+  for (l = priv->subtasks; l != NULL; l = l->next)
+    {
+      GtdTaskPrivate *subtask_priv;
+
+      subtask_priv = gtd_task_get_instance_private (l->data);
+
+      /* Update the subtask percentage first */
+      update_complete_percentage (l->data);
+
+      number_of_tasks++;
+      total_completion += subtask_priv->complete_percentage;
+    }
+
+  total_completion += gtd_task_get_complete (self);
+  total_completion = total_completion / number_of_tasks;
+
+  /* No need to notify anything when the value didn't change */
+  if (total_completion == priv->complete_percentage)
+    return;
+
+  priv->complete_percentage = total_completion;
+  g_object_notify (G_OBJECT (self), "complete-percentage");
+}
+
 static gboolean
 share_same_ancestor (GtdTask *t1,
                      GtdTask *t2)
@@ -252,6 +298,8 @@ real_add_subtask (GtdTask *self,
   /* And also the task's depth */
   set_depth (subtask, priv->depth + 1);
 
+  update_complete_percentage (self);
+
   e_cal_component_free_id (id);
 }
 
@@ -288,6 +336,8 @@ real_remove_subtask (GtdTask *self,
 
   /* And also the task's depth */
   set_depth (subtask, 0);
+
+  update_complete_percentage (self);
 }
 
 static void
@@ -355,6 +405,10 @@ gtd_task_get_property (GObject    *object,
       g_value_set_boolean (value, gtd_task_get_complete (self));
       break;
 
+    case PROP_COMPLETE_PERCENTAGE:
+      g_value_set_float (value, priv->complete_percentage);
+      break;
+
     case PROP_COMPONENT:
       g_value_set_object (value, priv->component);
       break;
@@ -483,6 +537,22 @@ gtd_task_class_init (GtdTaskClass *klass)
                               G_PARAM_READWRITE));
 
   /**
+   * GtdTask::complete-percentage:
+   *
+   * The percentage of completenes of this task.
+   */
+  g_object_class_install_property (
+        object_class,
+        PROP_COMPLETE_PERCENTAGE,
+        g_param_spec_float ("complete-percentage",
+                            "Percentage of completeness",
+                            "The percentage of completeness",
+                            0.0,
+                            1.0,
+                            0.0,
+                            G_PARAM_READABLE));
+
+  /**
    * GtdTask::component:
    *
    * The #ECalComponent of the task.
@@ -788,6 +858,12 @@ gtd_task_set_complete (GtdTask  *task,
       if (dt)
         e_cal_component_free_icaltimetype (dt);
 
+      /*
+       * By updating the percentage of the root task, it'll run recursively until
+       * eventually reaching this task.
+       */
+      update_complete_percentage (get_root_task (task));
+
       g_object_notify (G_OBJECT (task), "complete");
     }
 }
@@ -1514,3 +1590,24 @@ gtd_task_get_depth (GtdTask *self)
 
   return priv->depth;
 }
+
+/**
+ * gtd_task_get_complete_percentage:
+ * @self: a #GtdTask
+ *
+ * Retireves the percentage of completeness of @self. This value depends
+ * on the number of subtasks completed.
+ *
+ * Returns: a number between %0 and %1.
+ */
+gfloat
+gtd_task_get_complete_percentage (GtdTask *self)
+{
+  GtdTaskPrivate *priv;
+
+  g_return_val_if_fail (GTD_IS_TASK (self), 0);
+
+  priv = gtd_task_get_instance_private (self);
+
+  return priv->complete_percentage;
+}
diff --git a/src/gtd-task.h b/src/gtd-task.h
index 4dfb710..6e2f7b5 100644
--- a/src/gtd-task.h
+++ b/src/gtd-task.h
@@ -102,6 +102,8 @@ gboolean            gtd_task_is_subtask               (GtdTask              *sel
 
 gint                gtd_task_get_depth                (GtdTask              *self);
 
+gfloat              gtd_task_get_complete_percentage  (GtdTask              *self);
+
 G_END_DECLS
 
 #endif /* GTD_TASK_H */


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