After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 781079 - todo.txt: creating a second level subtask results in a new task with the subtask
todo.txt: creating a second level subtask results in a new task with the subtask
Status: RESOLVED FIXED
Product: gnome-todo
Classification: Other
Component: Plugins
unspecified
Other Linux
: High critical
: ---
Assigned To: GNOME To Do maintainer(s)
GNOME To Do maintainer(s)
Depends on:
Blocks:
 
 
Reported: 2017-04-09 04:12 UTC by Mohammed Sadiq
Modified: 2017-06-01 14:20 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Video (878.06 KB, video/mp4)
2017-04-23 00:13 UTC, Furqaan Shamsi
  Details
gtd_manager: remove old signals on provider-removal (1.80 KB, text/plain)
2017-05-19 13:59 UTC, Rohit Kaushik
  Details
file_monitor: move file-monitor from gtd-plugin to gtd-provider (7.75 KB, patch)
2017-05-19 14:15 UTC, Rohit Kaushik
needs-work Details | Review
gtd_provider_todo_txt: major rework on provider (43.53 KB, patch)
2017-05-19 16:03 UTC, Rohit Kaushik
needs-work Details | Review
plugin_todo_txt: rework on plugin (7.15 KB, patch)
2017-05-19 16:33 UTC, Rohit Kaushik
needs-work Details | Review
manager: remove old signals on provider-removal (1.80 KB, patch)
2017-05-19 18:42 UTC, Rohit Kaushik
committed Details | Review
todo_txt: move file-monitor from todo_txt_plugin to todo_txt_provider (7.71 KB, patch)
2017-05-19 19:10 UTC, Rohit Kaushik
needs-work Details | Review
todo-txt: move file-monitor from todo_txt_plugin to todo_txt_provider (8.42 KB, patch)
2017-05-20 06:56 UTC, Rohit Kaushik
none Details | Review
todo-txt: move file-monitor from todo_txt_plugin to todo_txt_provider (12.69 KB, patch)
2017-05-23 13:30 UTC, Rohit Kaushik
committed Details | Review
todo-txt: major rework on provider and parser (37.12 KB, patch)
2017-05-24 19:14 UTC, Rohit Kaushik
none Details | Review
todo-txt: major rework on provider and parser (48.60 KB, patch)
2017-05-24 19:25 UTC, Rohit Kaushik
none Details | Review
todo-txt: major rework on provider and parser (48.26 KB, patch)
2017-05-24 20:34 UTC, Rohit Kaushik
none Details | Review
todo-txt: major rework on provider and parser (48.72 KB, patch)
2017-05-24 21:02 UTC, Rohit Kaushik
committed Details | Review
todo-txt: rework on plugin (7.24 KB, patch)
2017-05-25 15:50 UTC, Rohit Kaushik
committed Details | Review

Description Mohammed Sadiq 2017-04-09 04:12:43 UTC
Creating a second level subtask creates a new task with the given subtask.


How to reproduce:
1. In a todo.txt list add items: 'A', 'B' and 'C'
2. drag 'B' as a subtask of 'A', and 'C' as a subtask of 'B'.
   Like this:
   A
   └── B
       └── C
3. Now restart gnome-todo.

Result:
The above items are replaced with the following:

   A
   └── B
   B
   └── C
Comment 1 Furqaan Shamsi 2017-04-23 00:13:34 UTC
Created attachment 350256 [details]
Video

Video showcasing the steps I followed in an attempt to unsuccessfully recreate your issue.
Comment 2 Mohammed Sadiq 2017-04-23 03:41:19 UTC
(In reply to Furqaan Shamsi from comment #1)
> Created attachment 350256 [details]
> Video
> 
> Video showcasing the steps I followed in an attempt to unsuccessfully
> recreate your issue.

The new created list should belong to Todo.txt provider. When creating a new list in the popover, click on the monitor icon, which will give you a list of providers. Select 'on Todo.txt file'. Otherwise you are using evolution backend, which doesn't have this issue (which is what you did in your video).

Please note that git master have disable building todo.txt by default. So you will have to manually enable it. Or just try to do the above steps with your current installed version (That is, don't update your repo).

Hope you understand.

Thanks
Comment 3 Georges Basile Stavracas Neto 2017-04-24 09:39:37 UTC
(In reply to Mohammed Sadiq from comment #2)

> Please note that git master have disable building todo.txt by default. So
> you will have to manually enable it. Or just try to do the above steps with
> your current installed version (That is, don't update your repo).

Because of that, I'm lowering the priority of this bug from "blocker" to "critical".
Comment 4 Rohit Kaushik 2017-05-19 13:59:09 UTC
Created attachment 352158 [details]
gtd_manager: remove old signals on provider-removal

Currently, the signals connected to providers are not disconnected
after the provider is removed.It doesn't cause any problem with
providers which are built-in but with providers that work as a plugin
e.g Todo.txt this would cause weird behaviour.
Removing all handlers on the signals that were connected initially,
solves the problem.
Comment 5 Rohit Kaushik 2017-05-19 14:15:22 UTC
Created attachment 352159 [details] [review]
file_monitor: move file-monitor from gtd-plugin to gtd-provider

We are initalising file-monitor in plugin class, but since we will
move the reload-function completely to gtd-provider-todo-txt,
there is no need for keeping an extra reference in plugin class.
Comment 6 Rohit Kaushik 2017-05-19 16:03:19 UTC
Created attachment 352165 [details] [review]
gtd_provider_todo_txt: major rework on provider

The current flow in provider is not too good and, task with
depths greater than 2 doesn't save correctly.To improve this
following changes have been introduced.

Changes introduced:
  1) Caching of task and task-list and storing pointers in GPtrArray
  2) Removing unnecessary signal emit eg. list added while
     loading the lists and task for first time
  3) using heuristis to store last encoureted task in a hash table
     and using this task as parent for any further task with
     same parent name.
  4) simplified code for updating changes.
Comment 7 Rohit Kaushik 2017-05-19 16:33:02 UTC
Created attachment 352167 [details] [review]
plugin_todo_txt: rework on plugin

Currently, the source is set after the plugin object is initialized,
but this should be done in init itself so the first the plugin is
laoded the provider is automatically loading and we dont have to send a
provider-added signal.
Other Changes are addition of function to set source, this helps in
code redundancy and make the code easier and better.
Comment 8 Georges Basile Stavracas Neto 2017-05-19 18:20:48 UTC
Review of attachment 352158 [details]:

LGTM, except for the commit title: please remove the "gtd_" prefix.
Comment 9 Georges Basile Stavracas Neto 2017-05-19 18:24:09 UTC
Review of attachment 352159 [details] [review]:

Some comments below. Also, the commit title needs some improvement: the component you modified was "todo-txt".

::: plugins/todo-txt/gtd-provider-todo-txt.c
@@ +356,3 @@
+gtd_provider_todo_txt_load_source_monitor (GtdProviderTodoTxt *self)
+{
+  GError *file_monitor = NULL;

Rename to "error"

@@ +368,3 @@
+                                      _("Error while opening the file monitor. Todo.txt will not be monitored"),
+                                      file_monitor->message);
+      g_clear_error (&file_monitor);

Use an early return here, and remove the "else" below.
Comment 10 Rohit Kaushik 2017-05-19 18:42:21 UTC
Created attachment 352180 [details] [review]
manager: remove old signals on provider-removal

Currently, the signals connected to providers are not disconnected
after the provider is removed.It doesn't cause any problem with
providers which are built-in but with providers that work as a plugin
e.g Todo.txt this would cause weird behaviour.
Removing all handlers on the signals that were connected initially,
solves the problem.
Comment 11 Rohit Kaushik 2017-05-19 19:10:56 UTC
Created attachment 352181 [details] [review]
todo_txt: move file-monitor from todo_txt_plugin to todo_txt_provider

We are initalising file-monitor in plugin class, but since we will
move the reload-function completely to gtd-provider-todo-txt,
there is no need for keeping an extra reference in plugin class.
Comment 12 Georges Basile Stavracas Neto 2017-05-19 20:03:01 UTC
Review of attachment 352165 [details] [review]:

Overall, I'm pretty confident this is an enormous improvement over the current code. This patch, however, introduces a series of compile warnings, breaking To Do build.

Besides that, the traditional "commit title prefix should be "todo-txt"."

An extensive review comes below:

::: plugins/todo-txt/gtd-provider-todo-txt.c
@@ +44,3 @@
+  GPtrArray         *cache;
+  GPtrArray         *list_cache;
+  gboolean           reload;

What does 'reload' mean?

@@ +141,3 @@
 
+static gchar*
+concat_tokens (GList *tokens)

I have the impression that this function is more like a "serializer" than "concatenator".

@@ +144,3 @@
+{
+  gchar *line;
+  GList *it;

- Always put struct types before native types. Here, GList comes before gchar.
- Rename to "it" to "l".

@@ +148,3 @@
+  it = NULL;
+  line = NULL;
+  for (it = tokens; it != NULL; it = it->next)

Jump line before the 'for'

@@ +156,3 @@
+      else
+        {
+          line = g_strconcat (line, " ", it->data, NULL);

There is a huge memory leak here. g_strconcat() is transfer full, and you have to free after use. Using a GString would be better here.

@@ +157,3 @@
+        {
+          line = g_strconcat (line, " ", it->data, NULL);
+        }

One-line "if" and "else" don't need brackets.

@@ +159,3 @@
+        }
+    }
+  return line;

Jump line before the 'return'

@@ +181,3 @@
+
+static gint
+*compare_tasks (gpointer task1,

Is the * a typo?

@@ +199,3 @@
+{
+  GtdTaskList *task_list;
+  GList *it;

In G* world, the usual name would be "l" rather than "it".

@@ +214,1 @@
+  for (it = lines; it = it->next; it != NULL)

The order of the 'for' elements is wrong. The condition is the second block, while the iterator is the third.

@@ +220,1 @@
+      if (it->data == NULL)

!it->data

@@ +231,1 @@
+      if (strcmp (gtd_todo_txt_parser_task_data_get_task_list_name (td), &(it->data[1])) == 0)

g_strcmp0()

@@ +243,3 @@
+      priority = gtd_todo_txt_parser_task_data_get_priority (td);
+
+      if (is_subtask)

I think you can simplify this whole section of code. Looks like most of the code inside the "if" and "else" are the same, except for a few things.

Instead of using one huge if/else, I think multiple small "if (is_subtask) ..." would be better.

@@ +376,3 @@
       if (!line_read)
         break;
+      task = g_list_append (task, line_read);

Nit: jump line before 'task = ...'

@@ +378,3 @@
+      task = g_list_append (task, line_read);
+    }
+  g_input_stream_close (G_INPUT_STREAM (reader), NULL, NULL);

Nit: jump line after }

@@ +390,3 @@
+                              GFile             *second,
+                              GFileMonitorEvent  event,
+                              gpointer           data)

You can pass "GtdProviderTodoTxt *self" rather than "gpointer data".

@@ +394,3 @@
+  GtdProviderTodoTxt *self;
+  GList *it;
+  guint  i;

Nit: jump line below

@@ +462,2 @@
   GError *error;
+  guint it;

Rename to 'i'

@@ +479,3 @@
     }
+  else
+    {

When there is an error, we're early returning. No need to have an "else" here

@@ +504,1 @@
+      for(it = 0; it < self->cache->len; it++)

Style issue

@@ +522,3 @@
+          g_free (task_line);
+        }
+      g_output_stream_close (G_OUTPUT_STREAM (writer), NULL, NULL);

Nit: jump line after }

@@ +540,3 @@
+
+  task_description = gtd_task_get_title (task);
+  g_ptr_array_add (self->cache, (gpointer) task);

No need to cast to gpointer

@@ +542,3 @@
+  g_ptr_array_add (self->cache, (gpointer) task);
+  g_ptr_array_sort (self->cache, (GCompareFunc) compare_tasks);
+  g_hash_table_replace (self->tasks, (gpointer) task_description, task);

No need to cast to gpointer

@@ +585,3 @@
+  g_ptr_array_remove (self->cache, (gpointer) task);
+  g_ptr_array_sort (self->cache, (GCompareFunc) compare_tasks);
+  update_source (self);

Nit: jump line before

@@ +604,3 @@
+  g_ptr_array_add (self->list_cache, (gpointer) list);
+  g_hash_table_insert (self->lists, name, list);
+  update_source (self);

Nit: jump line before

@@ +632,3 @@
+  GtdTaskList        *task_list;
+  GtdTask            *task;
+  guint               it;

Style issue. Don't align these variables.

@@ +641,2 @@
     {
+      task = g_ptr_array_index(self->cache, it);

Style issue

@@ +646,2 @@
         {
+          g_ptr_array_remove (self->cache, (gpointer) task);

No need to cast to gpointer

@@ +650,3 @@
     }
 
+  g_ptr_array_remove (self->list_cache, (gpointer) list);

No need to cast to gpointer

@@ +651,3 @@
 
+  g_ptr_array_remove (self->list_cache, (gpointer) list);
+  self->task_lists = g_list_remove (self->task_lists, list);

Nit: jump line before 'self->task_lists = ...'

@@ +719,3 @@
+  g_clear_pointer (&self->tasks, g_hash_table_destroy);
+  g_ptr_array_free (self->cache, TRUE);
+  g_ptr_array_free (self->list_cache, TRUE);

Nit: put the 'g_ptr_array_free()' calls before g_clear_pointer() ones

::: plugins/todo-txt/gtd-provider-todo-txt.h
@@ -34,3 @@
-void                   gtd_provider_todo_txt_set_monitor             (GtdProviderTodoTxt *self,
-                                                                      GFileMonitor       *monitor);
-

Shouldn't this be in the previous patch?
Comment 13 Georges Basile Stavracas Neto 2017-05-19 20:05:08 UTC
Review of attachment 352167 [details] [review]:

Some minor issues

::: plugins/todo-txt/gtd-plugin-todo-txt.c
@@ +191,3 @@
         }
     }
+  return TRUE;

Nit: jump line after }

@@ +201,3 @@
+
+  set = gtd_plugin_todo_txt_set_source (self);
+  if (!set)

Nit: jump line before 'if'

@@ +288,2 @@
   GtkWidget *label;
+  gboolean   set;

Jump line after variables
Comment 14 Georges Basile Stavracas Neto 2017-05-19 20:05:27 UTC
Review of attachment 352180 [details] [review]:

LGTM
Comment 15 Georges Basile Stavracas Neto 2017-05-19 20:06:35 UTC
Review of attachment 352181 [details] [review]:

The commit prefix should be "todo-txt", not "todo_txt". Never use underscores in prefixes
Comment 16 Rohit Kaushik 2017-05-20 06:56:52 UTC
Created attachment 352202 [details] [review]
todo-txt: move file-monitor from todo_txt_plugin to todo_txt_provider

We are initalising file-monitor in plugin class, but since we will
move the reload-function completely to gtd-provider-todo-txt,
there is no need for keeping an extra reference in plugin class.
Comment 17 Georges Basile Stavracas Neto 2017-05-23 01:44:12 UTC
Review of attachment 352202 [details] [review]:

Looks good!
Comment 18 Georges Basile Stavracas Neto 2017-05-23 01:47:36 UTC
Review of attachment 352202 [details] [review]:

Uh, I step back and say: this doesn't build.

You need to remove all g_signal_handlers_block_by_func (self->monitor, gtd_plugin_todo_txt_monitor_source, self) from GtdPluginTodoTxt.
Comment 19 Georges Basile Stavracas Neto 2017-05-23 01:49:16 UTC
Comment on attachment 352180 [details] [review]
manager: remove old signals on provider-removal

Attachment 352180 [details] pushed as 1c44729 - manager: remove old signals on provider-removal
Comment 20 Rohit Kaushik 2017-05-23 13:30:39 UTC
Created attachment 352425 [details] [review]
todo-txt: move file-monitor from todo_txt_plugin to todo_txt_provider

We are initalising file-monitor in plugin class, but since we will
move the reload-function completely to gtd-provider-todo-txt,
there is no need for keeping an extra reference in plugin class.
Comment 21 Georges Basile Stavracas Neto 2017-05-24 19:02:46 UTC
Comment on attachment 352425 [details] [review]
todo-txt: move file-monitor from todo_txt_plugin to todo_txt_provider

Looks good.
Comment 22 Georges Basile Stavracas Neto 2017-05-24 19:03:23 UTC
Comment on attachment 352425 [details] [review]
todo-txt: move file-monitor from todo_txt_plugin to todo_txt_provider

Attachment 352425 [details] pushed as e6e3696 - todo-txt: move file-monitor from todo_txt_plugin to todo_txt_provider
Comment 23 Rohit Kaushik 2017-05-24 19:14:58 UTC
Created attachment 352529 [details] [review]
todo-txt: major rework on provider and parser

Issues like creating task with many subtask and depth greater
than 2 being not save properly has been fixed.Provider has
been restrucred and changes has been made according in Parser.

Changes made:
   1)Remove custom structure TaskData from parser
   2)parse_tokens now return GtdTask directly
   3)Provider cache the lists so that updating the source
     is easier.
   4)monitor reloads the tasks/lists only when todo.txt file
     has been altered from outside.This is fixed using a dummy
     should_reload flag.
   5)Parser now makes use of GString that can grow, rather than
     using g_strconcat
Comment 24 Rohit Kaushik 2017-05-24 19:25:47 UTC
Created attachment 352530 [details] [review]
todo-txt: major rework on provider and parser

Issues like creating task with many subtask and depth greater
than 2 being not save properly has been fixed.Provider has
been restrucred and changes has been made according in Parser.

Changes made:
   1)Remove custom structure TaskData from parser
   2)parse_tokens now return GtdTask directly
   3)Provider cache the lists so that updating the source
     is easier.
   4)monitor reloads the tasks/lists only when todo.txt file
     has been altered from outside.This is fixed using a dummy
     should_reload flag.
   5)Parser now makes use of GString that can grow, rather than
     using g_strconcat
Comment 25 Georges Basile Stavracas Neto 2017-05-24 19:44:44 UTC
Review of attachment 352530 [details] [review]:

A few comments below. This is a ~massive~ improvement, a very honest congratulation!

::: plugins/todo-txt/gtd-provider-todo-txt.c
@@ +276,1 @@
           return;

I think this should be a 'continue'? This is leaking many variables when it returns here.

@@ -350,2 @@
-      g_list_free_full (tokens, g_free);
-      g_free (line_read);

You're leaking those two variable now.

@@ +322,3 @@
+{
+  GList *l;
+  guint  i;

Wrong style. Don't align 'i' with 'l'

::: plugins/todo-txt/gtd-provider-todo-txt.h
@@ +32,3 @@
 GtdProviderTodoTxt*    gtd_provider_todo_txt_new                     (GFile         *source_file);
 
+GtdTask* create_task (void);

Jump line below

::: plugins/todo-txt/gtd-todo-txt-parser.h
@@ +52,1 @@
+GString*      gtd_todo_txt_parser_serialize_task                  (GtdTask           *task);

Those two functions should return gchar* rather than GString*
Comment 26 Rohit Kaushik 2017-05-24 20:34:38 UTC
Created attachment 352533 [details] [review]
todo-txt: major rework on provider and parser

Issues like creating task with many subtask and depth greater
than 2 being not save properly has been fixed.Provider has
been restrucred and changes has been made according in Parser.

Changes made:
   1)Remove custom structure TaskData from parser
   2)parse_tokens now return GtdTask directly
   3)Provider cache the lists so that updating the source
     is easier.
   4)monitor reloads the tasks/lists only when todo.txt file
     has been altered from outside.This is fixed using a dummy
     should_reload flag.
   5)Parser now makes use of GString that can grow, rather than
     using g_strconcat
Comment 27 Rohit Kaushik 2017-05-24 21:02:23 UTC
Created attachment 352535 [details] [review]
todo-txt: major rework on provider and parser

Issues like creating task with many subtask and depth greater
than 2 being not save properly has been fixed.Provider has
been restrucred and changes has been made according in Parser.

Changes made:
   1)Remove custom structure TaskData from parser
   2)parse_tokens now return GtdTask directly
   3)Provider cache the lists so that updating the source
     is easier.
   4)monitor reloads the tasks/lists only when todo.txt file
     has been altered from outside.This is fixed using a dummy
     should_reload flag.
   5)Parser now makes use of GString that can grow, rather than
     using g_strconcat
Comment 28 Georges Basile Stavracas Neto 2017-05-24 21:27:01 UTC
Thanks! This rework is simply great!

Attachment 352535 [details] pushed as 9f7567d - todo-txt: major rework on provider and parser
Comment 29 Rohit Kaushik 2017-05-25 15:50:55 UTC
Created attachment 352584 [details] [review]
todo-txt: rework on plugin

Currently, the source is set after the plugin object is initialized,
but this should be done in init itself so the first time the plugin is
laoded, the provider is automatically loaded and we dont have to send a
provider-added signal.
Other Changes are addition of function to set source, this helps in
reducing code redundancy and makes code easier and better.
Comment 30 Georges Basile Stavracas Neto 2017-06-01 14:20:22 UTC
Comment on attachment 352584 [details] [review]
todo-txt: rework on plugin

Attachment 352584 [details] pushed as 15a70bb - todo-txt: rework on plugin