[gnome-todo/gnome-3-24] todo-txt: major rework on provider and parser



commit e1cded19fd5a5349f72e984bab9da8985b7f488b
Author: Rohit Kaushik <kaushikrohit325 gmail com>
Date:   Thu May 25 00:37:36 2017 +0530

    todo-txt: major rework on provider and parser
    
    Issues like creating task with many subtask and depth greater
    than 2 being not save properly has been fixed. Provider has
    been restructured and changes has been made according in the
    parser.
    
    Changes made:
       1) Remove custom structure TaskData from parser.
       2) parse_tokens now return GtdTask directly.
       3) Provider cache the lists so that updating the source
          is easier.
       4) Monitor reloads the tasks/lists only when todo.txt file
          has been altered from outside.This is fixed using a dummy
          should_reload flag.
       5) Parser now makes use of GString that can grow, rather than
          using g_strconcat.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=781079

 plugins/todo-txt/gtd-provider-todo-txt.c |  899 +++++++-----------------------
 plugins/todo-txt/gtd-provider-todo-txt.h |    2 +
 plugins/todo-txt/gtd-todo-txt-parser.c   |  300 ++++-------
 plugins/todo-txt/gtd-todo-txt-parser.h   |   23 +-
 4 files changed, 322 insertions(+), 902 deletions(-)
---
diff --git a/plugins/todo-txt/gtd-provider-todo-txt.c b/plugins/todo-txt/gtd-provider-todo-txt.c
index 7e707e2..e478648 100644
--- a/plugins/todo-txt/gtd-provider-todo-txt.c
+++ b/plugins/todo-txt/gtd-provider-todo-txt.c
@@ -19,8 +19,6 @@
 #include "gtd-provider-todo-txt.h"
 #include "gtd-plugin-todo-txt.h"
 #include "gtd-todo-txt-parser.h"
-#include "gtd-task-list.h"
-#include "gtd-task.h"
 #include <string.h>
 #include <stdlib.h>
 
@@ -34,14 +32,14 @@ struct _GtdProviderTodoTxt
   GIcon              *icon;
 
   GHashTable         *lists;
-  GHashTable         *root_tasks;
+  GHashTable         *tasks;
 
   GFileMonitor       *monitor;
   GFile              *source_file;
 
-  GList              *tasklists;
-
-  gint                no_of_lines;
+  GList              *task_lists;
+  GPtrArray          *cache;
+  gboolean            should_reload;
 };
 
 static void          gtd_provider_iface_init                     (GtdProviderInterface *iface);
@@ -106,22 +104,6 @@ gtd_provider_todo_txt_get_edit_panel (GtdProvider *provider)
   return NULL;
 }
 
-static GtdTask*
-gtd_provider_todo_txt_create_new_task (void)
-{
-  ECalComponent *component;
-  GtdTask *task;
-
-  component = e_cal_component_new ();
-
-  e_cal_component_set_new_vtype (component, E_CAL_COMPONENT_TODO);
-  e_cal_component_set_uid (component, e_cal_component_gen_uid ());
-
-  task = gtd_task_new (component);
-
-  return task;
-}
-
 static void
 emit_generic_error (GError *error)
 {
@@ -136,157 +118,127 @@ emit_generic_error (GError *error)
 }
 
 static void
-gtd_provider_todo_txt_load_task (TaskData           *td,
-                                 GtdProviderTodoTxt *self,
-                                 gint                line_number)
+update_source (GtdProviderTodoTxt *self)
 {
-  GtdTaskList *task_list = NULL;
-
-  gchar *task_list_name;
-  gchar *root_task_name;
-  gchar *title;
-
-  GDateTime    *due_date;
 
-  gboolean  is_subtask;
-  gboolean  is_task_completed;
-  gint      priority;
-
-  task_list_name = gtd_todo_txt_parser_task_data_get_task_list_name (td);
-  root_task_name = gtd_todo_txt_parser_task_data_get_root_task_name (td);
-  title = gtd_todo_txt_parser_task_data_get_title (td);
-  due_date = gtd_todo_txt_parser_task_data_get_due_date (td);
-  is_subtask = gtd_todo_txt_parser_task_data_is_subtask (td);
-  is_task_completed = gtd_todo_txt_parser_task_data_is_task_completed (td);
-  priority = gtd_todo_txt_parser_task_data_get_priority (td);
-
-  if (is_subtask)
+  GFileOutputStream *write_stream;
+  GDataOutputStream *writer;
+  GtdTaskList *list;
+  GError *error;
+  GList *tasks, *l;
+  guint i;
+
+  error = NULL;
+  tasks = NULL;
+  l = NULL;
+  self->should_reload = FALSE;
+
+  write_stream = g_file_replace (self->source_file,
+                                 NULL,
+                                 TRUE,
+                                 G_FILE_CREATE_NONE,
+                                 NULL,
+                                 &error);
+  if (error)
     {
-      GtdTask *root_task;
-      GtdTask *sub_task;
-
-      if (g_hash_table_contains (self->lists, task_list_name))
-        {
-          task_list = g_hash_table_lookup (self->lists, task_list_name);
-        }
-      else
-        {
-          task_list = gtd_task_list_new (GTD_PROVIDER (self));
-          gtd_task_list_set_is_removable (task_list, TRUE);
-
-          gtd_task_list_set_name (task_list, task_list_name);
-          self->tasklists = g_list_append (self->tasklists,
-                                           task_list);
-
-          g_object_set_data (G_OBJECT (task_list), "line", task_list_name);
-
-          g_signal_emit_by_name (self, "list-added", task_list);
-          g_hash_table_insert (self->lists, task_list_name, task_list);
-        }
-
-      if (g_hash_table_contains (self->root_tasks, root_task_name))
-        {
-          root_task = g_hash_table_lookup (self->root_tasks, root_task_name);
-        }
-      else
-        {
-          root_task = gtd_provider_todo_txt_create_new_task ();
-
-          gtd_task_set_title (root_task, root_task_name);
-          gtd_task_set_list  (root_task, task_list);
-          gtd_task_list_save_task (task_list, root_task);
+      emit_generic_error (error);
+      g_error_free (error);
+      return;
+    }
 
-          g_hash_table_insert (self->root_tasks, root_task_name, root_task);
-        }
+  writer = g_data_output_stream_new (G_OUTPUT_STREAM (write_stream));
 
-      sub_task = gtd_provider_todo_txt_create_new_task ();
+  for (i = 0; i < self->cache->len; i++)
+    {
+      gchar *list_line;
+      list = g_ptr_array_index (self->cache, i);
 
-      gtd_task_set_title (sub_task, title);
-      gtd_task_set_list (sub_task, task_list);
-      gtd_task_set_priority (sub_task, priority);
-      gtd_task_set_complete (sub_task, is_task_completed);
-      gtd_task_set_due_date (sub_task, due_date);
+      tasks = gtd_task_list_get_tasks (list);
+      tasks = g_list_sort (tasks, (GCompareFunc) gtd_task_compare);
 
-      g_object_set_data (G_OBJECT (sub_task), "line", GINT_TO_POINTER (line_number));
+      list_line = gtd_todo_txt_parser_serialize_list (list);
 
-      gtd_task_add_subtask (root_task, sub_task);
-      gtd_task_list_save_task (task_list, sub_task);
-    }
-  else
-    {
-      GtdTask *task;
+      g_data_output_stream_put_string (writer,
+                                       list_line,
+                                       NULL,
+                                       NULL);
 
-      if (g_hash_table_contains (self->lists, task_list_name))
+      for (l = tasks; l != NULL; l = l->next)
         {
-          task_list = g_hash_table_lookup (self->lists, task_list_name);
-        }
-      else
-        {
-          task_list = gtd_task_list_new (GTD_PROVIDER (self));
-          gtd_task_list_set_is_removable (task_list, TRUE);
+          gchar *task_line;
 
-          gtd_task_list_set_name (task_list, task_list_name);
-          self->tasklists = g_list_append (self->tasklists,
-                                           task_list);
+          task_line = gtd_todo_txt_parser_serialize_task (l->data);
 
-          g_object_set_data (G_OBJECT (task_list), "line", task_list_name);
+          g_data_output_stream_put_string (writer,
+                                           task_line,
+                                           NULL,
+                                           NULL);
 
-          g_signal_emit_by_name (self, "list-added", task_list);
-          g_hash_table_insert (self->lists, task_list_name, task_list);
+          g_free (task_line);
         }
-      task = gtd_provider_todo_txt_create_new_task ();
-
-      gtd_task_set_title (task, title);
-      gtd_task_set_list (task, task_list);
-      gtd_task_set_priority (task, priority);
-      gtd_task_set_complete (task, is_task_completed);
-      gtd_task_set_due_date (task, due_date);
-
-      g_object_set_data (G_OBJECT (task), "line", GINT_TO_POINTER (line_number));
 
-      gtd_task_list_save_task (task_list, task);
-      g_hash_table_insert (self->root_tasks, title, task);
+      g_free (list_line);
     }
+
+  g_output_stream_close (G_OUTPUT_STREAM (writer), NULL, NULL);
+  g_output_stream_close (G_OUTPUT_STREAM (write_stream), NULL, NULL);
 }
 
-static void
-gtd_provider_todo_txt_create_empty_list (GtdProviderTodoTxt *self,
-                                         gchar              *name)
+static GtdTaskList*
+create_list (GtdProviderTodoTxt *self,
+             gchar              *name)
 {
   GtdTaskList *task_list;
 
   if (g_hash_table_contains (self->lists, name))
-    return;
+    return g_hash_table_lookup (self->lists, name);
 
   task_list = gtd_task_list_new (GTD_PROVIDER (self));
   gtd_task_list_set_is_removable (task_list, TRUE);
-
+  g_ptr_array_add (self->cache, task_list);
+  g_hash_table_insert (self->lists, g_strdup (name), task_list);
   gtd_task_list_set_name (task_list, name);
-  self->tasklists = g_list_append (self->tasklists, task_list);
-  g_object_set_data (G_OBJECT (task_list), "line", name);
+  self->task_lists = g_list_append (self->task_lists, task_list);
 
-  g_signal_emit_by_name (self, "list-added", task_list);
-  g_hash_table_insert (self->lists, name, task_list);
+  return task_list;
+}
+
+GtdTask*
+create_task (void)
+{
+  ECalComponent *component;
+  GtdTask *task;
+
+  component = e_cal_component_new ();
+
+  e_cal_component_set_new_vtype (component, E_CAL_COMPONENT_TODO);
+  e_cal_component_set_uid (component, e_cal_component_gen_uid ());
+
+  task = gtd_task_new (component);
+
+  return task;
 }
 
 static void
-gtd_provider_todo_txt_load_source (GtdProviderTodoTxt *self)
+gtd_provider_todo_txt_load_tasks (GtdProviderTodoTxt *self)
 {
   GFileInputStream *readstream;
   GDataInputStream *reader;
-  TaskData *td;
-  GError *line_read_error;
+  GtdTaskList *list;
+  GtdTask *parent_task;
+  GtdTask *task;
   GError *error;
-  gint line_number = 0;
+  GList *tokens;
+  gboolean valid;
   gchar *line_read;
+  gchar *list_name;
+  gchar *root_task_name;
 
   g_return_if_fail (G_IS_FILE (self->source_file));
 
-  td = NULL;
-  error = line_read_error = NULL;
-  readstream = g_file_read (self->source_file,
-                            NULL,
-                            &error);
+  tokens = NULL;
+  error = NULL;
+  readstream = g_file_read (self->source_file, NULL, &error);
 
   if (error)
     {
@@ -297,55 +249,119 @@ gtd_provider_todo_txt_load_source (GtdProviderTodoTxt *self)
 
 
   reader = g_data_input_stream_new (G_INPUT_STREAM (readstream));
-  self->no_of_lines = 0;
 
-  while (!line_read_error)
+  while (!error)
     {
-      GList *tokens = NULL;
-      gboolean valid;
-
-      line_read = g_data_input_stream_read_line (reader,
-                                                 NULL,
-                                                 NULL,
-                                                 &line_read_error);
+      line_read = g_data_input_stream_read_line (reader, NULL, NULL, &error);
 
-      if (line_read_error)
+      if (error)
         {
           g_warning ("%s: %s: %s",
                      G_STRFUNC,
                      _("Error while reading a line from Todo.txt"),
-                     line_read_error->message);
+                     error->message);
 
           gtd_manager_emit_error_message (gtd_manager_get_default (),
                                           _("Error while reading a line from Todo.txt"),
-                                          line_read_error->message);
-          g_error_free (line_read_error);
+                                          error->message);
+          g_error_free (error);
 
-          return;
+          continue;
         }
 
       if (!line_read)
         break;
 
-      line_number++;
-      self->no_of_lines++;
-
+      g_strstrip (line_read);
       tokens = gtd_todo_txt_parser_tokenize (line_read);
       valid = gtd_todo_txt_parser_validate_token_format (tokens);
 
       if (valid)
         {
-          td = gtd_todo_txt_parser_parse_tokens (tokens);
+          if (g_list_length (tokens) == 1)
+            {
+              list_name = &((gchar*)tokens->data)[0];
+              list_name++;
+              create_list (self, list_name);
+              continue;
+            }
+
+          task = gtd_todo_txt_parser_parse_tokens (tokens);
+          g_hash_table_insert (self->tasks, g_strdup (gtd_task_get_title (task)), task);
+          list = create_list (self, g_object_get_data (G_OBJECT (task), "list_name"));
+          gtd_task_set_list (task, list);
 
-          if (strcmp (gtd_todo_txt_parser_task_data_get_task_list_name (td), &(line_read[1])) == 0)
-            gtd_provider_todo_txt_create_empty_list (self, g_strdup (&(line_read[1])));
-          else
-            gtd_provider_todo_txt_load_task (td, self, line_number);
+          if (g_object_get_data (G_OBJECT (task), "root_task_name"))
+            {
+              root_task_name = g_object_get_data (G_OBJECT (task), "root_task_name");
+
+              if (g_hash_table_contains (self->tasks, root_task_name))
+                {
+                  parent_task =  g_hash_table_lookup (self->tasks, root_task_name);
+                }
+              else
+                {
+                  parent_task = create_task ();
+                  gtd_task_set_list (parent_task, list);
+                  gtd_task_set_title (parent_task, g_object_get_data (G_OBJECT (task), "root_task_name"));
+
+                  g_hash_table_insert (self->tasks, root_task_name, parent_task);
+                }
+
+              gtd_task_add_subtask (parent_task, task);
+              gtd_task_list_save_task (list, parent_task);
+            }
+
+          gtd_task_list_save_task (list, task);
         }
 
       g_list_free_full (tokens, g_free);
       g_free (line_read);
     }
+
+  g_input_stream_close (G_INPUT_STREAM (reader), NULL, NULL);
+  g_input_stream_close (G_INPUT_STREAM (readstream), NULL, NULL);
+}
+
+static void
+gtd_provider_todo_txt_reload (GFileMonitor       *monitor,
+                              GFile              *first,
+                              GFile              *second,
+                              GFileMonitorEvent   event,
+                              GtdProviderTodoTxt *self)
+{
+  GList *l;
+  guint i;
+
+  l = NULL;
+
+  if (!self->should_reload)
+    {
+      self->should_reload = TRUE;
+      return;
+    }
+
+  g_clear_pointer (&self->lists, g_hash_table_destroy);
+  g_clear_pointer (&self->tasks, g_hash_table_destroy);
+  g_ptr_array_free (self->cache, TRUE);
+
+  for (l = self->task_lists; l != NULL; l = l->next)
+    g_signal_emit_by_name (self, "list-removed", l->data);
+
+  g_list_free (self->task_lists);
+  self->task_lists = NULL;
+  self->lists = g_hash_table_new ((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal);
+  self->tasks = g_hash_table_new ((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal);
+  self->cache = g_ptr_array_new ();
+
+  gtd_provider_todo_txt_load_tasks (self);
+
+  for (i = 0; i < self->cache->len; i++)
+    {
+      GtdTaskList *list;
+      list = g_ptr_array_index (self->cache, i);
+      g_signal_emit_by_name (self, "list-added", list);
+    }
 }
 
 static void
@@ -366,6 +382,8 @@ gtd_provider_todo_txt_load_source_monitor (GtdProviderTodoTxt *self)
       g_clear_error (&error);
       return;
     }
+
+  g_signal_connect (self->monitor, "changed", G_CALLBACK (gtd_provider_todo_txt_reload), self);
 }
 
 static void
@@ -373,71 +391,13 @@ gtd_provider_todo_txt_create_task (GtdProvider *provider,
                                    GtdTask     *task)
 {
   GtdProviderTodoTxt *self;
-  GFileOutputStream *write_stream;
-  GDataOutputStream *writer;
-  GtdTaskList *list;
-  GError *write_error;
-  GError *error;
-  const gchar *list_name;
-  const gchar *task_description;
-  gchar *task_line;
 
   self = GTD_PROVIDER_TODO_TXT (provider);
-  error = write_error = NULL;
-
-  g_return_if_fail (G_IS_FILE (self->source_file));
-
-  list = gtd_task_get_list (task);
-  list_name = gtd_task_list_get_name (list);
-  task_description = gtd_task_get_title (task);
-
-  task_line = g_strconcat (task_description, " ", "@", list_name, "\n", NULL);
-
-  write_stream = g_file_append_to (self->source_file,
-                                  G_FILE_CREATE_REPLACE_DESTINATION,
-                                  NULL,
-                                  &error);
 
-  if (error)
-    {
-      emit_generic_error (error);
-      g_error_free (error);
-      return;
-    }
-
-  writer = g_data_output_stream_new (G_OUTPUT_STREAM (write_stream));
-
-  g_data_output_stream_put_string (writer,
-                                   task_line,
-                                   NULL,
-                                   &write_error);
-
-  if (write_error)
-    {
-      g_warning ("%s: %s: %s",
-                 G_STRFUNC,
-                 _("Error while adding a task to Todo.txt"),
-                 write_error->message);
+  g_return_if_fail (GTD_IS_TASK (task));
+  g_return_if_fail (GTD_IS_TASK_LIST (gtd_task_get_list (task)));
 
-      gtd_manager_emit_error_message (gtd_manager_get_default (),
-                                      _("Error while adding a task to Todo.txt"),
-                                      write_error->message);
-      g_error_free (write_error);
-
-      goto out;
-    }
-
-  g_hash_table_insert (self->root_tasks,
-                       (gpointer) task_description,
-                       task);
-  self->no_of_lines++;
-  g_object_set_data (G_OBJECT (task), "line", GINT_TO_POINTER (self->no_of_lines));
-
-  g_output_stream_close (G_OUTPUT_STREAM (writer),
-                         NULL,
-                         NULL);
-out:
-  g_free (task_line);
+  update_source (self);
 }
 
 static void
@@ -445,124 +405,14 @@ gtd_provider_todo_txt_update_task (GtdProvider *provider,
                                    GtdTask     *task)
 {
   GtdProviderTodoTxt *self;
-  GFileInputStream *readstream;
-  GFileOutputStream *outstream;
-  GDataOutputStream *writer;
-  GDataInputStream *reader;
-  GError *line_read_error;
-  GError *error;
-  GError *write_error;
-  gchar *line_read;
-  gint line_to_update;
-  gint line_number;
 
   self = GTD_PROVIDER_TODO_TXT (provider);
-  line_number = 0;
-  error = write_error = line_read_error = NULL;
-
-  line_to_update = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (task), "line"));
 
+  g_return_if_fail (GTD_IS_TASK (task));
+  g_return_if_fail (GTD_IS_TASK_LIST (gtd_task_get_list (task)));
   g_return_if_fail (G_IS_FILE (self->source_file));
 
-  readstream = g_file_read (self->source_file,
-                            NULL,
-                            &error);
-  outstream = g_file_replace (self->source_file,
-                              NULL,
-                              TRUE,
-                              G_FILE_CREATE_NONE,
-                              NULL,
-                              &error);
-
-  if (error)
-    {
-      emit_generic_error (error);
-      g_error_free (error);
-      return;
-    }
-
-  reader = g_data_input_stream_new (G_INPUT_STREAM (readstream));
-  writer = g_data_output_stream_new (G_OUTPUT_STREAM (outstream));
-
-  while (!line_read_error)
-    {
-      gboolean valid;
-      GList *tokens = NULL;
-
-      line_read = g_data_input_stream_read_line (reader,
-                                                 NULL,
-                                                 NULL,
-                                                 &line_read_error);
-
-      if (line_read_error)
-        {
-          g_warning ("%s: %s: %s",
-                     G_STRFUNC,
-                     _("Error while reading tasks from Todo.txt"),
-                     line_read_error->message);
-
-          gtd_manager_emit_error_message (gtd_manager_get_default (),
-                                          _("Error while reading tasks from Todo.txt"),
-                                          line_read_error->message);
-          g_error_free (line_read_error);
-        }
-
-      if (!line_read)
-        break;
-
-      line_number++;
-
-      tokens = gtd_todo_txt_parser_tokenize (line_read);
-      valid = gtd_todo_txt_parser_validate_token_format (tokens);
-
-      if (valid &&
-          line_number == line_to_update)
-        {
-          GList *update_tokens;
-          GList *it;
-
-          update_tokens = gtd_todo_txt_parser_get_task_line (task);
-          it = NULL;
-          for (it = update_tokens; it != NULL; it = it->next)
-            {
-              g_data_output_stream_put_string (writer,
-                                               it->data,
-                                               NULL,
-                                               &write_error);
-              if (it->next == NULL)
-                {
-                  g_data_output_stream_put_string (writer,
-                                                   "\n",
-                                                   NULL,
-                                                   &write_error);
-                }
-              else
-                g_data_output_stream_put_string (writer,
-                                                 " ",
-                                                 NULL,
-                                                 &write_error);
-            }
-
-          g_list_free_full (update_tokens, g_free);
-        }
-
-
-      else
-        {
-          line_read = strcat (line_read, "\n");
-
-          g_data_output_stream_put_string (writer,
-                                           line_read,
-                                           NULL,
-                                           &write_error);
-        }
-
-      g_list_free_full (tokens, g_free);
-    }
-
-  g_output_stream_close (G_OUTPUT_STREAM (writer),
-                         NULL,
-                         NULL);
+  update_source (self);
 }
 
 static void
@@ -570,107 +420,14 @@ gtd_provider_todo_txt_remove_task (GtdProvider *provider,
                                    GtdTask     *task)
 {
   GtdProviderTodoTxt *self;
-  GFileInputStream *readstream;
-  GFileOutputStream *outstream;
-  GDataOutputStream *writer;
-  GDataInputStream *reader;
-  GError *error;
-  GError *write_error;
-  GError *line_read_error;
-  gchar *line_read;
-  gboolean skip;
-  gint line_number;
-  gint line_number_to_remove;
 
   self = GTD_PROVIDER_TODO_TXT (provider);
-  error = write_error = line_read_error = NULL;
-  line_number = 0;
 
+  g_return_if_fail (GTD_IS_TASK (task));
+  g_return_if_fail (GTD_IS_TASK_LIST (gtd_task_get_list (task)));
   g_return_if_fail (G_IS_FILE (self->source_file));
 
-  line_number_to_remove = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (task), "line"));
-  readstream = g_file_read (self->source_file,
-                            NULL,
-                            &error);
-  outstream = g_file_replace (self->source_file,
-                              NULL,
-                              TRUE,
-                              G_FILE_CREATE_NONE,
-                              NULL,
-                              &error);
-
-  if (error)
-    {
-      emit_generic_error (error);
-      g_error_free (error);
-      return;
-    }
-
-  reader = g_data_input_stream_new (G_INPUT_STREAM (readstream));
-  writer = g_data_output_stream_new (G_OUTPUT_STREAM (outstream));
-
-  while (!line_read_error)
-    {
-      TaskData *td;
-      gboolean valid;
-      GList *tokens = NULL;
-
-      line_read = g_data_input_stream_read_line (reader,
-                                                 NULL,
-                                                 NULL,
-                                                 &line_read_error);
-
-      skip = FALSE;
-
-      if (line_read_error)
-        {
-          g_warning ("%s: %s: %s",
-                     G_STRFUNC,
-                     _("Error while reading tasks from Todo.txt"),
-                     line_read_error->message);
-
-          gtd_manager_emit_error_message (gtd_manager_get_default (),
-                                          _("Error while reading tasks from Todo.txt"),
-                                          line_read_error->message);
-          g_error_free (line_read_error);
-          return;
-        }
-
-      if (!line_read)
-        break;
-
-      line_number++;
-
-      tokens = gtd_todo_txt_parser_tokenize (line_read);
-      valid = gtd_todo_txt_parser_validate_token_format (tokens);
-
-      if (valid)
-        td = gtd_todo_txt_parser_parse_tokens (tokens);
-      else
-        td = NULL;
-
-      if (line_number == line_number_to_remove)
-        {
-          skip = TRUE;
-          self->no_of_lines--;
-        }
-
-      if (!skip)
-        {
-          line_read = strcat (line_read, "\n");
-
-          g_data_output_stream_put_string (writer,
-                                           line_read,
-                                           NULL,
-                                          &write_error);
-        }
-
-      g_free (td);
-    }
-
-  g_output_stream_close (G_OUTPUT_STREAM (writer),
-                         NULL,
-                         NULL);
+  update_source (self);
 }
 
 static void
@@ -678,61 +435,20 @@ gtd_provider_todo_txt_create_task_list (GtdProvider *provider,
                                         GtdTaskList *list)
 {
   GtdProviderTodoTxt *self;
-  GFileOutputStream  *write_stream;
-  GDataOutputStream *writer;
-  GError *write_error;
-  GError *error;
-  gchar *put;
-  const gchar *name;
+  gchar *name;
+  g_return_if_fail (GTD_IS_TASK_LIST (list));
 
   self = GTD_PROVIDER_TODO_TXT (provider);
-  error = write_error = NULL;
-
-  g_return_if_fail (G_IS_FILE (self->source_file));
-
-  write_stream = g_file_append_to (self->source_file,
-                                  G_FILE_CREATE_REPLACE_DESTINATION,
-                                  NULL,
-                                  &error);
-
-  if (error)
-    {
-      emit_generic_error (error);
-      g_error_free (error);
-      return;
-    }
-
-  name = gtd_task_list_get_name (list);
-  writer = g_data_output_stream_new (G_OUTPUT_STREAM (write_stream));
+  name = g_strdup (gtd_task_list_get_name (list));
+  gtd_task_list_set_is_removable (list, TRUE);
 
-  put = g_strconcat ("@", name, "\n", NULL);
-
-  g_data_output_stream_put_string (writer,
-                                   put,
-                                   NULL,
-                                   &write_error);
-
-  if (write_error)
-    {
-      g_warning ("%s: %s: %s",
-                 G_STRFUNC,
-                 _("Error while creating a Todo.txt list"),
-                 write_error->message);
-
-      gtd_manager_emit_error_message (gtd_manager_get_default (),
-                                      _("Error while creating a Todo.txt list"),
-                                      write_error->message);
-      g_error_free (write_error);
-      goto out;
-    }
+  self->task_lists = g_list_append (self->task_lists, list);
+  g_ptr_array_add (self->cache, list);
+  g_hash_table_insert (self->lists, name, list);
 
-  self->tasklists = g_list_append (self->tasklists, list);
-  g_hash_table_insert (self->lists, (gpointer) name, list);
-  g_signal_emit_by_name (self, "list-added", list);
-  self->no_of_lines++;
+  update_source (self);
 
-out:
-  g_free (put);
+  g_signal_emit_by_name (provider, "list-added", list);
 }
 
 static void
@@ -740,231 +456,32 @@ gtd_provider_todo_txt_update_task_list (GtdProvider *provider,
                                         GtdTaskList *list)
 {
   GtdProviderTodoTxt *self;
-  GFileInputStream *readstream;
-  GFileOutputStream *outstream;
-  GDataOutputStream *writer;
-  GDataInputStream *reader;
-  GError *line_read_error = NULL;
-  GError *error;
-  GError *write_error;
-  const gchar *current_list_name;
-  gchar *stored_list_name;
-  gchar *line_read;
 
   self = GTD_PROVIDER_TODO_TXT (provider);
-  error = write_error = NULL;
-
-  g_return_if_fail (G_IS_FILE (self->source_file));
-
-  stored_list_name = g_object_get_data (G_OBJECT (list), "line");
-  current_list_name = gtd_task_list_get_name (list);
-
-  readstream = g_file_read (self->source_file,
-                            NULL,
-                            &error);
-  outstream = g_file_replace (self->source_file,
-                              NULL,
-                              TRUE,
-                              G_FILE_CREATE_NONE,
-                              NULL,
-                              &error);
-
-  if (error)
-    {
-      emit_generic_error (error);
-      g_error_free (error);
-      return;
-    }
 
-  reader = g_data_input_stream_new (G_INPUT_STREAM (readstream));
-  writer = g_data_output_stream_new (G_OUTPUT_STREAM (outstream));
-
-  while (!line_read_error)
-    {
-      gboolean valid;
-      GList *tokens;
-      TaskData *td = NULL;
+  g_return_if_fail (GTD_IS_TASK_LIST (list));
 
-      tokens = NULL;
-      line_read = g_data_input_stream_read_line (reader,
-                                                 NULL,
-                                                 NULL,
-                                                 &line_read_error);
-
-      if (line_read_error)
-        {
-          g_warning ("%s: %s: %s",
-                     G_STRFUNC,
-                     _("Error while reading tasks from Todo.txt"),
-                     line_read_error->message);
-
-          gtd_manager_emit_error_message (gtd_manager_get_default (),
-                                         _("Error while reading tasks from Todo.txt"),
-                                           line_read_error->message);
-          g_error_free (line_read_error);
-          continue;
-        }
-
-      if (!line_read)
-        break;
-
-      tokens = gtd_todo_txt_parser_tokenize (line_read);
-      valid = gtd_todo_txt_parser_validate_token_format (tokens);
+  update_source (self);
 
-      if (valid)
-        td = gtd_todo_txt_parser_parse_tokens (tokens);
-
-      if (valid &&
-          strcmp (stored_list_name, current_list_name) &&
-          !(strcmp (gtd_todo_txt_parser_task_data_get_task_list_name (td), stored_list_name)))
-        {
-          GList *update_tokens;
-          GList *it;
-
-          update_tokens = gtd_todo_txt_parser_get_list_updated_token (list, g_strdup (line_read));
-          it = NULL;
-
-          for (it = update_tokens; it != NULL; it = it->next)
-            {
-              g_data_output_stream_put_string (writer,
-                                               it->data,
-                                               NULL,
-                                               &write_error);
-              if (it->next == NULL)
-                {
-                  g_data_output_stream_put_string (writer,
-                                                   "\n",
-                                                   NULL,
-                                                   &write_error);
-                }
-              else
-                g_data_output_stream_put_string (writer,
-                                                 " ",
-                                                 NULL,
-                                                 &write_error);
-            }
-          g_list_free_full (update_tokens, g_free);
-        }
-      else
-        {
-          line_read = strcat (line_read, "\n");
-
-          g_data_output_stream_put_string (writer,
-                                           line_read,
-                                           NULL,
-                                           &write_error);
-        }
-
-      g_list_free_full (tokens, g_free);
-    }
-
-  g_output_stream_close (G_OUTPUT_STREAM (writer), NULL, NULL);
-  g_input_stream_close (G_INPUT_STREAM (reader), NULL, NULL);
-
-  g_output_stream_close (G_OUTPUT_STREAM (outstream), NULL, NULL);
-  g_input_stream_close (G_INPUT_STREAM (readstream), NULL, NULL);
+  g_signal_emit_by_name (provider, "list-changed", list);
 }
 
 static void
 gtd_provider_todo_txt_remove_task_list (GtdProvider *provider,
                                         GtdTaskList *list)
 {
-
   GtdProviderTodoTxt *self;
-  GFileOutputStream *outstream;
-  GDataOutputStream *writer;
-  GFileInputStream *readstream;
-  GDataInputStream *reader;
-  GError *line_read_error = NULL;
-  GError *write_error;
-  GError *error;
-  const gchar  *list_name;
-  gboolean skip;
-  gchar *line;
 
   self = GTD_PROVIDER_TODO_TXT (provider);
-  error = write_error = NULL;
-  list_name = gtd_task_list_get_name (list);
-
-  g_return_if_fail (G_IS_FILE (self->source_file));
-
-  readstream = g_file_read (self->source_file,
-                            NULL,
-                            &error);
-  outstream = g_file_replace (self->source_file,
-                              NULL,
-                              TRUE,
-                              G_FILE_CREATE_NONE,
-                              NULL,
-                              &error);
-
-  if (error)
-    {
-      emit_generic_error (error);
-      g_error_free (error);
-      return;
-    }
-
-  reader = g_data_input_stream_new (G_INPUT_STREAM (readstream));
-  writer = g_data_output_stream_new (G_OUTPUT_STREAM (outstream));
-
-  while (!line_read_error)
-    {
-      TaskData *td = NULL;
-      gboolean valid;
-      GList *tokens = NULL;
-
-      line = g_data_input_stream_read_line (reader,
-                                            NULL,
-                                            NULL,
-                                            &line_read_error);
 
-      skip = FALSE;
+  g_return_if_fail (GTD_IS_TASK_LIST (list));
 
-      if (line_read_error)
-        {
-          g_warning ("%s: %s: %s",
-                     G_STRFUNC,
-                     _("Error while reading task lists from Todo.txt"),
-                     line_read_error->message);
-
-          gtd_manager_emit_error_message (gtd_manager_get_default (),
-                                          _("Error while reading task lists from Todo.txt"),
-                                          line_read_error->message);
-          g_error_free (line_read_error);
-        }
-
-      if (!line)
-        break;
-
-      tokens = gtd_todo_txt_parser_tokenize (line);
-      valid = gtd_todo_txt_parser_validate_token_format (tokens);
-
-      if (valid)
-        td = gtd_todo_txt_parser_parse_tokens (tokens);
-
-      if (valid && strcmp (gtd_todo_txt_parser_task_data_get_task_list_name (td), list_name) == 0)
-        {
-          self->no_of_lines--;
-          skip = TRUE;
-        }
-
-      if (!skip)
-        {
-          line = strcat (line, "\n");
+  g_ptr_array_remove (self->cache, list);
+  self->task_lists = g_list_remove (self->task_lists, list);
 
-          g_data_output_stream_put_string (writer,
-                                           line,
-                                           NULL,
-                                           &write_error);
-        }
-
-      g_free (td);
-    }
+  update_source (self);
 
-  g_output_stream_close (G_OUTPUT_STREAM (writer),
-                         NULL,
-                         NULL);
+  g_signal_emit_by_name (provider, "list-removed", list);
 }
 
 static GList*
@@ -974,7 +491,7 @@ gtd_provider_todo_txt_get_task_lists (GtdProvider *provider)
 
   self = GTD_PROVIDER_TODO_TXT (provider);
 
-  return self->tasklists;
+  return self->task_lists;
 }
 
 static GtdTaskList*
@@ -1025,8 +542,9 @@ gtd_provider_todo_txt_finalize (GObject *object)
   GtdProviderTodoTxt *self = (GtdProviderTodoTxt *)object;
 
   g_clear_pointer (&self->lists, g_hash_table_destroy);
-  g_clear_pointer (&self->root_tasks, g_hash_table_destroy);
-  g_clear_pointer (&self->tasklists, g_clear_object);
+  g_clear_pointer (&self->tasks, g_hash_table_destroy);
+  g_ptr_array_free (self->cache, TRUE);
+  g_clear_pointer (&self->task_lists, g_clear_object);
   g_clear_object (&self->source_file);
   g_clear_object (&self->icon);
 
@@ -1083,8 +601,8 @@ gtd_provider_todo_txt_set_property (GObject      *object,
     {
     case PROP_SOURCE:
       self->source_file = g_value_dup_object (value);
-      gtd_provider_todo_txt_load_source (self);
       gtd_provider_todo_txt_load_source_monitor (self);
+      gtd_provider_todo_txt_load_tasks (self);
       break;
 
     default:
@@ -1122,9 +640,10 @@ gtd_provider_todo_txt_init (GtdProviderTodoTxt *self)
 {
   gtd_object_set_ready (GTD_OBJECT (self), TRUE);
 
-  self->no_of_lines = 0;
   self->lists = g_hash_table_new ((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal);
-  self->root_tasks = g_hash_table_new ((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal);
+  self->tasks = g_hash_table_new ((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal);
+  self->cache = g_ptr_array_new ();
+  self->should_reload = TRUE;
 
   /* icon */
   self->icon = G_ICON (g_themed_icon_new_with_default_fallbacks ("computer-symbolic"));
diff --git a/plugins/todo-txt/gtd-provider-todo-txt.h b/plugins/todo-txt/gtd-provider-todo-txt.h
index a4c0705..7d85b4f 100644
--- a/plugins/todo-txt/gtd-provider-todo-txt.h
+++ b/plugins/todo-txt/gtd-provider-todo-txt.h
@@ -31,6 +31,8 @@ G_DECLARE_FINAL_TYPE (GtdProviderTodoTxt, gtd_provider_todo_txt, GTD, PROVIDER_T
 
 GtdProviderTodoTxt*    gtd_provider_todo_txt_new                     (GFile         *source_file);
 
+GtdTask* create_task (void);
+
 G_END_DECLS
 
 #endif /* GTD_PROVIDER_TODO_TXT_H */
diff --git a/plugins/todo-txt/gtd-todo-txt-parser.c b/plugins/todo-txt/gtd-todo-txt-parser.c
index a1f96cb..edb763e 100644
--- a/plugins/todo-txt/gtd-todo-txt-parser.c
+++ b/plugins/todo-txt/gtd-todo-txt-parser.c
@@ -18,6 +18,7 @@
 
 #include <glib/gi18n.h>
 #include <gtd-todo-txt-parser.h>
+#include <gtd-provider-todo-txt.h>
 
 struct _GtdTodoTxtParser
 {
@@ -36,32 +37,6 @@ enum {
 
 G_DEFINE_TYPE (GtdTodoTxtParser, gtd_todo_txt_parser, GTD_TYPE_OBJECT);
 
-struct _TaskData
-{
-  gchar                   *root_task_name;
-  gchar                   *task_list_name;
-  gchar                   *title;
-
-  GDateTime               *creation_date;
-  GDateTime               *completion_date;
-  GDateTime               *due_date;
-
-  gboolean                 is_subtask;
-  gboolean                 is_task_completed;
-  gint                     priority;
-
-};
-
-static TaskData*
-task_data_new (void)
-{
-  TaskData *tdata;
-
-  tdata = g_new0 (TaskData, 1);
-
-  return tdata;
-}
-
 gint
 gtd_todo_txt_parser_get_priority (gchar *token)
 {
@@ -69,15 +44,12 @@ gtd_todo_txt_parser_get_priority (gchar *token)
     {
     case 'A':
       return 3;
-      break;
 
     case 'B':
       return 2;
-      break;
 
     case 'C':
       return 1;
-      break;
 
     default:
       return 0;
@@ -89,28 +61,27 @@ gtd_todo_txt_parser_get_priority (gchar *token)
 GDateTime*
 gtd_todo_txt_parser_get_date (gchar *token)
 {
-  GDate     *date = NULL;
-  GDateTime *dt = NULL;
-  gint       year;
-  gint       month;
-  gint       day;
-
-  date = g_date_new ();
+  GDateTime *dt;
+  GDate date;
+  gint year;
+  gint month;
+  gint day;
 
-  g_date_set_parse (date, token);
+  dt = NULL;
+  g_date_clear (&date, 1);
+  g_date_set_parse (&date, token);
 
-  if (!g_date_valid (date))
+  if (!g_date_valid (&date))
     return NULL;
 
-  year = g_date_get_year (date);
-  month = g_date_get_month (date);
-  day = g_date_get_day (date);
+  year = g_date_get_year (&date);
+  month = g_date_get_month (&date);
+  day = g_date_get_day (&date);
 
   dt = g_date_time_new_utc (year,
                             month,
                             day,
                             0, 0, 0);
-  g_date_free (date);
 
   return dt;
 }
@@ -118,7 +89,7 @@ gtd_todo_txt_parser_get_date (gchar *token)
 gboolean
 gtd_todo_txt_parser_is_date (gchar *dt)
 {
-  GDate  date;
+  GDate date;
 
   g_date_clear (&date, 1);
   g_date_set_parse (&date, dt);
@@ -154,140 +125,133 @@ gtd_todo_txt_parser_get_token_id (gchar *token,
   if (!g_strcmp0 (token, "x"))
     return TASK_COMPLETE;
 
-  if (token_length == 3)
-    {
-      if (token[0] == '(' && token[2] == ')')
-        return TASK_PRIORITY;
-    }
+  if (token_length == 3 && token[0] == '(' && token[2] == ')')
+    return TASK_PRIORITY;
 
-  if (!g_str_has_prefix (token , "due:") &&
-      gtd_todo_txt_parser_is_date (token))
+  if (!g_str_has_prefix (token , "due:") && gtd_todo_txt_parser_is_date (token))
     return TASK_DATE;
 
-
   if (gtd_todo_txt_parser_is_word (token) &&
       (last_read == TASK_DATE ||
        last_read == TASK_PRIORITY ||
        last_read == TASK_COMPLETE||
        last_read == TASK_TITLE))
-    return TASK_TITLE;
-
-  if (token_length > 1)
     {
-      if (token[0] == '@')
-        return TASK_LIST_NAME;
+      return TASK_TITLE;
     }
 
-  if (token_length > 1)
-    {
-      if (token[0] == '+')
-        return ROOT_TASK_NAME;
-    }
+  if (token_length > 1 && token[0] == '@')
+    return TASK_LIST_NAME;
 
-  if (gtd_todo_txt_parser_is_word (token) &&
-      last_read == TASK_LIST_NAME)
+  if (token_length > 1 && token[0] == '+')
+    return ROOT_TASK_NAME;
+
+  if (gtd_todo_txt_parser_is_word (token) && last_read == TASK_LIST_NAME)
     return TASK_LIST_NAME;
 
-  if (gtd_todo_txt_parser_is_word (token) &&
-      last_read == ROOT_TASK_NAME)
+  if (gtd_todo_txt_parser_is_word (token) && last_read == ROOT_TASK_NAME)
     return ROOT_TASK_NAME;
 
   if (g_str_has_prefix (token , "due:"))
     return TASK_DUE_DATE;
 
-
-
   return -1;
 }
 
-TaskData*
-gtd_todo_txt_parser_parse_tokens (GList *tk)
+GtdTask*
+gtd_todo_txt_parser_parse_tokens (GList *tokens)
 {
+  GtdTask *task;
   GDateTime *dt;
-  TaskData *td;
-  GList *it;
+  GString *list_name;
+  GString *title;
+  GString *root_task_name;
+  gboolean is_subtask;
+
+  GList *l;
   gint last_read_token;
   gint token_id;
 
   dt = NULL;
-  it = NULL;
-  td = task_data_new ();
+  l = NULL;
+  task = create_task ();
+  list_name = g_string_new (NULL);
+  title = g_string_new (NULL);
+  root_task_name = g_string_new (NULL);
+  is_subtask = FALSE;
 
   last_read_token = TASK_COMPLETE;
 
-  for (it = tk; it != NULL; it = it->next)
+  for (l = tokens; l != NULL; l = l->next)
     {
+
       gchar *str;
 
-      str = it->data;
-      token_id = gtd_todo_txt_parser_get_token_id (it->data, last_read_token);
+      g_strstrip (l->data);
+      str = l->data;
+      token_id = gtd_todo_txt_parser_get_token_id (l->data, last_read_token);
 
       switch (token_id)
         {
         case TASK_COMPLETE:
           last_read_token = TASK_COMPLETE;
-          td->is_task_completed = TRUE;
+          gtd_task_set_complete (task, TRUE);
           break;
 
         case TASK_PRIORITY:
           last_read_token = TASK_PRIORITY;
-          td->priority = gtd_todo_txt_parser_get_priority (it->data);
+          gtd_task_set_priority (task, gtd_todo_txt_parser_get_priority (l->data));
           break;
 
         case TASK_DATE:
           last_read_token = TASK_DATE;
-          dt = gtd_todo_txt_parser_get_date (it->data);
-          td->creation_date = dt;
+          dt = gtd_todo_txt_parser_get_date (l->data);
           break;
 
         case TASK_TITLE:
           last_read_token = TASK_TITLE;
-          if (td->title == NULL)
-            td->title = g_strdup (it->data);
-          else
-            {
-              char *temp = td->title;
-              td->title = g_strconcat (td->title, " ",it->data, NULL);
-              g_free (temp);
-            }
+          g_string_append (title, l->data);
+          g_string_append (title, " ");
           break;
 
         case TASK_LIST_NAME:
           last_read_token = TASK_LIST_NAME;
-          if (td->task_list_name == NULL)
-            td->task_list_name = g_strdup (&str[1]);
-          else
-            {
-              gchar *temp = td->task_list_name;
-              td->task_list_name = g_strconcat (td->task_list_name, " ",it->data, NULL);
-              g_free (temp);
-            }
+          g_string_append (list_name, l->data);
+          g_string_append (list_name, " ");
           break;
 
         case ROOT_TASK_NAME:
           last_read_token = ROOT_TASK_NAME;
-          if (td->root_task_name == NULL)
-            td->root_task_name = g_strdup (&str[1]);
-          else
-            {
-              gchar *temp = td->root_task_name;
-              td->root_task_name = g_strconcat (td->root_task_name, " ",it->data, NULL);
-              g_free (temp);
-            }
-          td->is_subtask = TRUE;
+          is_subtask = TRUE;
+          g_string_append (root_task_name, l->data);
+          g_string_append (root_task_name, " ");
           break;
 
         case TASK_DUE_DATE:
           last_read_token = TASK_DUE_DATE;
           dt = gtd_todo_txt_parser_get_date (&str[4]);
-          td->due_date = dt;
+          gtd_task_set_due_date (task, dt);
           break;
 
         default:
           return NULL;
         }
     }
-  return td;
+
+  g_strstrip (title->str);
+  g_strstrip (list_name->str);
+  g_strstrip (root_task_name->str);
+  gtd_task_set_title (task, title->str);
+  g_object_set_data_full (G_OBJECT (task), "list_name", g_strdup (list_name->str + 1), g_free);
+
+  if (is_subtask)
+    g_object_set_data_full (G_OBJECT (task), "root_task_name", g_strdup (root_task_name->str + 1), g_free);
+
+  g_string_free (root_task_name, TRUE);
+  g_string_free (list_name, TRUE);
+  g_string_free (title, TRUE);
+
+  return task;
 }
 
 gboolean
@@ -410,53 +374,36 @@ gtd_todo_txt_parser_tokenize (const gchar *line)
   return tokens;
 }
 
-GList*
-gtd_todo_txt_parser_get_list_updated_token (GtdTaskList *list,
-                                            gchar       *line)
+gchar*
+gtd_todo_txt_parser_serialize_list (GtdTaskList *list)
 {
-  gint last_read_token = TASK_COMPLETE;
-  gboolean list_name_updated = FALSE;
-  GList *tokens = NULL;
-  GList *it = NULL;
-
-  tokens = gtd_todo_txt_parser_tokenize (line);
+  GString *description;
+  const gchar   *list_name;
 
-  for (it = tokens; it != NULL; it = it->next)
-    {
-      gint token_id;
+  description = g_string_new (NULL);
+  list_name = gtd_task_list_get_name (list);
 
-      token_id = gtd_todo_txt_parser_get_token_id (it->data, last_read_token);
-      last_read_token = token_id;
-      if (token_id == TASK_LIST_NAME)
-        {
-          if (list_name_updated)
-            {
-              it = g_list_remove (tokens, it->data);
-              last_read_token = TASK_COMPLETE;
-            }
+  g_string_append (description, "@");
+  g_string_append (description, list_name);
 
-          else
-            {
-              it->data = g_strconcat ("@", gtd_task_list_get_name(list), NULL);
-              list_name_updated = TRUE;
-            }
-        }
-    }
+  g_string_append (description, "\n");
 
-  return tokens;
+  return g_string_free (description, FALSE);
 }
 
-GList*
-gtd_todo_txt_parser_get_task_line (GtdTask *task)
+gchar*
+gtd_todo_txt_parser_serialize_task (GtdTask *task)
 {
   GtdTaskList *list;
   GDateTime   *dt;
-  GtdTask *parent;
-  GList *tokens = NULL;
-  gint priority;
-  gboolean is_complete;
+  GtdTask     *parent;
+  GString     *description;
   const gchar *list_name;
   const gchar *title;
+  gint priority;
+  gboolean is_complete;
+
+  description = g_string_new (NULL);
 
   is_complete = gtd_task_get_complete (task);
   title = gtd_task_get_title (task);
@@ -468,72 +415,41 @@ gtd_todo_txt_parser_get_task_line (GtdTask *task)
   list_name = gtd_task_list_get_name (list);
 
   if (is_complete)
-    tokens = g_list_append (tokens, g_strdup ("x"));
+    g_string_append (description, "x ");
 
   if (priority)
     {
       if (priority == 1)
-        tokens = g_list_append (tokens, g_strdup ("(C)"));
+        g_string_append (description, "(C) ");
       else if (priority == 2)
-        tokens = g_list_append (tokens, g_strdup ("(B)"));
+        g_string_append (description, "(B) ");
       else if (priority == 3)
-        tokens = g_list_append (tokens, g_strdup ("(A)"));
+        g_string_append (description, "(A) ");
     }
 
-  tokens = g_list_append (tokens, g_strdup (title));
-  tokens = g_list_append (tokens, g_strconcat ("@", list_name, NULL));
+  g_string_append (description, title);
+  g_string_append (description, " @");
+  g_string_append (description, list_name);
 
   if (parent)
-    tokens = g_list_append (tokens, g_strconcat ("+", gtd_task_get_title (parent), NULL));
+    {
+      g_string_append (description, " +");
+      g_string_append (description, gtd_task_get_title (parent));
+    }
 
   if (dt)
-    tokens = g_list_append (tokens, g_strconcat ("due:",g_date_time_format (dt, "%F"),NULL));
-
-  return tokens;
-}
-
-/* Accessor Methods for the TaskData Structure */
-
-gchar*
-gtd_todo_txt_parser_task_data_get_root_task_name (TaskData *td)
-{
-  return td->root_task_name;
-}
-
-gchar*
-gtd_todo_txt_parser_task_data_get_task_list_name (TaskData *td)
-{
-  return td->task_list_name;
-}
+    {
+      g_autofree gchar *formatted_time;
 
-gchar*
-gtd_todo_txt_parser_task_data_get_title (TaskData *td)
-{
-  return td->title;
-}
+      formatted_time = g_date_time_format (dt, "%F");
 
-GDateTime*
-gtd_todo_txt_parser_task_data_get_due_date (TaskData *td)
-{
-  return td->due_date;
-}
-
-gboolean
-gtd_todo_txt_parser_task_data_is_subtask (TaskData *td)
-{
-  return td->is_subtask;
-}
+      g_string_append (description, " due:");
+      g_string_append (description, formatted_time);
+    }
 
-gboolean
-gtd_todo_txt_parser_task_data_is_task_completed (TaskData *td)
-{
-  return td->is_task_completed;
-}
+  g_string_append (description, "\n");
 
-gint
-gtd_todo_txt_parser_task_data_get_priority (TaskData *td)
-{
-  return td->priority;
+  return g_string_free (description, FALSE);
 }
 
 static void
diff --git a/plugins/todo-txt/gtd-todo-txt-parser.h b/plugins/todo-txt/gtd-todo-txt-parser.h
index dfeb081..ff6fe1a 100644
--- a/plugins/todo-txt/gtd-todo-txt-parser.h
+++ b/plugins/todo-txt/gtd-todo-txt-parser.h
@@ -41,32 +41,15 @@ gboolean      gtd_todo_txt_parser_is_word                         (gchar
 gint          gtd_todo_txt_parser_get_token_id                    (gchar             *token,
                                                                    gint               last_read);
 
-TaskData*     gtd_todo_txt_parser_parse_tokens                    (GList             *tk);
+GtdTask*      gtd_todo_txt_parser_parse_tokens                    (GList             *tokens);
 
 gboolean      gtd_todo_txt_parser_validate_token_format           (GList             *tokens);
 
 GList*        gtd_todo_txt_parser_tokenize                        (const gchar       *line);
 
-GList*        gtd_todo_txt_parser_get_list_updated_token          (GtdTaskList       *list,
-                                                                   gchar             *line);
+gchar*        gtd_todo_txt_parser_serialize_list                  (GtdTaskList       *list);
 
-GList*        gtd_todo_txt_parser_get_task_line                   (GtdTask           *task);
-
-/*Accessor Methods for TaskData Strcuture*/
-
-gchar*        gtd_todo_txt_parser_task_data_get_root_task_name    (TaskData          *td);
-
-gchar*        gtd_todo_txt_parser_task_data_get_task_list_name    (TaskData          *td);
-
-gchar*        gtd_todo_txt_parser_task_data_get_title             (TaskData          *td);
-
-GDateTime*    gtd_todo_txt_parser_task_data_get_due_date          (TaskData          *td);
-
-gboolean      gtd_todo_txt_parser_task_data_is_subtask            (TaskData          *td);
-
-gboolean      gtd_todo_txt_parser_task_data_is_task_completed     (TaskData          *td);
-
-gint          gtd_todo_txt_parser_task_data_get_priority          (TaskData          *td);
+gchar*        gtd_todo_txt_parser_serialize_task                  (GtdTask           *task);
 
 G_END_DECLS
 


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