[gnome-todo] todo-txt: introduce plugin to manage todo.txt files
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-todo] todo-txt: introduce plugin to manage todo.txt files
- Date: Tue, 14 Feb 2017 00:14:41 +0000 (UTC)
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]