[gnome-todo] todo-txt: introduce plugin to manage todo.txt files



commit a7a340027df5177b35cc5621d5425651cf64bf6a
Author: Rohit Kaushik <kaushikrohit325 gmail com>
Date:   Fri Jan 20 19:23:04 2017 +0530

    todo-txt: introduce plugin to manage todo.txt files
    
    https://bugzilla.gnome.org/show_bug.cgi?id=755734

 configure.ac                                    |    2 +
 data/todo.gresource.xml                         |    4 +
 plugins/Makefile.am                             |    3 +
 plugins/todo-txt/Makefile.am                    |   24 +
 plugins/todo-txt/gtd-plugin-todo-txt.c          |  405 ++++++++
 plugins/todo-txt/gtd-plugin-todo-txt.h          |   41 +
 plugins/todo-txt/gtd-provider-todo-txt.c        | 1208 +++++++++++++++++++++++
 plugins/todo-txt/gtd-provider-todo-txt.h        |   39 +
 plugins/todo-txt/gtd-todo-txt-parser.c          |  582 +++++++++++
 plugins/todo-txt/gtd-todo-txt-parser.h          |   73 ++
 plugins/todo-txt/org.gnome.todo.txt.gschema.xml |   10 +
 plugins/todo-txt/todo-txt.plugin.in             |   13 +
 src/Makefile.am                                 |    5 +-
 13 files changed, 2408 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 2636781..6924d96 100644
--- a/configure.ac
+++ b/configure.ac
@@ -92,6 +92,7 @@ GNOME_TODO_ADD_PLUGIN([scheduled-panel], [Scheduled Panel], [yes])
 GNOME_TODO_ADD_PLUGIN([score], [Score], [yes])
 GNOME_TODO_ADD_PLUGIN([today-panel], [Today Panel], [yes])
 GNOME_TODO_ADD_PLUGIN([unscheduled-panel], [Unscheduled Tasks Panel], [yes])
+GNOME_TODO_ADD_PLUGIN([todo-txt], [Todo.Txt], [yes])
 
 
 dnl ***********************************************************************
@@ -141,6 +142,7 @@ echo "
         Score ................... ${enable_score_plugin}
         Today panel ............. ${enable_today_panel_plugin}
         Unscheduled panel ....... ${enable_unscheduled_panel_plugin}
+        Todo.txt ................ ${enable_todo_txt_plugin}
 
         Now type 'make' to build $PACKAGE
 "
diff --git a/data/todo.gresource.xml b/data/todo.gresource.xml
index c53e344..1052a9d 100644
--- a/data/todo.gresource.xml
+++ b/data/todo.gresource.xml
@@ -43,4 +43,8 @@
   <gresource prefix="/org/gnome/todo">
     <file alias="plugins/today-panel/today-panel.plugin">../plugins/today-panel/today-panel.plugin</file>
   </gresource>
+  <!--Todo.Txt-->
+  <gresource prefix="/org/gnome/todo">
+    <file alias="plugins/todo-txt/todo-txt.plugin">../plugins/todo-txt/todo-txt.plugin</file>
+  </gresource>
 </gresources>
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index eb4fdec..e6afbd0 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -20,5 +20,8 @@ if BUILD_UNSCHEDULED_PANEL_PLUGIN
 SUBDIRS += unscheduled-panel
 endif
 
+if BUILD_TODO_TXT_PLUGIN
+SUBDIRS += todo-txt
+endif
 
 MAINTAINERCLEANFILES = Makefile.in
diff --git a/plugins/todo-txt/Makefile.am b/plugins/todo-txt/Makefile.am
new file mode 100644
index 0000000..cf1f3ba
--- /dev/null
+++ b/plugins/todo-txt/Makefile.am
@@ -0,0 +1,24 @@
+gsettings_SCHEMAS = org.gnome.todo.txt.gschema.xml
+
+@GSETTINGS_RULES@
+
+include $(top_srcdir)/common.am
+
+noinst_LTLIBRARIES = libtodotxt.la
+
+libtodotxt_la_SOURCES = \
+       gtd-plugin-todo-txt.c \
+       gtd-plugin-todo-txt.h \
+       gtd-provider-todo-txt.c \
+       gtd-provider-todo-txt.h \
+       gtd-todo-txt-parser.c \
+       gtd-todo-txt-parser.h
+
+libtodotxt_la_CFLAGS = \
+       $(GNOME_TODO_PLUGIN_CFLAGS) \
+       $(GNOME_TODO_PLUGIN_WARN_CFLAGS)
+
+EXTRA_DIST = \
+       $(gsettings_SCHEMAS) \
+       todo-txt.plugin.in
+
diff --git a/plugins/todo-txt/gtd-plugin-todo-txt.c b/plugins/todo-txt/gtd-plugin-todo-txt.c
new file mode 100644
index 0000000..e3f36de
--- /dev/null
+++ b/plugins/todo-txt/gtd-plugin-todo-txt.c
@@ -0,0 +1,405 @@
+/* gtd-plugin-todo-txt.c
+ *
+ * Copyright (C) 2016 Rohit Kaushik <kaushikrohit325 gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "Todo Txt"
+
+#include "gtd-plugin-todo-txt.h"
+#include "gtd-provider-todo-txt.h"
+
+#include <glib/gi18n.h>
+#include <glib-object.h>
+
+/**
+ * The #GtdPluginTodoTxt is a class that loads Todo.txt
+ * provider of GNOME To Do.
+ */
+
+struct _GtdPluginTodoTxt
+{
+  PeasExtensionBase   parent;
+
+  gchar              *source;
+
+  GFile              *source_file;
+  GFileMonitor       *monitor;
+
+  GSettings          *settings;
+
+  GtkWidget          *preferences_box;
+  GtkWidget          *preferences;
+
+  /* Providers */
+  GList              *providers;
+};
+
+enum
+{
+  PROP_0,
+  PROP_PREFERENCES_PANEL,
+  LAST_PROP
+};
+
+static void          gtd_activatable_iface_init                  (GtdActivatableInterface  *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GtdPluginTodoTxt, gtd_plugin_todo_txt, PEAS_TYPE_EXTENSION_BASE,
+                                0,
+                                G_IMPLEMENT_INTERFACE_DYNAMIC (GTD_TYPE_ACTIVATABLE,
+                                                               gtd_activatable_iface_init))
+
+void
+gtd_plugin_todo_txt_monitor_source (GFileMonitor      *monitor,
+                                    GFile             *first,
+                                    GFile             *second,
+                                    GFileMonitorEvent  event,
+                                    gpointer           data)
+{
+  GtdProviderTodoTxt *provider;
+  GtdPluginTodoTxt *self;
+
+  self = data;
+
+  provider = self->providers->data;
+
+  g_list_free_full (self->providers, g_object_unref);
+  self->providers = NULL;
+
+  g_signal_emit_by_name (self, "provider-removed", provider);
+
+  provider = gtd_provider_todo_txt_new (self->source);
+  self->source_file = g_file_new_for_uri (self->source);
+
+  self->providers = g_list_append (self->providers, provider);
+  g_signal_emit_by_name (self, "provider-added", provider);
+}
+
+static void
+gtd_plugin_todo_txt_load_source_monitor (GtdPluginTodoTxt *self)
+{
+  GError *file_monitor = NULL;
+
+  self->monitor = g_file_monitor_file (self->source_file,
+                                       G_FILE_MONITOR_WATCH_MOVES,
+                                       NULL,
+                                       &file_monitor);
+
+  if (file_monitor)
+    {
+      gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                     _("Error opening file monitor.Todo.txt will not be monitored"),
+                                      file_monitor->message);
+      g_clear_error (&file_monitor);
+    }
+  else
+    {
+      gtd_provider_todo_txt_set_monitor (self->providers->data, self->monitor);
+      g_signal_connect (self->monitor, "changed", G_CALLBACK (gtd_plugin_todo_txt_monitor_source), self);
+    }
+}
+
+static gboolean
+gtd_plugin_todo_txt_set_default_source (GtdPluginTodoTxt *self)
+{
+  GError *dir_open_error;
+  GDir *default_dir = NULL;
+  gchar *default_file;
+
+  dir_open_error = NULL;
+  default_file = g_strconcat (g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS), "todo.txt", NULL);
+
+  if (dir_open_error)
+    {
+      gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                    _("Error opening default todo.txt directory"),
+                                      dir_open_error->message);
+
+      g_clear_error (&dir_open_error);
+      return FALSE;
+    }
+  else
+    {
+      GError *error;
+
+      error = NULL;
+
+      self->source = g_filename_to_uri (default_file, NULL, &error);
+      self->source_file = g_file_new_for_uri (default_file);
+
+      if (error)
+        {
+          gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                        _("Error converting default todo.txt path to uri"),
+                                          error->message);
+
+          g_clear_error (&error);
+          return FALSE;
+        }
+
+      if (!g_file_query_exists (self->source_file, NULL))
+        {
+          g_file_create (self->source_file,
+                         G_FILE_CREATE_NONE,
+                         NULL,
+                         &error);
+
+          if (error)
+            {
+              gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                            _("Cannot create file"),
+                                              error->message);
+
+              g_clear_error (&error);
+              return FALSE;
+            }
+        }
+
+      g_dir_close (default_dir);
+    }
+
+  return TRUE;
+}
+
+/*
+ * GtdActivatable interface implementation
+ */
+static void
+gtd_plugin_todo_txt_activate (GtdActivatable *activatable)
+{
+  GtdPluginTodoTxt *self;
+  GtdProviderTodoTxt *provider;
+
+  self = GTD_PLUGIN_TODO_TXT (activatable);
+
+  if (!self->source)
+    {
+      gboolean set;
+      set = gtd_plugin_todo_txt_set_default_source (self);
+
+      if (!set)
+        return;
+    }
+
+
+  provider = gtd_provider_todo_txt_new (self->source);
+  self->source_file = g_file_new_for_uri (self->source);
+
+  self->providers = g_list_append (self->providers, provider);
+  g_signal_emit_by_name (self, "provider-added", provider);
+
+  gtd_plugin_todo_txt_load_source_monitor (self);
+}
+
+static void
+gtd_plugin_todo_txt_deactivate (GtdActivatable *activatable)
+{
+  ;
+}
+
+static GList*
+gtd_plugin_todo_txt_get_header_widgets (GtdActivatable *activatable)
+{
+  return NULL;
+}
+
+static GtkWidget*
+gtd_plugin_todo_txt_get_preferences_panel (GtdActivatable *activatable)
+{
+  GtdPluginTodoTxt *plugin = GTD_PLUGIN_TODO_TXT (activatable);
+
+  return plugin->preferences_box;
+
+}
+
+static GList*
+gtd_plugin_todo_txt_get_panels (GtdActivatable *activatable)
+{
+  return NULL;
+}
+
+static GList*
+gtd_plugin_todo_txt_get_providers (GtdActivatable *activatable)
+{
+  GtdPluginTodoTxt *plugin = GTD_PLUGIN_TODO_TXT (activatable);
+
+  return plugin->providers;
+}
+
+static void
+gtd_activatable_iface_init (GtdActivatableInterface *iface)
+{
+  iface->activate = gtd_plugin_todo_txt_activate;
+  iface->deactivate = gtd_plugin_todo_txt_deactivate;
+  iface->get_header_widgets = gtd_plugin_todo_txt_get_header_widgets;
+  iface->get_preferences_panel = gtd_plugin_todo_txt_get_preferences_panel;
+  iface->get_panels = gtd_plugin_todo_txt_get_panels;
+  iface->get_providers = gtd_plugin_todo_txt_get_providers;
+}
+
+/*
+ * Init
+ */
+
+static void
+gtd_plugin_todo_txt_source_changed_finished_cb (GtdPluginTodoTxt *self)
+{
+  GtdProviderTodoTxt *provider;
+
+  self->source = g_settings_get_string (self->settings, "file");
+
+  if (!self->source)
+    {
+      gboolean set;
+      set = gtd_plugin_todo_txt_set_default_source (self);
+
+      if(!set)
+        return;
+    }
+
+  self->source_file = g_file_new_for_uri (self->source);
+
+  provider = gtd_provider_todo_txt_new (self->source);
+  self->providers = g_list_append (self->providers, provider);
+
+  gtd_plugin_todo_txt_load_source_monitor (self);
+
+  g_signal_emit_by_name (self, "provider-added", provider);
+}
+
+static void
+gtd_plugin_todo_txt_source_changed_cb (GtkWidget *preference_panel,
+                                       gpointer   user_data)
+{
+  GtdPluginTodoTxt *self;
+  GtdProviderTodoTxt *provider;
+
+  self = GTD_PLUGIN_TODO_TXT (user_data);
+
+  g_clear_object (&self->monitor);
+  g_free (self->source);
+  g_clear_object (&self->source_file);
+
+  g_settings_set_string (self->settings,
+                        "file",
+                         gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (self->preferences)));
+
+  if (self->providers)
+    {
+      provider = self->providers->data;
+
+      g_list_free_full (self->providers, g_object_unref);
+      self->providers = NULL;
+
+      g_signal_emit_by_name (self, "provider-removed", provider);
+    }
+
+  gtd_plugin_todo_txt_source_changed_finished_cb (self);
+}
+
+
+static void
+gtd_plugin_todo_txt_finalize (GObject *object)
+{
+  GtdPluginTodoTxt *self = (GtdPluginTodoTxt *) object;
+
+  g_clear_object (&self->monitor);
+  g_free (self->source);
+  g_clear_object (&self->source_file);
+  g_list_free_full (self->providers, g_object_unref);
+  self->providers = NULL;
+
+  G_OBJECT_CLASS (gtd_plugin_todo_txt_parent_class)->finalize (object);
+}
+
+static void
+gtd_plugin_todo_txt_get_property (GObject    *object,
+                                  guint       prop_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
+{
+  GtdPluginTodoTxt *self = GTD_PLUGIN_TODO_TXT (object);
+  switch (prop_id)
+    {
+    case PROP_PREFERENCES_PANEL:
+      g_value_set_object (value, self->preferences);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_plugin_todo_txt_class_init (GtdPluginTodoTxtClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize     = gtd_plugin_todo_txt_finalize;
+  object_class->get_property = gtd_plugin_todo_txt_get_property;
+
+  g_object_class_override_property (object_class,
+                                    PROP_PREFERENCES_PANEL,
+                                    "preferences-panel");
+}
+
+static void
+gtd_plugin_todo_txt_init (GtdPluginTodoTxt *self)
+{
+  GtkWidget *label, *frame;
+
+  self->settings = g_settings_new ("org.gnome.todo.plugins.todo-txt");
+  self->source = g_settings_get_string (self->settings, "file");
+  self->providers = NULL;
+
+  /* Preferences */
+  self->preferences_box = g_object_new (GTK_TYPE_BOX,
+                                        "margin", 18,
+                                        "spacing", 12,
+                                        "expand", TRUE,
+                                        "orientation", GTK_ORIENTATION_VERTICAL,
+                                        NULL);
+  label = gtk_label_new (_("Select the Todo.txt-formatted file:"));
+  frame = gtk_frame_new (NULL);
+  self->preferences = gtk_file_chooser_widget_new (GTK_FILE_CHOOSER_ACTION_SAVE);
+
+  gtk_container_add (GTK_CONTAINER (self->preferences_box), label);
+  gtk_container_add (GTK_CONTAINER (self->preferences_box), frame);
+  gtk_container_add (GTK_CONTAINER (frame), self->preferences);
+
+  gtk_widget_show_all (self->preferences_box);
+
+  g_signal_connect (self->preferences,
+                    "file-activated",
+                    G_CALLBACK (gtd_plugin_todo_txt_source_changed_cb),
+                    self);
+}
+
+/* Empty class_finalize method */
+static void
+gtd_plugin_todo_txt_class_finalize (GtdPluginTodoTxtClass *klass)
+{
+
+}
+
+G_MODULE_EXPORT void
+gtd_plugin_todo_txt_register_types (PeasObjectModule *module)
+{
+  gtd_plugin_todo_txt_register_type (G_TYPE_MODULE (module));
+
+  peas_object_module_register_extension_type (module,
+                                              GTD_TYPE_ACTIVATABLE,
+                                              GTD_TYPE_PLUGIN_TODO_TXT);
+}
diff --git a/plugins/todo-txt/gtd-plugin-todo-txt.h b/plugins/todo-txt/gtd-plugin-todo-txt.h
new file mode 100644
index 0000000..8fb1995
--- /dev/null
+++ b/plugins/todo-txt/gtd-plugin-todo-txt.h
@@ -0,0 +1,41 @@
+/* gtd-todo-txt-plugin.h
+ *
+ * Copyright (C) 2016 Rohit Kaushik <kaushikrohit325 gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTD_TODO_TXT_PLUGIN_H
+#define GTD_TODO_TXT_PLUGIN_H
+
+#include <glib.h>
+#include <gnome-todo.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_PLUGIN_TODO_TXT (gtd_plugin_todo_txt_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdPluginTodoTxt, gtd_plugin_todo_txt, GTD, PLUGIN_TODO_TXT, PeasExtensionBase)
+
+G_MODULE_EXPORT void  gtd_plugin_todo_txt_register_types      (PeasObjectModule   *module);
+
+void     gtd_plugin_todo_txt_monitor_source      (GFileMonitor      *monitor,
+                                                  GFile             *first,
+                                                  GFile             *second,
+                                                  GFileMonitorEvent  event,
+                                                  gpointer           data);
+
+G_END_DECLS
+
+#endif /* GTD_TODO_TXT_PLUGIN_H */
diff --git a/plugins/todo-txt/gtd-provider-todo-txt.c b/plugins/todo-txt/gtd-provider-todo-txt.c
new file mode 100644
index 0000000..f012f3a
--- /dev/null
+++ b/plugins/todo-txt/gtd-provider-todo-txt.c
@@ -0,0 +1,1208 @@
+/* gtd-provider-todo-txt.c
+ *
+ * Copyright (C) 2016 Rohit Kaushik <kaushikrohit325 gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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>
+
+#include <glib/gi18n.h>
+
+
+struct _GtdProviderTodoTxt
+{
+  GtdObject          parent;
+
+  GIcon              *icon;
+
+  GHashTable         *lists;
+  GHashTable         *root_tasks;
+
+  GFileMonitor       *monitor;
+  GFile              *source_file;
+
+  gchar              *source;
+  GList              *tasklists;
+
+  gint                no_of_lines;
+};
+
+static void          gtd_provider_iface_init                     (GtdProviderInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtdProviderTodoTxt, gtd_provider_todo_txt, GTD_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GTD_TYPE_PROVIDER,
+                                                gtd_provider_iface_init))
+
+enum {
+  PROP_0,
+  PROP_ENABLED,
+  PROP_ICON,
+  PROP_ID,
+  PROP_NAME,
+  PROP_DESCRIPTION,
+  PROP_SOURCE,
+  LAST_PROP
+};
+
+/*
+ * GtdProviderInterface implementation
+ */
+static const gchar*
+gtd_provider_todo_txt_get_id (GtdProvider *provider)
+{
+  return "todo-txt";
+}
+
+static const gchar*
+gtd_provider_todo_txt_get_name (GtdProvider *provider)
+{
+  return _("Todo.txt");
+}
+
+static const gchar*
+gtd_provider_todo_txt_get_description (GtdProvider *provider)
+{
+  return _("On the todo.txt file");
+}
+
+
+static gboolean
+gtd_provider_todo_txt_get_enabled (GtdProvider *provider)
+{
+  return TRUE;
+}
+
+static GIcon*
+gtd_provider_todo_txt_get_icon (GtdProvider *provider)
+{
+  GtdProviderTodoTxt *self;
+
+  self = GTD_PROVIDER_TODO_TXT (provider);
+
+  return self->icon;
+}
+
+static const GtkWidget*
+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
+gtd_provider_todo_txt_load_task (TaskData           *td,
+                                 GtdProviderTodoTxt *self,
+                                 gint                line_number)
+{
+  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)
+    {
+      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);
+
+          g_hash_table_insert (self->root_tasks, root_task_name, root_task);
+        }
+
+      sub_task = gtd_provider_todo_txt_create_new_task ();
+
+      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);
+
+      g_object_set_data (G_OBJECT (sub_task), "line", GINT_TO_POINTER (line_number));
+
+      gtd_task_add_subtask (root_task, sub_task);
+      gtd_task_list_save_task (task_list, sub_task);
+    }
+  else
+    {
+      GtdTask *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);
+        }
+      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);
+    }
+}
+
+static void
+gtd_provider_todo_txt_create_empty_list (GtdProviderTodoTxt *self,
+                                         gchar              *line)
+{
+  GtdTaskList *task_list;
+
+  if (g_hash_table_contains (self->lists, line))
+    return;
+
+  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, line);
+  self->tasklists = g_list_append (self->tasklists,
+                                           task_list);
+  g_object_set_data (G_OBJECT (task_list), "line", line);
+
+  g_signal_emit_by_name (self, "list-added", task_list);
+  g_hash_table_insert (self->lists, line, task_list);
+}
+
+static void
+gtd_provider_todo_txt_load_source (GtdProviderTodoTxt *self)
+{
+  GFileInputStream *readstream;
+  GError *error = NULL;
+  gint line_number = 0;
+
+  g_return_if_fail (G_IS_FILE (self->source_file));
+
+  readstream = g_file_read (self->source_file,
+                            NULL,
+                            &error);
+
+  if (!error)
+    {
+      GDataInputStream *reader;
+      gchar *line_read;
+      GError *line_read_error = NULL;
+      TaskData *td = NULL;
+
+      reader = g_data_input_stream_new (G_INPUT_STREAM (readstream));
+      self->no_of_lines = 0;
+
+      while (!line_read_error)
+        {
+          GList *tokens = NULL;
+          gboolean valid;
+          line_read = g_data_input_stream_read_line (reader,
+                                                     NULL,
+                                                     NULL,
+                                                     &line_read_error);
+
+          if (!line_read_error)
+            {
+              if (!line_read)
+                break;
+
+              line_number++;
+              self->no_of_lines++;
+
+              tokens = gtd_todo_txt_parser_tokenize (g_strdup(line_read));
+              valid = gtd_todo_txt_parser_validate_token_format (tokens);
+
+              if (valid)
+                {
+                  td = gtd_todo_txt_parser_parse_tokens (tokens);
+
+                  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);
+                }
+            }
+          else
+            {
+              g_warning ("%s: %s: %s",
+                 G_STRFUNC,
+                 _("Error reading line from Todo.txt"),
+                    line_read_error->message);
+
+              gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                             _("Error reading line from Todo.txt"),
+                                               line_read_error->message);
+              g_error_free (line_read_error);
+
+              return;
+            }
+
+          g_list_free_full (tokens, g_free);
+          g_free (line_read);
+        }
+    }
+  else
+    {
+      g_warning ("%s: %s: %s",
+                 G_STRFUNC,
+                 _("Error opening Todo.txt"),
+                   error->message);
+
+      gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                      _("Error opening Todo.txt"),
+                                        error->message);
+      g_error_free (error);
+      return;
+    }
+}
+
+static void
+gtd_provider_todo_txt_create_task (GtdProvider *provider,
+                                   GtdTask     *task)
+{
+  GtdProviderTodoTxt *self;
+  GFileOutputStream *write_stream;
+  GtdTaskList *list;
+  GError *error;
+  const gchar *list_name;
+  const gchar *task_description;
+  gchar *task_line;
+
+  self = GTD_PROVIDER_TODO_TXT (provider);
+  error = NULL;
+
+  g_return_if_fail (G_IS_FILE (self->source_file));
+
+  if (self->monitor)
+    g_signal_handlers_block_by_func(self->monitor, gtd_plugin_todo_txt_monitor_source, self);
+
+  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)
+    {
+      GDataOutputStream *writer;
+      GError *write_error = NULL;
+
+      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 adding task to Todo.txt"),
+                       write_error->message);
+
+          gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                      _("Error adding task to Todo.txt"),
+                                        write_error->message);
+          g_error_free (write_error);
+          return;
+        }
+      else
+        {
+          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);
+    }
+  else
+    {
+      g_warning ("%s: %s: %s",
+                 G_STRFUNC,
+                 _("Error opening Todo.txt"),
+                   error->message);
+
+      gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                      _("Error opening Todo.txt"),
+                                        error->message);
+      g_error_free (error);
+    }
+  if (self->monitor)
+    g_signal_handlers_unblock_by_func(self->monitor, gtd_plugin_todo_txt_monitor_source, self);
+
+  g_free (task_line);
+}
+
+static void
+gtd_provider_todo_txt_update_task (GtdProvider *provider,
+                                   GtdTask     *task)
+{
+  GtdProviderTodoTxt *self;
+  GFileInputStream *readstream;
+  GFileOutputStream *outstream;
+  GDataOutputStream *writer;
+  GError *error;
+  GError *write_error;
+  gint line_to_update;
+  gint line_number;
+
+  self = GTD_PROVIDER_TODO_TXT (provider);
+  line_number = 0;
+  error = write_error = NULL;
+
+  if (self->monitor)
+    g_signal_handlers_block_by_func(self->monitor, gtd_plugin_todo_txt_monitor_source, self);
+
+  line_to_update = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (task), "line"));
+
+  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)
+    {
+      GDataInputStream *reader;
+      GError *line_read_error = NULL;
+      gchar *line_read;
+
+      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)
+            {
+              if (!line_read)
+                break;
+
+              line_number++;
+
+              tokens = gtd_todo_txt_parser_tokenize (g_strdup (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);
+                }
+            }
+          else
+            {
+              g_warning ("%s: %s: %s",
+                 G_STRFUNC,
+                 _("Error reading tasks from Todo.txt"),
+                    line_read_error->message);
+
+              gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                             _("Error reading tasks from Todo.txt"),
+                                               line_read_error->message);
+              g_error_free (line_read_error);
+            }
+
+          g_list_free_full (tokens, g_free);
+        }
+
+      g_output_stream_close (G_OUTPUT_STREAM (writer),
+                             NULL,
+                             NULL);
+    }
+  else
+    {
+      g_warning ("%s: %s: %s",
+                 G_STRFUNC,
+                 _("Error opening Todo.txt"),
+                   error->message);
+
+      gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                      _("Error opening Todo.txt"),
+                                        error->message);
+      g_error_free (error);
+    }
+  if (self->monitor)
+    g_signal_handlers_unblock_by_func(self->monitor, gtd_plugin_todo_txt_monitor_source, self);
+}
+
+static void
+gtd_provider_todo_txt_remove_task (GtdProvider *provider,
+                                   GtdTask     *task)
+{
+  GtdProviderTodoTxt *self;
+  GFileInputStream *readstream;
+  GFileOutputStream *outstream;
+  GDataOutputStream *writer;
+  GError *error;
+  GError *write_error;
+  gint line_number;
+  gint line_number_to_remove;
+
+  self = GTD_PROVIDER_TODO_TXT (provider);
+  error = write_error = NULL;
+  line_number = 0;
+
+  g_return_if_fail (G_IS_FILE (self->source_file));
+
+  if (self->monitor)
+    g_signal_handlers_block_by_func(self->monitor, gtd_plugin_todo_txt_monitor_source, self);
+
+  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)
+    {
+      GDataInputStream *reader;
+      GError *line_read_error = NULL;
+      gchar *line_read;
+      gboolean skip;
+
+      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)
+            {
+              if (!line_read)
+                break;
+              line_number++;
+
+              tokens = gtd_todo_txt_parser_tokenize (g_strdup(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);
+                }
+            }
+          else
+            {
+              g_warning ("%s: %s: %s",
+                 G_STRFUNC,
+                 _("Error reading tasks from Todo.txt"),
+                    line_read_error->message);
+
+              gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                             _("Error reading tasks from Todo.txt"),
+                                               line_read_error->message);
+              g_error_free (line_read_error);
+
+              return;
+            }
+          g_free (td);
+        }
+
+      g_output_stream_close (G_OUTPUT_STREAM (writer),
+                             NULL,
+                             NULL);
+    }
+  else
+    {
+      g_warning ("%s: %s: %s",
+                 G_STRFUNC,
+                 _("Error opening Todo.txt"),
+                   error->message);
+
+      gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                      _("Error opening Todo.txt"),
+                                        error->message);
+      g_error_free (error);
+    }
+  if (self->monitor)
+    g_signal_handlers_unblock_by_func(self->monitor, gtd_plugin_todo_txt_monitor_source, self);
+}
+
+static void
+gtd_provider_todo_txt_create_task_list (GtdProvider *provider,
+                                        GtdTaskList *list)
+{
+  GtdProviderTodoTxt *self;
+  GFileOutputStream  *write_stream;
+  GError *error;
+  const gchar *name;
+
+  self = GTD_PROVIDER_TODO_TXT (provider);
+  error = NULL;
+
+  g_return_if_fail (G_IS_FILE (self->source_file));
+
+  if (self->monitor)
+    g_signal_handlers_block_by_func (self->monitor, gtd_plugin_todo_txt_monitor_source, self);
+
+  write_stream = g_file_append_to (self->source_file,
+                                  G_FILE_CREATE_REPLACE_DESTINATION,
+                                  NULL,
+                                  &error);
+
+  if(!error)
+    {
+      GDataOutputStream *writer;
+      GError *write_error = NULL;
+      gchar *put;
+
+      name = gtd_task_list_get_name (list);
+      writer = g_data_output_stream_new (G_OUTPUT_STREAM (write_stream));
+
+      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 creating Todo.txt list"),
+                       write_error->message);
+
+          gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                      _("Error creating Todo.txt list"),
+                                        write_error->message);
+          g_error_free (write_error);
+          return;
+        }
+      else
+        {
+          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++;
+        }
+
+      g_free (put);
+    }
+  else
+    {
+      g_warning ("%s: %s: %s",
+                 G_STRFUNC,
+                 _("Error opening Todo.txt"),
+                   error->message);
+
+      gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                      _("Error opening Todo.txt"),
+                                        error->message);
+      g_error_free (error);
+    }
+  if (self->monitor)
+    g_signal_handlers_unblock_by_func(self->monitor, gtd_plugin_todo_txt_monitor_source, self);
+}
+
+static void
+gtd_provider_todo_txt_update_task_list (GtdProvider *provider,
+                                        GtdTaskList *list)
+{
+  GtdProviderTodoTxt *self;
+  GFileInputStream *readstream;
+  GFileOutputStream *outstream;
+  GDataOutputStream *writer;
+  GError *error;
+  GError *write_error;
+  const gchar *current_list_name;
+  gchar *stored_list_name;
+
+  self = GTD_PROVIDER_TODO_TXT (provider);
+  error = write_error = NULL;
+
+  g_return_if_fail (G_IS_FILE (self->source_file));
+
+  if (self->monitor)
+    g_signal_handlers_block_by_func(self->monitor, gtd_plugin_todo_txt_monitor_source, self);
+
+  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)
+    {
+      GDataInputStream *reader;
+      GError *line_read_error = NULL;
+      char *line_read;
+
+      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;
+
+          tokens = NULL;
+          line_read = g_data_input_stream_read_line (reader,
+                                                     NULL,
+                                                     NULL,
+                                                     &line_read_error);
+
+          if (!line_read_error)
+            {
+              if (!line_read)
+                break;
+
+              tokens = gtd_todo_txt_parser_tokenize (g_strdup(line_read));
+              valid = gtd_todo_txt_parser_validate_token_format (tokens);
+
+              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);
+                }
+            }
+          else
+            {
+              g_warning ("%s: %s: %s",
+                         G_STRFUNC,
+                         _("Error reading tasks from Todo.txt"),
+                         line_read_error->message);
+
+              gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                             _("Error reading tasks from Todo.txt"),
+                                               line_read_error->message);
+              g_error_free (line_read_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);
+    }
+  else
+    {
+      g_warning ("%s: %s: %s",
+                 G_STRFUNC,
+                 _("Error opening Todo.txt"),
+                   error->message);
+
+      gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                      _("Error opening Todo.txt"),
+                                        error->message);
+      g_error_free (error);
+    }
+  g_input_stream_close (G_INPUT_STREAM (readstream),
+                        NULL,
+                        NULL);
+  g_output_stream_close (G_OUTPUT_STREAM (outstream),
+                         NULL,
+                         NULL);
+  if (self->monitor)
+    g_signal_handlers_unblock_by_func(self->monitor, gtd_plugin_todo_txt_monitor_source, self);
+}
+
+static void
+gtd_provider_todo_txt_remove_task_list (GtdProvider *provider,
+                                        GtdTaskList *list)
+{
+
+  GtdProviderTodoTxt *self;
+  GFileOutputStream *outstream;
+  GDataOutputStream *writer;
+  GFileInputStream *readstream;
+  GError *write_error;
+  GError *error;
+  const gchar  *list_name;
+
+  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));
+
+  if (self->monitor)
+    g_signal_handlers_block_by_func(self->monitor, gtd_plugin_todo_txt_monitor_source, self);
+
+  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)
+    {
+      GDataInputStream *reader;
+      GError *line_read_error = NULL;
+      char *line;
+      gboolean skip;
+
+      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;
+
+          if (!line_read_error)
+            {
+              if (!line)
+                break;
+
+              tokens = gtd_todo_txt_parser_tokenize (g_strdup(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_data_output_stream_put_string (writer,
+                                                   line,
+                                                   NULL,
+                                                   &write_error);
+                }
+            }
+          else
+            {
+              g_warning ("%s: %s: %s",
+                 G_STRFUNC,
+                 _("Error reading task-lists from Todo.txt"),
+                    line_read_error->message);
+
+              gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                             _("Error reading task-lists from Todo.txt"),
+                                               line_read_error->message);
+              g_error_free (line_read_error);
+            }
+          g_free (td);
+        }
+      g_output_stream_close (G_OUTPUT_STREAM (writer),
+                             NULL,
+                             NULL);
+    }
+  else
+    {
+      g_warning ("%s: %s: %s",
+                 G_STRFUNC,
+                 _("Error opening Todo.txt"),
+                   error->message);
+
+      gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                      _("Error opening Todo.txt"),
+                                        error->message);
+      g_error_free (error);
+    }
+  if (self->monitor)
+    g_signal_handlers_unblock_by_func(self->monitor, gtd_plugin_todo_txt_monitor_source, self);
+}
+
+static GList*
+gtd_provider_todo_txt_get_task_lists (GtdProvider *provider)
+{
+  GtdProviderTodoTxt *self;
+
+  self = GTD_PROVIDER_TODO_TXT (provider);
+
+  return self->tasklists;
+}
+
+static GtdTaskList*
+gtd_provider_todo_txt_get_default_task_list (GtdProvider *provider)
+{
+  return NULL;
+}
+
+static void
+gtd_provider_iface_init (GtdProviderInterface *iface)
+{
+  iface->get_id = gtd_provider_todo_txt_get_id;
+  iface->get_name = gtd_provider_todo_txt_get_name;
+  iface->get_description = gtd_provider_todo_txt_get_description;
+  iface->get_enabled = gtd_provider_todo_txt_get_enabled;
+  iface->get_icon = gtd_provider_todo_txt_get_icon;
+  iface->get_edit_panel = gtd_provider_todo_txt_get_edit_panel;
+  iface->create_task = gtd_provider_todo_txt_create_task;
+  iface->update_task = gtd_provider_todo_txt_update_task;
+  iface->remove_task = gtd_provider_todo_txt_remove_task;
+  iface->create_task_list = gtd_provider_todo_txt_create_task_list;
+  iface->update_task_list = gtd_provider_todo_txt_update_task_list;
+  iface->remove_task_list = gtd_provider_todo_txt_remove_task_list;
+  iface->get_task_lists = gtd_provider_todo_txt_get_task_lists;
+  iface->get_default_task_list = gtd_provider_todo_txt_get_default_task_list;
+}
+
+GtdProviderTodoTxt*
+gtd_provider_todo_txt_new (gchar *source)
+{
+
+  return g_object_new (GTD_TYPE_PROVIDER_TODO_TXT,
+                       "source", source,
+                       NULL);
+}
+
+static void
+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->source_file, g_free);
+  g_clear_object (&self->icon);
+  g_clear_pointer (&self->source, g_free);
+
+  G_OBJECT_CLASS (gtd_provider_todo_txt_parent_class)->finalize (object);
+}
+
+static void
+gtd_provider_todo_txt_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+  GtdProvider *provider = GTD_PROVIDER (object);
+
+  switch (prop_id)
+    {
+    case PROP_DESCRIPTION:
+      g_value_set_string (value, gtd_provider_todo_txt_get_description (provider));
+      break;
+
+    case PROP_ENABLED:
+      g_value_set_boolean (value, gtd_provider_todo_txt_get_enabled (provider));
+      break;
+
+    case PROP_ICON:
+      g_value_set_object (value, gtd_provider_todo_txt_get_icon (provider));
+      break;
+
+    case PROP_ID:
+      g_value_set_string (value, gtd_provider_todo_txt_get_id (provider));
+      break;
+
+    case PROP_NAME:
+      g_value_set_string (value, gtd_provider_todo_txt_get_name (provider));
+      break;
+
+    case PROP_SOURCE:
+      g_value_set_string (value, GTD_PROVIDER_TODO_TXT (provider)->source);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_provider_todo_txt_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+  GtdProviderTodoTxt *self = GTD_PROVIDER_TODO_TXT (object);
+  switch (prop_id)
+    {
+    case PROP_SOURCE:
+      self->source = g_value_dup_string (value);
+      self->source_file = g_file_new_for_uri (self->source);
+      gtd_provider_todo_txt_load_source (self);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_provider_todo_txt_class_init (GtdProviderTodoTxtClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gtd_provider_todo_txt_finalize;
+  object_class->get_property = gtd_provider_todo_txt_get_property;
+  object_class->set_property = gtd_provider_todo_txt_set_property;
+
+  g_object_class_install_property (object_class,
+                                   PROP_SOURCE,
+                                   g_param_spec_string ("source",
+                                                        "Source file",
+                                                        "The Todo.txt source file",
+                                                         NULL,
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  g_object_class_override_property (object_class, PROP_DESCRIPTION, "description");
+  g_object_class_override_property (object_class, PROP_ENABLED, "enabled");
+  g_object_class_override_property (object_class, PROP_ICON, "icon");
+  g_object_class_override_property (object_class, PROP_ID, "id");
+  g_object_class_override_property (object_class, PROP_NAME, "name");
+}
+
+static void
+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);
+
+  /* icon */
+  self->icon = G_ICON (g_themed_icon_new_with_default_fallbacks ("computer-symbolic"));
+}
+
+void
+gtd_provider_todo_txt_set_monitor (GtdProviderTodoTxt *self,
+                                   GFileMonitor       *monitor)
+{
+  g_return_if_fail (GTD_IS_PROVIDER_TODO_TXT (self));
+
+  self->monitor = monitor;
+}
diff --git a/plugins/todo-txt/gtd-provider-todo-txt.h b/plugins/todo-txt/gtd-provider-todo-txt.h
new file mode 100644
index 0000000..fe09857
--- /dev/null
+++ b/plugins/todo-txt/gtd-provider-todo-txt.h
@@ -0,0 +1,39 @@
+/* gtd-provider-todo-txt.h
+ *
+ * Copyright (C) 2016 Rohit Kaushik <kaushikrohit325 gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTD_PROVIDER_TODO_TXT_H
+#define GTD_PROVIDER_TODO_TXT_H
+
+#include <glib.h>
+
+#include <gnome-todo.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_PROVIDER_TODO_TXT (gtd_provider_todo_txt_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdProviderTodoTxt, gtd_provider_todo_txt, GTD, PROVIDER_TODO_TXT, GtdObject)
+
+GtdProviderTodoTxt*    gtd_provider_todo_txt_new                     (gchar          *source);
+
+void                   gtd_provider_todo_txt_set_monitor             (GtdProviderTodoTxt *self,
+                                                                      GFileMonitor       *monitor);
+
+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
new file mode 100644
index 0000000..44a6b1e
--- /dev/null
+++ b/plugins/todo-txt/gtd-todo-txt-parser.c
@@ -0,0 +1,582 @@
+/* gtd-task-list.c
+ *
+ * Copyright (C) 2017 Rohit Kaushik <kaushikrohit325 gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+#include <gtd-todo-txt-parser.h>
+
+struct _GtdTodoTxtParser
+{
+  GtdObject          parent;
+};
+
+enum {
+  TASK_COMPLETE,
+  TASK_PRIORITY,
+  TASK_DATE,
+  TASK_TITLE,
+  TASK_LIST_NAME,
+  ROOT_TASK_NAME,
+  TASK_DUE_DATE
+};
+
+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)
+{
+  switch (token[1])
+    {
+    case 'A':
+      return 3;
+      break;
+
+    case 'B':
+      return 2;
+      break;
+
+    case 'C':
+      return 1;
+      break;
+
+    default:
+      return 0;
+    }
+
+  return 0;
+}
+
+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 ();
+
+  g_date_set_parse (date, token);
+
+  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);
+
+  dt = g_date_time_new_utc (year,
+                            month,
+                            day,
+                            0, 0, 0);
+  g_date_free (date);
+
+  return dt;
+}
+
+gboolean
+gtd_todo_txt_parser_is_date (gchar *dt)
+{
+  GDate   *date = NULL;
+
+  date = g_date_new ();
+  g_date_set_parse (date, dt);
+
+  if (!g_date_valid (date))
+    return FALSE;
+
+  g_date_free (date);
+
+  return TRUE;
+}
+
+gboolean
+gtd_todo_txt_parser_is_word (gchar *token)
+{
+  guint pos;
+
+  for (pos = 0; pos < strlen (token); pos++)
+    {
+      if (!g_unichar_isalnum (token[pos]))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+gint
+gtd_todo_txt_parser_get_token_id (gchar *token,
+                                  gint last_read)
+{
+  gint token_length;
+
+  token_length = strlen (token);
+
+  if (!g_strcmp0 (token, "x"))
+    return TASK_COMPLETE;
+
+  if (token_length == 3)
+    {
+      if (token[0] == '(' && token[2] == ')')
+        return TASK_PRIORITY;
+    }
+
+  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;
+    }
+
+  if (token_length > 1)
+    {
+      if (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)
+    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)
+{
+  GDateTime *dt;
+  TaskData *td;
+  GList *it;
+  gint last_read_token;
+  gint token_id;
+
+  dt = NULL;
+  it = NULL;
+  td = task_data_new ();
+
+  last_read_token = TASK_COMPLETE;
+
+  for (it = tk; it != NULL; it = it->next)
+    {
+      gchar *str;
+
+      str = it->data;
+      token_id = gtd_todo_txt_parser_get_token_id (it->data, last_read_token);
+
+      switch (token_id)
+        {
+        case TASK_COMPLETE:
+          last_read_token = TASK_COMPLETE;
+          td->is_task_completed = TRUE;
+          break;
+
+        case TASK_PRIORITY:
+          last_read_token = TASK_PRIORITY;
+          td->priority = gtd_todo_txt_parser_get_priority (it->data);
+          break;
+
+        case TASK_DATE:
+          last_read_token = TASK_DATE;
+          dt = gtd_todo_txt_parser_get_date (it->data);
+          td->creation_date = dt;
+          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);
+            }
+          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);
+            }
+          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;
+          break;
+
+        case TASK_DUE_DATE:
+          last_read_token = TASK_DUE_DATE;
+          dt = gtd_todo_txt_parser_get_date (&str[4]);
+          td->due_date = dt;
+          break;
+
+        default:
+          return NULL;
+        }
+    }
+  return td;
+}
+
+gboolean
+gtd_todo_txt_parser_validate_token_format (GList *tokens)
+{
+  GList *it = NULL;
+  gint token_id;
+  gint position = 0;
+
+  gboolean complete_tk = FALSE;
+  gboolean priority_tk = FALSE;
+  gboolean task_list_name_tk = FALSE;
+
+  gint last_read = TASK_COMPLETE;
+
+  for (it = tokens; it != NULL; it = it->next)
+    {
+      gchar *str;
+
+      str = it->data;
+      token_id = gtd_todo_txt_parser_get_token_id (it->data, last_read);
+      position++;
+
+      switch (token_id)
+        {
+        case TASK_COMPLETE:
+          last_read = TASK_COMPLETE;
+          if (position != 1)
+            {
+              gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                  _("Task Completion token x should be at the start of line"),
+                                  _("Skipping this line"));
+              return FALSE;
+            }
+          else
+            complete_tk = TRUE;
+          break;
+
+        case TASK_PRIORITY:
+          last_read = TASK_PRIORITY;
+          if (position != (complete_tk + 1))
+            {
+              gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                  _("Task Prirority should be at the start of line"),
+                                  _("Skipping this line"));
+              return FALSE;
+            }
+          else
+            priority_tk = TRUE;
+          break;
+
+        case TASK_DATE:
+          last_read = TASK_DATE;
+
+          if (position != (complete_tk + priority_tk + 1))
+            return FALSE;
+          if (!gtd_todo_txt_parser_is_date (it->data))
+            {
+              gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                             _("Inccorect Date"),
+                                             _("Please make sure the date in todo.txt is valid."));
+              return FALSE;
+            }
+
+          break;
+
+        case TASK_TITLE:
+          last_read = TASK_TITLE;
+          break;
+
+        case TASK_LIST_NAME:
+          task_list_name_tk = TRUE;
+          last_read = TASK_LIST_NAME;
+          break;
+
+        case ROOT_TASK_NAME:
+          last_read = ROOT_TASK_NAME;
+          break;
+
+        case TASK_DUE_DATE:
+          last_read = TASK_DUE_DATE;
+          if (!gtd_todo_txt_parser_is_date (&str[4]))
+            {
+              gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                             _("Incorrect Due Date"),
+                                             _("Please make sure the due date in todo.txt is valid.Tasks 
with invalid date are not loaded"));
+              return FALSE;
+            }
+          break;
+
+        default:
+          gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                       _("Unrecognised Token in Todo.Txt line"),
+                                       _("To Do cannot recognise some tags in your todo.txt file.Some tasks 
may not be loaded"));
+          return FALSE;
+          break;
+        }
+    }
+
+  if (!task_list_name_tk)
+    {
+      gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                    _("No Tasklist found for some tasks"),
+                                    _("Some of tasks in your todo.txt file do not have tasklist.To Do 
supports tasks with Tasklist.Please add list to all your tasks"));
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+GList*
+gtd_todo_txt_parser_tokenize (gchar *line)
+{
+  GList *tokens = NULL;
+  gchar **token = NULL;
+
+  token = g_strsplit (line, " ", -1);
+
+  while (*token)
+  {
+    g_strstrip (*token);
+    tokens = g_list_prepend (tokens, g_strdup(*token));
+    token++;
+  }
+  tokens = g_list_reverse (tokens);
+
+  g_free (line);
+
+  return tokens;
+}
+
+GList*
+gtd_todo_txt_parser_get_list_updated_token (GtdTaskList *list,
+                                            gchar       *line)
+{
+  gint last_read_token = TASK_COMPLETE;
+  gboolean list_name_updated = FALSE;
+  GList *tokens = NULL;
+  GList *it = NULL;
+
+  tokens = gtd_todo_txt_parser_tokenize (g_strdup(line));
+
+  for (it = tokens; it != NULL; it = it->next)
+    {
+      gint token_id;
+
+      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;
+            }
+
+          else
+            {
+              it->data = g_strconcat ("@", gtd_task_list_get_name(list), NULL);
+              list_name_updated = TRUE;
+            }
+        }
+    }
+
+  return tokens;
+}
+
+GList*
+gtd_todo_txt_parser_get_task_line (GtdTask *task)
+{
+  GtdTaskList *list;
+  GDateTime   *dt;
+  GtdTask *parent;
+  GList *tokens = NULL;
+  gint priority;
+  gboolean is_complete;
+  const gchar *list_name;
+  const gchar *title;
+
+  is_complete = gtd_task_get_complete (task);
+  title = gtd_task_get_title (task);
+  priority = gtd_task_get_priority (task);
+  dt = gtd_task_get_due_date (task);
+  list = gtd_task_get_list (task);
+  parent = gtd_task_get_parent (task);
+
+  list_name = gtd_task_list_get_name (list);
+
+  if (is_complete)
+    tokens = g_list_append (tokens, g_strdup ("x"));
+
+  if (priority)
+    {
+      if (priority == 1)
+        tokens = g_list_append (tokens, g_strdup ("(C)"));
+      else if (priority == 2)
+        tokens = g_list_append (tokens, g_strdup ("(B)"));
+      else if (priority == 3)
+        tokens = g_list_append (tokens, g_strdup ("(A)"));
+    }
+
+  tokens = g_list_append (tokens, g_strdup (title));
+  tokens = g_list_append (tokens, g_strconcat ("@", list_name, NULL));
+
+  if (parent)
+    tokens = g_list_append (tokens, g_strconcat ("+", gtd_task_get_title (parent), NULL));
+
+  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;
+}
+
+gchar*
+gtd_todo_txt_parser_task_data_get_title (TaskData *td)
+{
+  return td->title;
+}
+
+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;
+}
+
+gboolean
+gtd_todo_txt_parser_task_data_is_task_completed (TaskData *td)
+{
+  return td->is_task_completed;
+}
+
+gint
+gtd_todo_txt_parser_task_data_get_priority (TaskData *td)
+{
+  return td->priority;
+}
+
+static void
+gtd_todo_txt_parser_get_property (GObject    *object,
+                            guint       prop_id,
+                            GValue     *value,
+                            GParamSpec *pspec)
+{
+  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+}
+
+static void
+gtd_todo_txt_parser_set_property (GObject      *object,
+                                  guint         prop_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+}
+
+static void
+gtd_todo_txt_parser_class_init (GtdTodoTxtParserClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->get_property = gtd_todo_txt_parser_get_property;
+  object_class->set_property = gtd_todo_txt_parser_set_property;
+
+}
+
+static void
+gtd_todo_txt_parser_init (GtdTodoTxtParser *self)
+{
+  ;
+}
diff --git a/plugins/todo-txt/gtd-todo-txt-parser.h b/plugins/todo-txt/gtd-todo-txt-parser.h
new file mode 100644
index 0000000..65eb749
--- /dev/null
+++ b/plugins/todo-txt/gtd-todo-txt-parser.h
@@ -0,0 +1,73 @@
+/* gtd-todo-txt-parser.h
+ *
+ * Copyright (C) 2017 Rohit Kaushik <kaushikrohit325 gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTD_TODO_TXT_PARSE_H
+#define GTD_TODO_TXT_PARSE_H
+
+#include <glib.h>
+#include <gnome-todo.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_TODO_TXT_PARSER (gtd_todo_txt_parser_get_type())
+
+typedef struct _TaskData TaskData;
+
+G_DECLARE_FINAL_TYPE (GtdTodoTxtParser, gtd_todo_txt_parser, GTD, TODO_TXT_PARSER, GtdObject)
+
+gint          gtd_todo_txt_parser_get_priority                    (gchar       *token);
+
+GDateTime*    gtd_todo_txt_parser_get_date                        (gchar       *token);
+
+gboolean      gtd_todo_txt_parser_is_date                         (gchar       *dt);
+
+gboolean      gtd_todo_txt_parser_is_word                         (gchar       *token);
+
+gint          gtd_todo_txt_parser_get_token_id                    (gchar       *token,
+                                                                   gint         last_read);
+
+TaskData*     gtd_todo_txt_parser_parse_tokens                    (GList       *tk);
+
+gboolean      gtd_todo_txt_parser_validate_token_format           (GList       *tokens);
+
+GList*        gtd_todo_txt_parser_tokenize                        (gchar       *line);
+
+GList*        gtd_todo_txt_parser_get_list_updated_token          (GtdTaskList *list,
+                                                                   gchar       *line);
+
+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);
+
+G_END_DECLS
+
+#endif /* GTD_TODO_TXT_PARSER_H */
diff --git a/plugins/todo-txt/org.gnome.todo.txt.gschema.xml b/plugins/todo-txt/org.gnome.todo.txt.gschema.xml
new file mode 100644
index 0000000..a2da741
--- /dev/null
+++ b/plugins/todo-txt/org.gnome.todo.txt.gschema.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schemalist gettext-domain="gnome-todo">
+    <schema id="org.gnome.todo.plugins.todo-txt" path="/org/gnome/todo/plugins/todo-txt/">
+        <key name="file" type="s">
+            <default>''</default>
+            <summary>Todo Txt File </summary>
+            <description>Source of Todo.txt file</description>
+        </key>
+    </schema>
+</schemalist>
diff --git a/plugins/todo-txt/todo-txt.plugin.in b/plugins/todo-txt/todo-txt.plugin.in
new file mode 100644
index 0000000..610c468
--- /dev/null
+++ b/plugins/todo-txt/todo-txt.plugin.in
@@ -0,0 +1,13 @@
+[Plugin]
+Name = Todo.Txt
+Module = todo-txt
+Description = Todo.txt plugin for GNOME To Do
+Version = @VERSION@
+Authors = Rohit Kaushik <kaushikrohit325 gmail com>
+Copyright = Copyleft © The To Do maintainers
+Website = https://wiki.gnome.org/Apps/Todo
+Builtin = true
+License = GPL
+Loader = C
+Embedded = gtd_plugin_todo_txt_register_types
+Depends =
diff --git a/src/Makefile.am b/src/Makefile.am
index edf4e6a..703597d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -102,6 +102,7 @@ gnome_todo_LDFLAGS = \
        -Wl,--undefined=gtd_plugin_dark_theme_register_types \
        -Wl,--undefined=gtd_plugin_scheduled_panel_register_types \
        -Wl,--undefined=gtd_plugin_today_panel_register_types \
+        -Wl,--undefined=gtd_plugin_todo_txt_register_types \
        -lm \
        $(GNOME_TODO_WARN_LDFLAGS)
 
@@ -110,13 +111,15 @@ gnome_todo_LDADD = \
        $(top_builddir)/plugins/dark-theme/libdarktheme.la \
        $(top_builddir)/plugins/scheduled-panel/libscheduledpanel.la \
        $(top_builddir)/plugins/today-panel/libtodaypanel.la \
+        $(top_builddir)/plugins/todo-txt/libtodotxt.la \
        $(GNOME_TODO_LIBS)
 
 gnome_todo_DEPENDENCIES = \
        $(top_builddir)/plugins/eds/libeds.la \
        $(top_builddir)/plugins/dark-theme/libdarktheme.la \
        $(top_builddir)/plugins/scheduled-panel/libscheduledpanel.la \
-       $(top_builddir)/plugins/today-panel/libtodaypanel.la
+       $(top_builddir)/plugins/today-panel/libtodaypanel.la \
+        $(top_builddir)/plugins/todo-txt/libtodotxt.la
 
 #
 # Export headers to [PREFIX]/include/gnome-todo


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