todo-txt: Rework parser

This commit introduces an improved and more robust
Todo.txt parser, but has one major drawback that we
have to figure out before the release: the Todo.txt
provider stopped supporting parent/child tasks.
parent 8af61ded
......@@ -18,6 +18,7 @@
#define G_LOG_DOMAIN "GtdPluginTodoTxt"
#include "gtd-debug.h"
#include "gtd-plugin-todo-txt.h"
#include "gtd-provider-todo-txt.h"
......@@ -53,88 +54,29 @@ enum
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))
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))
/*
* GtdActivatable interface implementation
*/
static void
gtd_plugin_todo_txt_activate (GtdActivatable *activatable)
{
;
}
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
* Auxiliary methods
*/
static gboolean
gtd_plugin_todo_txt_set_default_source (GtdPluginTodoTxt *self)
set_default_source (GtdPluginTodoTxt *self)
{
g_autofree gchar *default_file;
GError *error;
g_autofree gchar *default_file = NULL;
g_autoptr (GError) error = NULL;
error = NULL;
default_file = g_build_filename (g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS),
"todo.txt",
NULL);
GTD_ENTRY;
default_file = g_build_filename (g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS), "todo.txt", NULL);
self->source_file = g_file_new_for_path (default_file);
if (g_file_query_exists (self->source_file, NULL))
return TRUE;
GTD_RETURN (TRUE);
g_file_create (self->source_file,
G_FILE_CREATE_NONE,
NULL,
&error);
g_file_create (self->source_file, G_FILE_CREATE_NONE, NULL, &error);
if (error)
{
......@@ -143,39 +85,35 @@ gtd_plugin_todo_txt_set_default_source (GtdPluginTodoTxt *self)
error->message,
NULL,
NULL);
g_clear_error (&error);
return FALSE;
GTD_RETURN (FALSE);
}
return TRUE;
GTD_RETURN (TRUE);
}
static gboolean
gtd_plugin_todo_txt_set_source (GtdPluginTodoTxt *self)
setup_source (GtdPluginTodoTxt *self)
{
GError *error;
gchar *source;
g_autoptr (GError) error = NULL;
g_autofree gchar *source = NULL;
GTD_ENTRY;
error = NULL;
source = g_settings_get_string (self->settings, "file");
if (!source || source[0] == '\0')
{
if (!gtd_plugin_todo_txt_set_default_source (self))
return FALSE;
if (!set_default_source (self))
GTD_RETURN (FALSE);
}
else
{
self->source_file = g_file_new_for_uri (source);
self->source_file = g_file_new_for_path (source);
}
if (!g_file_query_exists (self->source_file, NULL))
{
g_file_create (self->source_file,
G_FILE_CREATE_NONE,
NULL,
&error);
g_file_create (self->source_file, G_FILE_CREATE_NONE, NULL, &error);
if (error)
{
......@@ -184,46 +122,52 @@ gtd_plugin_todo_txt_set_source (GtdPluginTodoTxt *self)
error->message,
NULL,
NULL);
g_clear_error (&error);
return FALSE;
GTD_RETURN (FALSE);
}
}
return TRUE;
GTD_RETURN (TRUE);
}
/*
* Callbacks
*/
static void
gtd_plugin_todo_txt_source_changed_finished_cb (GtdPluginTodoTxt *self)
on_source_changed_finished_cb (GtdPluginTodoTxt *self)
{
GtdProviderTodoTxt *provider;
gboolean set;
set = gtd_plugin_todo_txt_set_source (self);
GTD_ENTRY;
set = setup_source (self);
if (!set)
return;
GTD_RETURN ();
provider = gtd_provider_todo_txt_new (self->source_file);
self->providers = g_list_append (self->providers, provider);
g_signal_emit_by_name (self, "provider-added", provider);
GTD_EXIT;
}
static void
gtd_plugin_todo_txt_source_changed_cb (GtkWidget *preference_panel,
gpointer user_data)
on_source_changed_cb (GtkWidget *preference_panel,
GtdPluginTodoTxt *self)
{
GtdPluginTodoTxt *self;
GtdProviderTodoTxt *provider;
self = GTD_PLUGIN_TODO_TXT (user_data);
GTD_ENTRY;
g_clear_object (&self->source_file);
g_settings_set_string (self->settings,
"file",
gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (self->preferences)));
gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (self->preferences)));
if (self->providers)
{
......@@ -235,9 +179,72 @@ gtd_plugin_todo_txt_source_changed_cb (GtkWidget *preference_panel,
g_signal_emit_by_name (self, "provider-removed", provider);
}
gtd_plugin_todo_txt_source_changed_finished_cb (self);
on_source_changed_finished_cb (self);
GTD_EXIT;
}
/*
* GtdActivatable implementation
*/
static void
gtd_plugin_todo_txt_activate (GtdActivatable *activatable)
{
;
}
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;
}
/*
* GObject overrides
*/
static void
gtd_plugin_todo_txt_finalize (GObject *object)
{
......@@ -272,12 +279,10 @@ 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->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");
g_object_class_override_property (object_class, PROP_PREFERENCES_PANEL, "preferences-panel");
}
static void
......@@ -288,7 +293,7 @@ gtd_plugin_todo_txt_init (GtdPluginTodoTxt *self)
gboolean set;
self->settings = g_settings_new ("org.gnome.todo.plugins.todo-txt");
set = gtd_plugin_todo_txt_set_source (self);
set = setup_source (self);
self->providers = NULL;
if (set)
......@@ -317,13 +322,9 @@ gtd_plugin_todo_txt_init (GtdPluginTodoTxt *self)
gtk_widget_show_all (self->preferences_box);
g_signal_connect (self->preferences,
"file-set",
G_CALLBACK (gtd_plugin_todo_txt_source_changed_cb),
self);
g_signal_connect (self->preferences, "file-set", G_CALLBACK (on_source_changed_cb), self);
}
/* Empty class_finalize method */
static void
gtd_plugin_todo_txt_class_finalize (GtdPluginTodoTxtClass *klass)
{
......
This diff is collapsed.
This diff is collapsed.
......@@ -25,33 +25,33 @@
G_BEGIN_DECLS
#define GTD_TYPE_TODO_TXT_PARSER (gtd_todo_txt_parser_get_type())
typedef enum
{
GTD_TODO_TXT_PARSER_INVALID_DUE_DATE,
GTD_TODO_TXT_PARSER_INVALID_LINE,
GTD_TODO_TXT_PARSER_UNSUPPORTED_TOKEN,
GTD_TODO_TXT_PARSER_WRONG_LINE_TYPE,
} GtdTodoTxtParserError;
typedef struct _TaskData TaskData;
typedef enum
{
GTD_TODO_TXT_LINE_TYPE_TASKLIST,
GTD_TODO_TXT_LINE_TYPE_TASK,
} GtdTodoTxtLineType;
G_DECLARE_FINAL_TYPE (GtdTodoTxtParser, gtd_todo_txt_parser, GTD, TODO_TXT_PARSER, GtdObject)
#define GTD_TODO_TXT_PARSER_ERROR (gtd_todo_txt_parser_error_quark ())
gint gtd_todo_txt_parser_get_priority (gchar *token);
GQuark gtd_todo_txt_parser_error_quark (void);
GDateTime* gtd_todo_txt_parser_get_date (gchar *token);
GtdTodoTxtLineType gtd_todo_txt_parser_get_line_type (const gchar *line,
GError **error);
gboolean gtd_todo_txt_parser_is_date (gchar *dt);
GtdTaskList* gtd_todo_txt_parser_parse_task_list (GtdProvider *provider,
const gchar *line);
gboolean gtd_todo_txt_parser_is_word (gchar *token);
gint gtd_todo_txt_parser_get_token_id (gchar *token,
gint last_read);
void gtd_todo_txt_parser_parse_tokens (GtdTask *task,
GList *tokens);
gboolean gtd_todo_txt_parser_validate_token_format (GList *tokens);
GList* gtd_todo_txt_parser_tokenize (const gchar *line);
gchar* gtd_todo_txt_parser_serialize_list (GtdTaskList *list);
gchar* gtd_todo_txt_parser_serialize_task (GtdTask *task);
GtdTask* gtd_todo_txt_parser_parse_task (GtdProvider *provider,
const gchar *line,
gchar **out_list_name);
G_END_DECLS
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment