[gnome-todo/wip/gbsneto/subtasks: 5/27] task: add subtask support
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-todo/wip/gbsneto/subtasks: 5/27] task: add subtask support
- Date: Fri, 14 Oct 2016 14:41:34 +0000 (UTC)
commit 5f4590a2bbdb5d4ef34c39d289da520909286674
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Fri Jul 8 11:26:18 2016 -0300
task: add subtask support
Subtask is a very important feature of a To Do manager,
and supported by the iCalendar protocol.
This commit, then, is a preparation for the feature and
adds backend support for subtasks.
src/gtd-task.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/gtd-task.h | 19 +++++-
2 files changed, 242 insertions(+), 1 deletions(-)
---
diff --git a/src/gtd-task.c b/src/gtd-task.c
index d1dac7a..c9ed3e9 100644
--- a/src/gtd-task.c
+++ b/src/gtd-task.c
@@ -40,6 +40,8 @@ typedef struct
gchar *description;
GtdTaskList *list;
ECalComponent *component;
+ GtdTask *parent;
+ GList *subtasks;
} GtdTaskPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GtdTask, gtd_task, GTD_TYPE_OBJECT)
@@ -53,11 +55,21 @@ enum
PROP_CREATION_DATE,
PROP_DUE_DATE,
PROP_LIST,
+ PROP_PARENT,
PROP_PRIORITY,
PROP_TITLE,
LAST_PROP
};
+enum
+{
+ SUBTASK_ADDED,
+ SUBTASK_REMOVED,
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS] = { 0, };
+
static GDateTime*
gtd_task__convert_icaltime (const icaltimetype *date)
{
@@ -77,6 +89,75 @@ gtd_task__convert_icaltime (const icaltimetype *date)
}
static void
+real_add_subtask (GtdTask *self,
+ GtdTask *subtask)
+{
+ GtdTaskPrivate *priv, *subtask_priv;
+ ECalComponentId *id;
+ ECalComponent *comp;
+ icalcomponent *ical_comp;
+ icalproperty *property;
+
+ priv = gtd_task_get_instance_private (self);
+
+ if (g_list_find (priv->subtasks, subtask))
+ return;
+
+ id = e_cal_component_get_id (priv->component);
+ subtask_priv = gtd_task_get_instance_private (subtask);
+ comp = subtask_priv->component;
+
+ ical_comp = e_cal_component_get_icalcomponent (comp);
+ property = icalcomponent_get_first_property (ical_comp, ICAL_RELATEDTO_PROPERTY);
+
+ if (property)
+ icalproperty_set_relatedto (property, id->uid);
+ else
+ icalcomponent_add_property (ical_comp, icalproperty_new_relatedto (id->uid));
+
+ /* Add to this task's list of subtasks */
+ priv->subtasks = g_list_prepend (priv->subtasks, subtask);
+
+ /* Update the subtask's parent property */
+ subtask_priv->parent = self;
+ g_object_notify (G_OBJECT (subtask), "parent");
+
+ e_cal_component_free_id (id);
+}
+
+static void
+real_remove_subtask (GtdTask *self,
+ GtdTask *subtask)
+{
+ GtdTaskPrivate *priv, *subtask_priv;
+ icalcomponent *ical_comp;
+ icalproperty *property;
+
+ priv = gtd_task_get_instance_private (self);
+
+ if (!g_list_find (priv->subtasks, subtask))
+ return;
+
+ subtask_priv = gtd_task_get_instance_private (subtask);
+
+ /* Remove the parent link from the subtask's component */
+ ical_comp = e_cal_component_get_icalcomponent (subtask_priv->component);
+ property = icalcomponent_get_first_property (ical_comp, ICAL_RELATEDTO_PROPERTY);
+
+ if (!property)
+ return;
+
+ icalcomponent_remove_property (ical_comp, property);
+
+ /* Add to this task's list of subtasks */
+ priv->subtasks = g_list_remove (priv->subtasks, subtask);
+
+ /* Update the subtask's parent property */
+ subtask_priv->parent = NULL;
+ g_object_notify (G_OBJECT (subtask), "parent");
+}
+
+static void
gtd_task_finalize (GObject *object)
{
GtdTask *self = (GtdTask*) object;
@@ -161,6 +242,10 @@ gtd_task_get_property (GObject *object,
g_value_set_object (value, priv->list);
break;
+ case PROP_PARENT:
+ g_value_set_object (value, priv->parent);
+ break;
+
case PROP_PRIORITY:
g_value_set_int (value, gtd_task_get_priority (self));
break;
@@ -235,6 +320,9 @@ gtd_task_class_init (GtdTaskClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtdObjectClass *obj_class = GTD_OBJECT_CLASS (klass);
+ klass->subtask_added = real_add_subtask;
+ klass->subtask_removed = real_remove_subtask;
+
object_class->finalize = gtd_task_finalize;
object_class->get_property = gtd_task_get_property;
object_class->set_property = gtd_task_set_property;
@@ -329,6 +417,20 @@ gtd_task_class_init (GtdTaskClass *klass)
G_PARAM_READWRITE));
/**
+ * GtdTask::parent:
+ *
+ * The parent of the task.
+ */
+ g_object_class_install_property (
+ object_class,
+ PROP_PARENT,
+ g_param_spec_object ("parent",
+ "Parent of the task",
+ "The GtdTask that is parent of this task.",
+ GTD_TYPE_TASK,
+ G_PARAM_READABLE));
+
+ /**
* GtdTask::priority:
*
* Priority of the task, 0 if not set.
@@ -357,6 +459,39 @@ gtd_task_class_init (GtdTaskClass *klass)
"The title of the task",
NULL,
G_PARAM_READWRITE));
+
+ /* Signals */
+ /**
+ * GtdTask:subtask-added:
+ *
+ * Emited when a subtask is added to @self.
+ */
+ signals[SUBTASK_ADDED] = g_signal_new ("subtask-added",
+ GTD_TYPE_TASK,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtdTaskClass, subtask_added),
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1,
+ GTD_TYPE_TASK);
+
+ /**
+ * GtdTask:subtask-added:
+ *
+ * Emited when a subtask is added to @self.
+ */
+ signals[SUBTASK_REMOVED] = g_signal_new ("subtask-removed",
+ GTD_TYPE_TASK,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtdTaskClass, subtask_removed),
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1,
+ GTD_TYPE_TASK);
}
static void
@@ -1055,3 +1190,92 @@ gtd_task_compare (GtdTask *t1,
return retval;
}
+
+/**
+ * gtd_task_get_parent:
+ * @self: a #GtdTask
+ *
+ * Retrieves the parent task of @self, or %NULL if none is set.
+ *
+ * Returns: (transfer none)(nullable): the #GtdTask that is parent of @self
+ */
+GtdTask*
+gtd_task_get_parent (GtdTask *self)
+{
+ GtdTaskPrivate *priv;
+
+ g_return_val_if_fail (GTD_IS_TASK (self), NULL);
+
+ priv = gtd_task_get_instance_private (self);
+
+ return priv->parent;
+}
+
+/**
+ * gtd_task_get_substasks:
+ * @self: a #GtdTask
+ *
+ * Retrieves the subtasks of @self, or %NULL if it has no subtasks.
+ *
+ * Returns: (transfer container)(nullable)(element-type Gtd.Task): the subtasks of @self
+ */
+GList*
+gtd_task_get_substasks (GtdTask *self)
+{
+ GtdTaskPrivate *priv;
+
+ g_return_val_if_fail (GTD_IS_TASK (self), NULL);
+
+ priv = gtd_task_get_instance_private (self);
+
+ return g_list_copy (priv->subtasks);
+}
+
+/**
+ * gtd_task_add_subtask:
+ * @self: a #GtdTask
+ * @subtask: the subtask to be added to @self
+ *
+ * Adds @subtask as a subtask of @self.
+ */
+void
+gtd_task_add_subtask (GtdTask *self,
+ GtdTask *subtask)
+{
+ GtdTaskPrivate *priv;
+
+ g_return_if_fail (GTD_IS_TASK (self));
+ g_return_if_fail (GTD_IS_TASK (subtask));
+
+ priv = gtd_task_get_instance_private (self);
+
+ if (!g_list_find (priv->subtasks, subtask))
+ {
+ g_signal_emit (self, signals[SUBTASK_ADDED], 0, subtask);
+ }
+}
+
+/**
+ * gtd_task_remove_subtask:
+ * @self: a #GtdTask
+ * @subtask: the subtask to be removed to @self
+ *
+ * Removes @subtask from @self.
+ */
+void
+gtd_task_remove_subtask (GtdTask *self,
+ GtdTask *subtask)
+{
+ GtdTaskPrivate *priv;
+
+ g_return_if_fail (GTD_IS_TASK (self));
+ g_return_if_fail (GTD_IS_TASK (subtask));
+
+ priv = gtd_task_get_instance_private (self);
+
+ if (g_list_find (priv->subtasks, subtask))
+ {
+ g_signal_emit (self, signals[SUBTASK_REMOVED], 0, subtask);
+ }
+}
+
diff --git a/src/gtd-task.h b/src/gtd-task.h
index eb8b76a..9846992 100644
--- a/src/gtd-task.h
+++ b/src/gtd-task.h
@@ -34,7 +34,14 @@ struct _GtdTaskClass
{
GtdObjectClass parent;
- gpointer padding[10];
+ /*< signals >*/
+ void (*subtask_added) (GtdTask *self,
+ GtdTask *subtask);
+
+ void (*subtask_removed) (GtdTask *self,
+ GtdTask *subtask);
+
+ gpointer padding[8];
};
GtdTask* gtd_task_new (ECalComponent *component);
@@ -80,6 +87,16 @@ void gtd_task_save (GtdTask *tas
gint gtd_task_compare (GtdTask *t1,
GtdTask *t2);
+GtdTask* gtd_task_get_parent (GtdTask *self);
+
+GList* gtd_task_get_substasks (GtdTask *self);
+
+void gtd_task_add_subtask (GtdTask *self,
+ GtdTask *subtask);
+
+void gtd_task_remove_subtask (GtdTask *self,
+ GtdTask *subtask);
+
G_END_DECLS
#endif /* GTD_TASK_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]