[gnome-todo] provider: Make all vfuncs async



commit c1e3245e8f9aa6da5fcb3cf1d69d75863951c5c5
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Sat May 2 23:24:50 2020 -0300

    provider: Make all vfuncs async
    
    https://gitlab.gnome.org/GNOME/gnome-todo/-/issues/330

 src/gtd-task-list.c                                |  28 +-
 src/interfaces/gtd-provider.c                      | 238 ++++++++-
 src/interfaces/gtd-provider.h                      | 108 +++-
 src/plugins/eds/gtd-provider-eds.c                 | 563 ++++++++++++++-------
 src/plugins/task-lists-workspace/gtd-sidebar.c     |  16 +-
 .../task-lists-workspace/gtd-task-list-panel.c     |  43 +-
 src/provider/gtd-provider-popover.c                |  29 +-
 src/task-list-view/gtd-dnd-row.c                   |  31 +-
 src/task-list-view/gtd-new-task-row.c              |  36 +-
 src/task-list-view/gtd-task-list-view.c            |  21 +-
 src/task-list-view/gtd-task-row.c                  |  42 +-
 tests/dummy-provider.c                             |  22 +-
 12 files changed, 939 insertions(+), 238 deletions(-)
---
diff --git a/src/gtd-task-list.c b/src/gtd-task-list.c
index 74b37b8..ed4ef05 100644
--- a/src/gtd-task-list.c
+++ b/src/gtd-task-list.c
@@ -221,6 +221,22 @@ recursively_remove_subtasks (GtdTaskList *self,
  * Callbacks
  */
 
+static void
+on_task_updated_cb (GObject      *object,
+                    GAsyncResult *result,
+                    gpointer      user_data)
+{
+  g_autoptr (GError) error = NULL;
+
+  gtd_provider_update_task_finish (GTD_PROVIDER (object), result, &error);
+
+  if (error)
+    {
+      g_warning ("Error updating task: %s", error->message);
+      return;
+    }
+}
+
 static gint
 compare_tasks_cb (gconstpointer a,
                   gconstpointer b,
@@ -1022,7 +1038,11 @@ gtd_task_list_move_task_to_position (GtdTaskList *self,
       gtd_task_set_position (task_at_i, block1_new_start + i);
       g_signal_handlers_unblock_by_func (task_at_i, task_changed_cb, self);
 
-      gtd_provider_update_task (priv->provider, task_at_i);
+      gtd_provider_update_task (priv->provider,
+                                task_at_i,
+                                NULL,
+                                on_task_updated_cb,
+                                self);
     }
 
   /* Update Block 2 */
@@ -1036,7 +1056,11 @@ gtd_task_list_move_task_to_position (GtdTaskList *self,
       gtd_task_set_position (task_at_i, block2_new_start + i);
       g_signal_handlers_unblock_by_func (task_at_i, task_changed_cb, self);
 
-      gtd_provider_update_task (priv->provider, task_at_i);
+      gtd_provider_update_task (priv->provider,
+                                task_at_i,
+                                NULL,
+                                on_task_updated_cb,
+                                self);
     }
 
   /*
diff --git a/src/interfaces/gtd-provider.c b/src/interfaces/gtd-provider.c
index a446322..cdbe634 100644
--- a/src/interfaces/gtd-provider.c
+++ b/src/interfaces/gtd-provider.c
@@ -316,104 +316,302 @@ gtd_provider_get_icon (GtdProvider *provider)
  * gtd_provider_create_task:
  * @provider: a #GtdProvider
  * @task: a #GtdTask
+ * @due_date: (nullable): a #GDateTime
+ * @cancellable: (nullable): a #GCancellable
+ * @callback: (scope async): a callback
+ * @user_data: (closure): user data for @callback
  *
  * Creates the given task in @provider.
  */
 void
-gtd_provider_create_task (GtdProvider *provider,
-                          GtdTaskList *list,
-                          const gchar *title,
-                          GDateTime   *due_date)
+gtd_provider_create_task (GtdProvider         *provider,
+                          GtdTaskList         *list,
+                          const gchar         *title,
+                          GDateTime           *due_date,
+                          GCancellable        *cancellable,
+                          GAsyncReadyCallback  callback,
+                          gpointer             user_data)
 {
   g_return_if_fail (GTD_IS_PROVIDER (provider));
   g_return_if_fail (GTD_PROVIDER_GET_IFACE (provider)->create_task);
 
-  GTD_PROVIDER_GET_IFACE (provider)->create_task (provider, list, title, due_date);
+  GTD_PROVIDER_GET_IFACE (provider)->create_task (provider,
+                                                  list,
+                                                  title,
+                                                  due_date,
+                                                  cancellable,
+                                                  callback,
+                                                  user_data);
+}
+
+/**
+ * gtd_provider_create_task_finish:
+ * @self: a #GtdProvider
+ * @result: a #GAsyncResult
+ * @error: (direction out)(nullable): return location for a #GError
+ *
+ * Finishes creating the task.
+ *
+ * Returns: (transfer none)(nullable): a #GtdTask
+ */
+GtdTask*
+gtd_provider_create_task_finish (GtdProvider   *self,
+                                 GAsyncResult  *result,
+                                 GError       **error)
+{
+  g_return_val_if_fail (GTD_IS_PROVIDER (self), FALSE);
+  g_return_val_if_fail (!error || !*error, FALSE);
+  g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (self)->create_task_finish, FALSE);
+
+  return GTD_PROVIDER_GET_IFACE (self)->create_task_finish (self, result, error);
 }
 
 /**
  * gtd_provider_update_task:
  * @provider: a #GtdProvider
  * @task: a #GtdTask
+ * @cancellable: (nullable): a #GCancellable
+ * @callback: (scope async): a callback
+ * @user_data: (closure): user data for @callback
  *
  * Updates the given task in @provider.
  */
 void
-gtd_provider_update_task (GtdProvider *provider,
-                          GtdTask     *task)
+gtd_provider_update_task (GtdProvider         *provider,
+                          GtdTask             *task,
+                          GCancellable        *cancellable,
+                          GAsyncReadyCallback  callback,
+                          gpointer             user_data)
 {
   g_return_if_fail (GTD_IS_PROVIDER (provider));
   g_return_if_fail (GTD_PROVIDER_GET_IFACE (provider)->update_task);
 
-  GTD_PROVIDER_GET_IFACE (provider)->update_task (provider, task);
+  GTD_PROVIDER_GET_IFACE (provider)->update_task (provider,
+                                                  task,
+                                                  cancellable,
+                                                  callback,
+                                                  user_data);
+}
+
+/**
+ * gtd_provider_update_task_finish:
+ * @self: a #GtdProvider
+ * @result: a #GAsyncResult
+ * @error: (direction out)(nullable): return location for a #GError
+ *
+ * Finishes updating the task list.
+ *
+ * Returns: %TRUE if task list was successfully updated, %FALSE otherwise
+ */
+gboolean
+gtd_provider_update_task_finish (GtdProvider   *self,
+                                 GAsyncResult  *result,
+                                 GError       **error)
+{
+  g_return_val_if_fail (GTD_IS_PROVIDER (self), FALSE);
+  g_return_val_if_fail (!error || !*error, FALSE);
+  g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (self)->update_task_finish, FALSE);
+
+  return GTD_PROVIDER_GET_IFACE (self)->update_task_finish (self, result, error);
 }
 
 /**
  * gtd_provider_remove_task:
  * @provider: a #GtdProvider
  * @task: a #GtdTask
+ * @cancellable: (nullable): a #GCancellable
+ * @callback: (scope async): a callback
+ * @user_data: (closure): user data for @callback
  *
  * Removes the given task from @provider.
  */
 void
-gtd_provider_remove_task (GtdProvider *provider,
-                          GtdTask     *task)
+gtd_provider_remove_task (GtdProvider         *provider,
+                          GtdTask             *task,
+                          GCancellable        *cancellable,
+                          GAsyncReadyCallback  callback,
+                          gpointer             user_data)
 {
   g_return_if_fail (GTD_IS_PROVIDER (provider));
   g_return_if_fail (GTD_PROVIDER_GET_IFACE (provider)->remove_task);
 
-  GTD_PROVIDER_GET_IFACE (provider)->remove_task (provider, task);
+  GTD_PROVIDER_GET_IFACE (provider)->remove_task (provider,
+                                                  task,
+                                                  cancellable,
+                                                  callback,
+                                                  user_data);
+}
+
+/**
+ * gtd_provider_remove_task_finish:
+ * @self: a #GtdProvider
+ * @result: a #GAsyncResult
+ * @error: (direction out)(nullable): return location for a #GError
+ *
+ * Finishes removing the task.
+ *
+ * Returns: %TRUE if task was successfully removed, %FALSE otherwise
+ */
+gboolean
+gtd_provider_remove_task_finish (GtdProvider   *self,
+                                 GAsyncResult  *result,
+                                 GError       **error)
+{
+  g_return_val_if_fail (GTD_IS_PROVIDER (self), FALSE);
+  g_return_val_if_fail (!error || !*error, FALSE);
+  g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (self)->remove_task_finish, FALSE);
+
+  return GTD_PROVIDER_GET_IFACE (self)->remove_task_finish (self, result, error);
 }
 
 /**
  * gtd_provider_create_task_list:
  * @provider: a #GtdProvider
  * @name: (nullable): the name of the new task list
+ * @cancellable: (nullable): a #GCancellable
+ * @callback: (scope async): a callback
+ * @user_data: (closure): user data for @callback
  *
  * Creates the given list in @provider.
  */
 void
-gtd_provider_create_task_list (GtdProvider *provider,
-                               const gchar *name)
+gtd_provider_create_task_list (GtdProvider         *provider,
+                               const gchar         *name,
+                               GCancellable        *cancellable,
+                               GAsyncReadyCallback  callback,
+                               gpointer             user_data)
 {
   g_return_if_fail (GTD_IS_PROVIDER (provider));
   g_return_if_fail (GTD_PROVIDER_GET_IFACE (provider)->create_task_list);
 
-  GTD_PROVIDER_GET_IFACE (provider)->create_task_list (provider, name);
+  GTD_PROVIDER_GET_IFACE (provider)->create_task_list (provider,
+                                                       name,
+                                                       cancellable,
+                                                       callback,
+                                                       user_data);
+}
+
+/**
+ * gtd_provider_create_task_list_finish:
+ * @self: a #GtdProvider
+ * @result: a #GAsyncResult
+ * @error: (direction out)(nullable): return location for a #GError
+ *
+ * Finishes creating the task list. The provider will emit the
+ * GtdProvider:list-added signal after creating the task list.
+ *
+ * Returns: %TRUE if task list was successfully created, %FALSE otherwise
+ */
+gboolean
+gtd_provider_create_task_list_finish (GtdProvider   *self,
+                                      GAsyncResult  *result,
+                                      GError       **error)
+{
+  g_return_val_if_fail (GTD_IS_PROVIDER (self), FALSE);
+  g_return_val_if_fail (!error || !*error, FALSE);
+  g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (self)->create_task_list_finish, FALSE);
+
+  return GTD_PROVIDER_GET_IFACE (self)->create_task_list_finish (self, result, error);
 }
 
 /**
  * gtd_provider_update_task_list:
  * @provider: a #GtdProvider
  * @list: a #GtdTaskList
+ * @cancellable: (nullable): a #GCancellable
+ * @callback: (scope async): a callback
+ * @user_data: (closure): user data for @callback
  *
  * Updates the given list in @provider.
  */
 void
-gtd_provider_update_task_list (GtdProvider *provider,
-                               GtdTaskList *list)
+gtd_provider_update_task_list (GtdProvider         *provider,
+                               GtdTaskList         *list,
+                               GCancellable        *cancellable,
+                               GAsyncReadyCallback  callback,
+                               gpointer             user_data)
 {
   g_return_if_fail (GTD_IS_PROVIDER (provider));
   g_return_if_fail (GTD_PROVIDER_GET_IFACE (provider)->update_task_list);
 
-  GTD_PROVIDER_GET_IFACE (provider)->update_task_list (provider, list);
+  GTD_PROVIDER_GET_IFACE (provider)->update_task_list (provider,
+                                                       list,
+                                                       cancellable,
+                                                       callback,
+                                                       user_data);
+}
+
+/**
+ * gtd_provider_create_task_list_finish:
+ * @self: a #GtdProvider
+ * @result: a #GAsyncResult
+ * @error: (direction out)(nullable): return location for a #GError
+ *
+ * Finishes updating the task list. The provider will emit the
+ * GtdProvider:list-updated signal after updating the task list.
+ *
+ * Returns: %TRUE if task list was successfully created, %FALSE otherwise
+ */
+gboolean
+gtd_provider_update_task_list_finish (GtdProvider   *self,
+                                      GAsyncResult  *result,
+                                      GError       **error)
+{
+  g_return_val_if_fail (GTD_IS_PROVIDER (self), FALSE);
+  g_return_val_if_fail (!error || !*error, FALSE);
+  g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (self)->update_task_list_finish, FALSE);
+
+  return GTD_PROVIDER_GET_IFACE (self)->update_task_list_finish (self, result, error);
 }
 
 /**
  * gtd_provider_remove_task_list:
  * @provider: a #GtdProvider
  * @list: a #GtdTaskList
+ * @cancellable: (nullable): a #GCancellable
+ * @callback: (scope async): a callback
+ * @user_data: (closure): user data for @callback
  *
  * Removes the given list from @provider.
  */
 void
-gtd_provider_remove_task_list (GtdProvider *provider,
-                               GtdTaskList *list)
+gtd_provider_remove_task_list (GtdProvider         *provider,
+                               GtdTaskList         *list,
+                               GCancellable        *cancellable,
+                               GAsyncReadyCallback  callback,
+                               gpointer             user_data)
 {
   g_return_if_fail (GTD_IS_PROVIDER (provider));
   g_return_if_fail (GTD_PROVIDER_GET_IFACE (provider)->remove_task_list);
 
-  GTD_PROVIDER_GET_IFACE (provider)->remove_task_list (provider, list);
+  GTD_PROVIDER_GET_IFACE (provider)->remove_task_list (provider,
+                                                       list,
+                                                       cancellable,
+                                                       callback,
+                                                       user_data);
+}
+
+/**
+ * gtd_provider_remove_task_list_finish:
+ * @self: a #GtdProvider
+ * @result: a #GAsyncResult
+ * @error: (direction out)(nullable): return location for a #GError
+ *
+ * Finishes removing the task list. The provider will emit the
+ * GtdProvider:list-removed signal after removing the task list.
+ *
+ * Returns: %TRUE if task list was successfully removed, %FALSE otherwise
+ */
+gboolean
+gtd_provider_remove_task_list_finish (GtdProvider   *self,
+                                      GAsyncResult  *result,
+                                      GError       **error)
+{
+  g_return_val_if_fail (GTD_IS_PROVIDER (self), FALSE);
+  g_return_val_if_fail (!error || !*error, FALSE);
+  g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (self)->remove_task_list_finish, FALSE);
+
+  return GTD_PROVIDER_GET_IFACE (self)->remove_task_list_finish (self, result, error);
 }
 
 /**
diff --git a/src/interfaces/gtd-provider.h b/src/interfaces/gtd-provider.h
index dbdc77e..0b8e097 100644
--- a/src/interfaces/gtd-provider.h
+++ b/src/interfaces/gtd-provider.h
@@ -55,23 +55,65 @@ struct _GtdProviderInterface
   void               (*create_task)                              (GtdProvider        *provider,
                                                                   GtdTaskList        *list,
                                                                   const gchar        *title,
-                                                                  GDateTime          *due_date);
+                                                                  GDateTime          *due_date,
+                                                                  GCancellable       *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer            user_data);
+
+  GtdTask*           (*create_task_finish)                       (GtdProvider        *self,
+                                                                  GAsyncResult       *result,
+                                                                  GError            **error);
 
   void               (*update_task)                              (GtdProvider        *provider,
-                                                                  GtdTask            *task);
+                                                                  GtdTask            *task,
+                                                                  GCancellable       *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer            user_data);
+
+  gboolean           (*update_task_finish)                       (GtdProvider        *self,
+                                                                  GAsyncResult       *result,
+                                                                  GError            **error);
 
   void               (*remove_task)                              (GtdProvider        *provider,
-                                                                  GtdTask            *task);
+                                                                  GtdTask            *task,
+                                                                  GCancellable       *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer            user_data);
+
+  gboolean           (*remove_task_finish)                       (GtdProvider        *self,
+                                                                  GAsyncResult       *result,
+                                                                  GError            **error);
 
   /* Task lists */
   void               (*create_task_list)                         (GtdProvider        *provider,
-                                                                  const gchar        *name);
+                                                                  const gchar        *name,
+                                                                  GCancellable       *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer            user_data);
+
+  gboolean           (*create_task_list_finish)                  (GtdProvider        *self,
+                                                                  GAsyncResult       *result,
+                                                                  GError            **error);
 
   void               (*update_task_list)                         (GtdProvider        *provider,
-                                                                  GtdTaskList        *list);
+                                                                  GtdTaskList        *list,
+                                                                  GCancellable       *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer            user_data);
+
+  gboolean           (*update_task_list_finish)                  (GtdProvider        *self,
+                                                                  GAsyncResult       *result,
+                                                                  GError            **error);
 
   void               (*remove_task_list)                         (GtdProvider        *provider,
-                                                                  GtdTaskList        *list);
+                                                                  GtdTaskList        *list,
+                                                                  GCancellable       *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer            user_data);
+
+  gboolean           (*remove_task_list_finish)                  (GtdProvider        *self,
+                                                                  GAsyncResult       *result,
+                                                                  GError            **error);
 
   GList*             (*get_task_lists)                           (GtdProvider        *provider);
 
@@ -95,22 +137,64 @@ GIcon*               gtd_provider_get_icon                       (GtdProvider
 void                 gtd_provider_create_task                    (GtdProvider        *provider,
                                                                   GtdTaskList        *list,
                                                                   const gchar        *title,
-                                                                  GDateTime          *due_date);
+                                                                  GDateTime          *due_date,
+                                                                  GCancellable       *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer            user_data);
+
+GtdTask*             gtd_provider_create_task_finish             (GtdProvider        *self,
+                                                                  GAsyncResult       *result,
+                                                                  GError            **error);
 
 void                 gtd_provider_update_task                    (GtdProvider        *provider,
-                                                                  GtdTask            *task);
+                                                                  GtdTask            *task,
+                                                                  GCancellable       *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer            user_data);
+
+gboolean             gtd_provider_update_task_finish             (GtdProvider        *self,
+                                                                  GAsyncResult       *result,
+                                                                  GError            **error);
 
 void                 gtd_provider_remove_task                    (GtdProvider        *provider,
-                                                                  GtdTask            *task);
+                                                                  GtdTask            *task,
+                                                                  GCancellable       *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer            user_data);
+
+gboolean             gtd_provider_remove_task_finish             (GtdProvider        *self,
+                                                                  GAsyncResult       *result,
+                                                                  GError            **error);
 
 void                 gtd_provider_create_task_list               (GtdProvider        *provider,
-                                                                  const gchar        *name);
+                                                                  const gchar        *name,
+                                                                  GCancellable       *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer            user_data);
+
+gboolean             gtd_provider_create_task_list_finish        (GtdProvider        *self,
+                                                                  GAsyncResult       *result,
+                                                                  GError            **error);
 
 void                 gtd_provider_update_task_list               (GtdProvider        *provider,
-                                                                  GtdTaskList        *list);
+                                                                  GtdTaskList        *list,
+                                                                  GCancellable       *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer            user_data);
+
+gboolean             gtd_provider_update_task_list_finish        (GtdProvider        *self,
+                                                                  GAsyncResult       *result,
+                                                                  GError            **error);
 
 void                 gtd_provider_remove_task_list               (GtdProvider        *provider,
-                                                                  GtdTaskList        *list);
+                                                                  GtdTaskList        *list,
+                                                                  GCancellable       *cancellable,
+                                                                  GAsyncReadyCallback callback,
+                                                                  gpointer            user_data);
+
+gboolean             gtd_provider_remove_task_list_finish        (GtdProvider        *self,
+                                                                  GAsyncResult       *result,
+                                                                  GError            **error);
 
 GList*               gtd_provider_get_task_lists                 (GtdProvider        *provider);
 
diff --git a/src/plugins/eds/gtd-provider-eds.c b/src/plugins/eds/gtd-provider-eds.c
index aaa5a0d..22b0433 100644
--- a/src/plugins/eds/gtd-provider-eds.c
+++ b/src/plugins/eds/gtd-provider-eds.c
@@ -37,6 +37,18 @@
  * sources whose backend is not "local".
  */
 
+typedef struct
+{
+  GtdTaskList        *list;
+  GDateTime          *due_date;
+  gchar              *title;
+  ESource            *source;
+
+  /* Update Task */
+  ECalComponent      *component;
+  GtdTask            *task;
+} AsyncData;
+
 typedef struct
 {
   GHashTable           *task_lists;
@@ -75,6 +87,20 @@ enum
  * Auxiliary methods
  */
 
+static void
+async_data_free (gpointer data)
+{
+  AsyncData *async_data = data;
+
+  g_clear_pointer (&async_data->due_date, g_date_time_unref);
+  g_clear_pointer (&async_data->title, g_free);
+  g_clear_object (&async_data->source);
+  g_clear_object (&async_data->list);
+  g_clear_object (&async_data->task);
+  g_clear_object (&async_data->component);
+  g_free (async_data);
+}
+
 static void
 set_default_list (GtdProviderEds *self,
                   GtdTaskList    *list)
@@ -256,172 +282,224 @@ on_source_refreshed_cb (GObject      *source_object,
   GTD_EXIT;
 }
 
-#define REPORT_ERROR(title,error) \
-G_STMT_START \
-  if (error) \
-    { \
-      g_warning ("%s: %s", title, error->message); \
-      gtd_manager_emit_error_message (gtd_manager_get_default (), title, error->message, NULL, NULL); \
-      GTD_RETURN (); \
-    } \
-G_STMT_END
-
 static void
-on_task_created_cb (ECalClient   *client,
-                    GAsyncResult *result,
-                    GtdTask      *task)
+create_task_in_thread_cb (GTask        *task,
+                          gpointer      source_object,
+                          gpointer      task_data,
+                          GCancellable *cancellable)
 {
+  g_autoptr (ECalComponent) component = NULL;
   g_autoptr (GError) error = NULL;
   g_autofree gchar *new_uid = NULL;
-  GtdProviderEds *self;
-  GtdTaskList *list;
+  ECalComponentText *new_summary;
+  GtdTaskListEds *tasklist;
+  ECalClient *client;
+  AsyncData *data;
+  GtdTask *new_task;
 
   GTD_ENTRY;
 
-  self = GTD_PROVIDER_EDS (gtd_task_get_provider (task));
-  list = gtd_task_get_list (task);
+  data = task_data;
+  tasklist = GTD_TASK_LIST_EDS (data->list);
+  client = gtd_task_list_eds_get_client (tasklist);
 
-  gtd_object_pop_loading (GTD_OBJECT (self));
-  gtd_object_pop_loading (GTD_OBJECT (task));
+  /* Create the new task */
+  component = e_cal_component_new ();
+  e_cal_component_set_new_vtype (component, E_CAL_COMPONENT_TODO);
 
-  e_cal_client_create_object_finish (client, result, &new_uid, &error);
+  new_summary = e_cal_component_text_new (data->title, NULL);
+  e_cal_component_set_summary (component, new_summary);
+
+  if (data->due_date)
+    {
+      ECalComponentDateTime *comp_dt;
+      ICalTime *idt;
+
+      idt = i_cal_time_new_null_time ();
+      i_cal_time_set_date (idt,
+                           g_date_time_get_year (data->due_date),
+                           g_date_time_get_month (data->due_date),
+                           g_date_time_get_day_of_month (data->due_date));
+      i_cal_time_set_time (idt,
+                           g_date_time_get_hour (data->due_date),
+                           g_date_time_get_minute (data->due_date),
+                           g_date_time_get_seconds (data->due_date));
+      i_cal_time_set_is_date (idt,
+                              i_cal_time_get_hour (idt) == 0 &&
+                              i_cal_time_get_minute (idt) == 0 &&
+                              i_cal_time_get_second (idt) == 0);
+
+      comp_dt = e_cal_component_datetime_new_take (idt, g_strdup ("UTC"));
+      e_cal_component_set_due (component, comp_dt);
+      e_cal_component_commit_sequence (component);
+
+      e_cal_component_datetime_free (comp_dt);
+    }
 
-  REPORT_ERROR (_("An error occurred while creating a task"), error);
+  e_cal_client_create_object_sync (client,
+                                   e_cal_component_get_icalcomponent (component),
+                                   E_CAL_OPERATION_FLAG_NONE,
+                                   &new_uid,
+                                   cancellable,
+                                   &error);
 
-  /* Update the default tasklist */
-  set_default_list (self, list);
+  e_cal_component_text_free (new_summary);
+
+  if (error)
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      return;
+    }
+
+  new_task = gtd_task_eds_new (component);
+  gtd_task_set_position (new_task, g_list_model_get_n_items (G_LIST_MODEL (tasklist)));
 
   /*
    * In the case the task UID changes because of creation proccess,
    * reapply it to the task.
    */
   if (new_uid)
-    gtd_object_set_uid (GTD_OBJECT (task), new_uid);
+    gtd_object_set_uid (GTD_OBJECT (new_task), new_uid);
 
   /* Effectively apply the updated component */
-  gtd_task_eds_apply (GTD_TASK_EDS (task));
+  gtd_task_eds_apply (GTD_TASK_EDS (new_task));
+
+  g_task_return_pointer (task, g_object_ref (new_task), g_object_unref);
 
   GTD_EXIT;
 }
 
 static void
-on_task_modified_cb (ECalClient   *client,
-                     GAsyncResult *result,
-                     GtdTask      *task)
+update_task_in_thread_cb (GTask        *task,
+                          gpointer      source_object,
+                          gpointer      task_data,
+                          GCancellable *cancellable)
 {
   g_autoptr (GError) error = NULL;
-  GtdProviderEds *self;
+  GtdTaskListEds *tasklist;
+  ECalClient *client;
+  AsyncData *data;
 
   GTD_ENTRY;
 
-  self = GTD_PROVIDER_EDS (gtd_task_get_provider (task));
+  data = task_data;
+  tasklist = GTD_TASK_LIST_EDS (gtd_task_get_list (data->task));
+  client = gtd_task_list_eds_get_client (tasklist);
 
-  gtd_object_pop_loading (GTD_OBJECT (task));
-  gtd_object_pop_loading (GTD_OBJECT (self));
+  e_cal_client_modify_object_sync (client,
+                                   e_cal_component_get_icalcomponent (data->component),
+                                   E_CAL_OBJ_MOD_THIS,
+                                   E_CAL_OPERATION_FLAG_NONE,
+                                   cancellable,
+                                   &error);
 
-  e_cal_client_modify_object_finish (client, result, &error);
 
-  if (!error)
-    {
-      gtd_task_eds_apply (GTD_TASK_EDS (task));
-      gtd_task_list_update_task (gtd_task_get_list (task), task);
-    }
-  else
+  if (error)
     {
-      gtd_task_eds_revert (GTD_TASK_EDS (task));
+      g_task_return_error (task, g_steal_pointer (&error));
+      GTD_RETURN ();
     }
 
-  REPORT_ERROR (_("An error occurred while modifying a task"), error);
+  g_task_return_boolean (task, TRUE);
 
   GTD_EXIT;
 }
 
 static void
-on_task_removed_cb (GObject      *object,
-                    GAsyncResult *result,
-                    gpointer      user_data)
+remove_task_in_thread_cb (GTask        *task,
+                          gpointer      source_object,
+                          gpointer      task_data,
+                          GCancellable *cancellable)
 {
+  g_autoptr (ECalComponentId) id = NULL;
   g_autoptr (GError) error = NULL;
-  GtdProviderEds *self;
+  GtdTaskListEds *tasklist;
+  ECalClient *client;
+  AsyncData *data;
 
   GTD_ENTRY;
 
-  self = GTD_PROVIDER_EDS (user_data);
-
-  gtd_object_pop_loading (GTD_OBJECT (self));
-
-  e_cal_client_remove_object_finish (E_CAL_CLIENT (object), result, &error);
-
-  REPORT_ERROR (_("An error occurred while removing a task"), error);
-
-  GTD_EXIT;
-}
-
-static void
-on_task_list_created_cb (ESourceRegistry *registry,
-                         GAsyncResult    *result,
-                         GtdProviderEds  *self)
-{
-  g_autoptr (GError) error = NULL;
+  data = task_data;
+  tasklist = GTD_TASK_LIST_EDS (gtd_task_get_list (data->task));
+  client = gtd_task_list_eds_get_client (tasklist);
+  id = e_cal_component_get_id (data->component);
 
-  GTD_ENTRY;
+  e_cal_client_remove_object_sync (client,
+                                   e_cal_component_id_get_uid (id),
+                                   e_cal_component_id_get_rid (id),
+                                   E_CAL_OBJ_MOD_THIS,
+                                   E_CAL_OPERATION_FLAG_NONE,
+                                   cancellable,
+                                   &error);
 
-  gtd_object_pop_loading (GTD_OBJECT (self));
 
-  e_source_registry_commit_source_finish (registry, result, &error);
+  if (error)
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      GTD_RETURN ();
+    }
 
-  REPORT_ERROR (_("An error occurred while creating a task list"), error);
+  g_task_return_boolean (task, TRUE);
 
   GTD_EXIT;
 }
 
 static void
-on_task_list_modified_cb (ESourceRegistry *registry,
-                          GAsyncResult    *result,
-                          GtdTaskList     *list)
+create_or_update_task_list_in_thread_cb (GTask        *task,
+                                         gpointer      source_object,
+                                         gpointer      task_data,
+                                         GCancellable *cancellable)
 {
+  GtdProviderEdsPrivate *priv;
   g_autoptr (GError) error = NULL;
   GtdProviderEds *self;
+  AsyncData *data;
 
   GTD_ENTRY;
 
-  self = GTD_PROVIDER_EDS (gtd_task_list_get_provider (list));
-
-  gtd_object_pop_loading (GTD_OBJECT (self));
-  gtd_object_pop_loading (GTD_OBJECT (list));
+  data = task_data;
+  self = GTD_PROVIDER_EDS (source_object);
+  priv = gtd_provider_eds_get_instance_private (self);
 
-  e_source_registry_commit_source_finish (registry, result, &error);
+  e_source_registry_commit_source_sync (priv->source_registry,
+                                        data->source,
+                                        cancellable,
+                                        &error);
 
-  REPORT_ERROR (_("An error occurred while modifying a task list"), error);
+  if (error)
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      GTD_RETURN ();
+    }
 
-  g_signal_emit_by_name (self, "list-changed", list);
+  g_task_return_boolean (task, TRUE);
 
   GTD_EXIT;
 }
 
+
 static void
-on_task_list_removed_cb (ESource      *source,
-                         GAsyncResult *result,
-                         GtdTaskList  *list)
+remove_task_list_in_thread_cb (GTask        *task,
+                               gpointer      source_object,
+                               gpointer      task_data,
+                               GCancellable *cancellable)
 {
   g_autoptr (GError) error = NULL;
-  GtdProviderEds *self;
+  AsyncData *data;
 
   GTD_ENTRY;
 
-  self = GTD_PROVIDER_EDS (gtd_task_list_get_provider (list));
+  data = task_data;
 
-  gtd_object_pop_loading (GTD_OBJECT (self));
+  e_source_remove_sync (data->source, cancellable, &error);
 
-  e_source_remove_finish (source, result, &error);
+  if (error)
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      GTD_RETURN ();
+    }
 
-  REPORT_ERROR (_("An error occurred while modifying a task list"), error);
-
-  /*
-   * Note: we don't need to emit the "list-removed" signal here
-   * because EDS will emit the "source-removed" signal, and we
-   * emit "list-removed" there.
-   */
+  g_task_return_boolean (task, TRUE);
 
   GTD_EXIT;
 }
@@ -526,70 +604,85 @@ gtd_provider_eds_get_icon (GtdProvider *provider)
 }
 
 static void
-gtd_provider_eds_create_task (GtdProvider *provider,
-                              GtdTaskList *list,
-                              const gchar *title,
-                              GDateTime   *due_date)
+gtd_provider_eds_create_task (GtdProvider         *provider,
+                              GtdTaskList         *list,
+                              const gchar         *title,
+                              GDateTime           *due_date,
+                              GCancellable        *cancellable,
+                              GAsyncReadyCallback  callback,
+                              gpointer             user_data)
 {
-  g_autoptr (ECalComponent) component = NULL;
-  ECalComponent *updated_component;
-  GtdTaskListEds *tasklist;
+  g_autoptr (GTask) task = NULL;
   GtdProviderEds *self;
-  ECalClient *client;
-  GtdTask *new_task;
+  AsyncData *data;
 
   g_return_if_fail (GTD_IS_TASK_LIST_EDS (list));
 
   GTD_ENTRY;
 
   self = GTD_PROVIDER_EDS (provider);
-  tasklist = GTD_TASK_LIST_EDS (list);
-  client = gtd_task_list_eds_get_client (tasklist);
 
-  /* Create the new task */
-  component = e_cal_component_new ();
-  e_cal_component_set_new_vtype (component, E_CAL_COMPONENT_TODO);
+  data = g_new0 (AsyncData, 1);
+  data->list = g_object_ref (list);
+  data->title = g_strdup (title);
+  data->due_date = due_date ? g_date_time_ref (due_date) : NULL;
 
-  new_task = gtd_task_eds_new (component);
-  gtd_task_set_title (new_task, title);
-  gtd_task_set_due_date (new_task, due_date);
-  gtd_task_set_list (new_task, list);
-  gtd_task_set_position (new_task, g_list_model_get_n_items (G_LIST_MODEL (list)));
+  gtd_object_push_loading (GTD_OBJECT (self));
 
-  /* Use the component with the changes we've just done */
-  updated_component = gtd_task_eds_get_component (GTD_TASK_EDS (new_task));
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, gtd_provider_eds_create_task);
+  g_task_set_task_data (task, data, async_data_free);
+  g_task_run_in_thread (task, create_task_in_thread_cb);
 
-  gtd_task_list_add_task (list, new_task);
+  GTD_EXIT;
+}
 
-  /* The task is not ready until we finish the operation */
-  gtd_object_push_loading (GTD_OBJECT (self));
-  gtd_object_push_loading (GTD_OBJECT (new_task));
+static GtdTask*
+gtd_provider_eds_create_task_finish (GtdProvider   *provider,
+                                     GAsyncResult  *result,
+                                     GError       **error)
+{
+  g_autoptr (GtdTask) new_task = NULL;
+  GtdProviderEds *self;
+  GtdTaskList *list;
+  AsyncData *data;
+
+  GTD_ENTRY;
 
-  e_cal_client_create_object (client,
-                              e_cal_component_get_icalcomponent (updated_component),
-                              E_CAL_OPERATION_FLAG_NONE,
-                              NULL,
-                              (GAsyncReadyCallback) on_task_created_cb,
-                              new_task);
+  self = GTD_PROVIDER_EDS (provider);
+  data = g_task_get_task_data (G_TASK (result));
+  list = data->list;
 
-  GTD_EXIT;
+  gtd_object_pop_loading (GTD_OBJECT (self));
+
+  new_task = g_task_propagate_pointer (G_TASK (result), error);
+
+  if (new_task)
+    {
+      gtd_task_set_list (new_task, list);
+      gtd_task_list_add_task (list, new_task);
+      set_default_list (self, list);
+    }
+
+  GTD_RETURN (new_task);
 }
 
 static void
-gtd_provider_eds_update_task (GtdProvider *provider,
-                              GtdTask     *task)
+gtd_provider_eds_update_task (GtdProvider         *provider,
+                              GtdTask             *task,
+                              GCancellable        *cancellable,
+                              GAsyncReadyCallback  callback,
+                              gpointer             user_data)
 {
-  GtdTaskListEds *tasklist;
+  g_autoptr (GTask) gtask = NULL;
   ECalComponent *component;
-  ECalClient *client;
+  AsyncData *data;
 
   GTD_ENTRY;
 
   g_return_if_fail (GTD_IS_TASK (task));
   g_return_if_fail (GTD_IS_TASK_LIST_EDS (gtd_task_get_list (task)));
 
-  tasklist = GTD_TASK_LIST_EDS (gtd_task_get_list (task));
-  client = gtd_task_list_eds_get_client (tasklist);
   component = gtd_task_eds_get_component (GTD_TASK_EDS (task));
 
   e_cal_component_commit_sequence (component);
@@ -598,62 +691,107 @@ gtd_provider_eds_update_task (GtdProvider *provider,
   gtd_object_push_loading (GTD_OBJECT (task));
   gtd_object_push_loading (GTD_OBJECT (provider));
 
-  e_cal_client_modify_object (client,
-                              e_cal_component_get_icalcomponent (component),
-                              E_CAL_OBJ_MOD_THIS,
-                              E_CAL_OPERATION_FLAG_NONE,
-                              NULL,
-                              (GAsyncReadyCallback) on_task_modified_cb,
-                              task);
+  data = g_new0 (AsyncData, 1);
+  data->task = g_object_ref (task);
+  data->component = e_cal_component_clone (component);
+
+  gtask = g_task_new (provider, cancellable, callback, user_data);
+  g_task_set_source_tag (gtask, gtd_provider_eds_update_task);
+  g_task_set_task_data (gtask, data, async_data_free);
+  g_task_run_in_thread (gtask, update_task_in_thread_cb);
 
   GTD_EXIT;
 }
 
+static gboolean
+gtd_provider_eds_update_task_finish (GtdProvider   *provider,
+                                     GAsyncResult  *result,
+                                     GError       **error)
+{
+  GtdProviderEds *self;
+  AsyncData *data;
+  GtdTask *task;
+
+  GTD_ENTRY;
+
+  self = GTD_PROVIDER_EDS (provider);
+  data = g_task_get_task_data (G_TASK (result));
+  task = data->task;
+
+  gtd_object_pop_loading (GTD_OBJECT (self));
+  gtd_object_pop_loading (GTD_OBJECT (task));
+
+  if (!g_task_propagate_boolean (G_TASK (result), error))
+    {
+      gtd_task_eds_revert (GTD_TASK_EDS (task));
+      GTD_RETURN (FALSE);
+    }
+
+  gtd_task_eds_apply (GTD_TASK_EDS (task));
+  gtd_task_list_update_task (gtd_task_get_list (task), task);
+
+  GTD_RETURN (TRUE);
+}
+
 static void
-gtd_provider_eds_remove_task (GtdProvider *provider,
-                              GtdTask     *task)
+gtd_provider_eds_remove_task (GtdProvider         *provider,
+                              GtdTask             *task,
+                              GCancellable        *cancellable,
+                              GAsyncReadyCallback  callback,
+                              gpointer             user_data)
 {
-  g_autoptr (ECalComponentId) id = NULL;
-  GtdTaskListEds *tasklist;
+  g_autoptr (GTask) gtask = NULL;
   ECalComponent *component;
-  ECalClient *client;
+  AsyncData *data;
 
   GTD_ENTRY;
 
   g_return_if_fail (GTD_IS_TASK (task));
   g_return_if_fail (GTD_IS_TASK_LIST_EDS (gtd_task_get_list (task)));
 
-  tasklist = GTD_TASK_LIST_EDS (gtd_task_get_list (task));
-  client = gtd_task_list_eds_get_client (tasklist);
   component = gtd_task_eds_get_component (GTD_TASK_EDS (task));
-  id = e_cal_component_get_id (component);
 
   gtd_object_push_loading (GTD_OBJECT (provider));
 
-  e_cal_client_remove_object (client,
-                              e_cal_component_id_get_uid (id),
-                              e_cal_component_id_get_rid (id),
-                              E_CAL_OBJ_MOD_THIS,
-                              E_CAL_OPERATION_FLAG_NONE,
-                              NULL,
-                              (GAsyncReadyCallback) on_task_removed_cb,
-                              provider);
+  data = g_new0 (AsyncData, 1);
+  data->task = g_object_ref (task);
+  data->component = e_cal_component_clone (component);
+
+  gtask = g_task_new (provider, cancellable, callback, user_data);
+  g_task_set_source_tag (gtask, gtd_provider_eds_remove_task);
+  g_task_set_task_data (gtask, data, async_data_free);
+  g_task_run_in_thread (gtask, remove_task_in_thread_cb);
 
   GTD_EXIT;
 }
 
+static gboolean
+gtd_provider_eds_remove_task_finish (GtdProvider   *provider,
+                                     GAsyncResult  *result,
+                                     GError       **error)
+{
+  GTD_ENTRY;
+
+  gtd_object_pop_loading (GTD_OBJECT (provider));
+
+  GTD_RETURN (g_task_propagate_boolean (G_TASK (result), error));
+}
+
 static void
-gtd_provider_eds_create_task_list (GtdProvider *provider,
-                                   const gchar *name)
+gtd_provider_eds_create_task_list (GtdProvider         *provider,
+                                   const gchar         *name,
+                                   GCancellable        *cancellable,
+                                   GAsyncReadyCallback  callback,
+                                   gpointer             user_data)
 {
-  GtdProviderEdsPrivate *priv;
+  g_autoptr (GTask) task = NULL;
   GtdProviderEds *self;
+  AsyncData *data;
   ESource *source;
 
   GTD_ENTRY;
 
   self = GTD_PROVIDER_EDS (provider);
-  priv = gtd_provider_eds_get_instance_private (self);
   source = NULL;
 
   /* Create an ESource */
@@ -663,25 +801,47 @@ gtd_provider_eds_create_task_list (GtdProvider *provider,
   if (!source)
     return;
 
-  gtd_object_push_loading (GTD_OBJECT (provider));
-
   /* EDS properties */
   e_source_set_display_name (source, name);
 
-  e_source_registry_commit_source (priv->source_registry,
-                                   source,
-                                   NULL,
-                                   (GAsyncReadyCallback) on_task_list_created_cb,
-                                   provider);
+  data = g_new0 (AsyncData, 1);
+  data->title = g_strdup (name);
+  data->source = g_object_ref (source);
+
+  gtd_object_push_loading (GTD_OBJECT (provider));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, gtd_provider_eds_create_task_list);
+  g_task_set_task_data (task, data, async_data_free);
+  g_task_run_in_thread (task, create_or_update_task_list_in_thread_cb);
 
   GTD_EXIT;
 }
 
+static gboolean
+gtd_provider_eds_create_task_list_finish (GtdProvider   *provider,
+                                          GAsyncResult  *result,
+                                          GError       **error)
+{
+  GtdProviderEds *self;
+
+  GTD_ENTRY;
+
+  self = GTD_PROVIDER_EDS (provider);
+  gtd_object_pop_loading (GTD_OBJECT (self));
+
+  GTD_RETURN (g_task_propagate_boolean (G_TASK (result), error));
+}
+
 static void
-gtd_provider_eds_update_task_list (GtdProvider *provider,
-                                   GtdTaskList *list)
+gtd_provider_eds_update_task_list (GtdProvider         *provider,
+                                   GtdTaskList         *list,
+                                   GCancellable        *cancellable,
+                                   GAsyncReadyCallback  callback,
+                                   gpointer             user_data)
 {
-  GtdProviderEdsPrivate *priv;
+  g_autoptr (GTask) task = NULL;
+  AsyncData *data;
   ESource *source;
 
   GTD_ENTRY;
@@ -689,25 +849,53 @@ gtd_provider_eds_update_task_list (GtdProvider *provider,
   g_assert (GTD_IS_TASK_LIST_EDS (list));
   g_assert (gtd_task_list_eds_get_source (GTD_TASK_LIST_EDS (list)) != NULL);
 
-  priv = gtd_provider_eds_get_instance_private (GTD_PROVIDER_EDS (provider));
   source = gtd_task_list_eds_get_source (GTD_TASK_LIST_EDS (list));
 
   gtd_object_push_loading (GTD_OBJECT (provider));
   gtd_object_push_loading (GTD_OBJECT (list));
 
-  e_source_registry_commit_source (priv->source_registry,
-                                   source,
-                                   NULL,
-                                   (GAsyncReadyCallback) on_task_list_modified_cb,
-                                   list);
+  data = g_new0 (AsyncData, 1);
+  data->list = g_object_ref (list);
+  data->source = g_object_ref (source);
+
+  task = g_task_new (provider, cancellable, callback, user_data);
+  g_task_set_source_tag (task, gtd_provider_eds_update_task_list);
+  g_task_set_task_data (task, data, async_data_free);
+  g_task_run_in_thread (task, create_or_update_task_list_in_thread_cb);
 
   GTD_EXIT;
 }
 
+static gboolean
+gtd_provider_eds_update_task_list_finish (GtdProvider   *provider,
+                                          GAsyncResult  *result,
+                                          GError       **error)
+{
+  GtdProviderEds *self;
+  AsyncData *data;
+
+  GTD_ENTRY;
+
+  self = GTD_PROVIDER_EDS (provider);
+  data = g_task_get_task_data (G_TASK (result));
+
+  gtd_object_pop_loading (GTD_OBJECT (data->list));
+  gtd_object_pop_loading (GTD_OBJECT (self));
+
+  g_signal_emit_by_name (self, "list-changed", data->list);
+
+  GTD_RETURN (g_task_propagate_boolean (G_TASK (result), error));
+}
+
 static void
-gtd_provider_eds_remove_task_list (GtdProvider *provider,
-                                   GtdTaskList *list)
+gtd_provider_eds_remove_task_list (GtdProvider         *provider,
+                                   GtdTaskList         *list,
+                                   GCancellable        *cancellable,
+                                   GAsyncReadyCallback  callback,
+                                   gpointer             user_data)
 {
+  g_autoptr (GTask) gtask = NULL;
+  AsyncData *data;
   ESource *source;
 
   GTD_ENTRY;
@@ -719,14 +907,29 @@ gtd_provider_eds_remove_task_list (GtdProvider *provider,
 
   gtd_object_push_loading (GTD_OBJECT (provider));
 
-  e_source_remove (source,
-                   NULL,
-                   (GAsyncReadyCallback) on_task_list_removed_cb,
-                   list);
+  data = g_new0 (AsyncData, 1);
+  data->source = g_object_ref (source);
+
+  gtask = g_task_new (provider, cancellable, callback, user_data);
+  g_task_set_source_tag (gtask, gtd_provider_eds_remove_task_list);
+  g_task_set_task_data (gtask, data, async_data_free);
+  g_task_run_in_thread (gtask, remove_task_list_in_thread_cb);
 
   GTD_EXIT;
 }
 
+static gboolean
+gtd_provider_eds_remove_task_list_finish (GtdProvider   *provider,
+                                          GAsyncResult  *result,
+                                          GError       **error)
+{
+  GTD_ENTRY;
+
+  gtd_object_pop_loading (GTD_OBJECT (provider));
+
+  GTD_RETURN (g_task_propagate_boolean (G_TASK (result), error));
+}
+
 static GList*
 gtd_provider_eds_get_task_lists (GtdProvider *provider)
 {
@@ -754,11 +957,17 @@ gtd_provider_iface_init (GtdProviderInterface *iface)
   iface->refresh = gtd_provider_eds_refresh;
   iface->get_icon = gtd_provider_eds_get_icon;
   iface->create_task = gtd_provider_eds_create_task;
+  iface->create_task_finish = gtd_provider_eds_create_task_finish;
   iface->update_task = gtd_provider_eds_update_task;
+  iface->update_task_finish = gtd_provider_eds_update_task_finish;
   iface->remove_task = gtd_provider_eds_remove_task;
+  iface->remove_task_finish = gtd_provider_eds_remove_task_finish;
   iface->create_task_list = gtd_provider_eds_create_task_list;
+  iface->create_task_list_finish = gtd_provider_eds_create_task_list_finish;
   iface->update_task_list = gtd_provider_eds_update_task_list;
+  iface->update_task_list_finish = gtd_provider_eds_update_task_list_finish;
   iface->remove_task_list = gtd_provider_eds_remove_task_list;
+  iface->remove_task_list_finish = gtd_provider_eds_remove_task_list_finish;
   iface->get_task_lists = gtd_provider_eds_get_task_lists;
   iface->get_inbox = gtd_provider_eds_get_inbox;
 }
diff --git a/src/plugins/task-lists-workspace/gtd-sidebar.c b/src/plugins/task-lists-workspace/gtd-sidebar.c
index 94e336b..aa03ce0 100644
--- a/src/plugins/task-lists-workspace/gtd-sidebar.c
+++ b/src/plugins/task-lists-workspace/gtd-sidebar.c
@@ -362,6 +362,16 @@ on_panel_removed_cb (GtdManager *manager,
     gtk_widget_destroy (GTK_WIDGET (row));
 }
 
+static void
+on_provider_task_list_removed_cb (GObject      *source,
+                                  GAsyncResult *result,
+                                  gpointer      user_data)
+{
+  g_autoptr (GError) error = NULL;
+
+  gtd_provider_remove_task_list_finish (GTD_PROVIDER (source), result, &error);
+}
+
 static void
 delete_list_cb (GtdNotification *notification,
                 gpointer         user_data)
@@ -375,7 +385,11 @@ delete_list_cb (GtdNotification *notification,
   g_assert (provider != NULL);
   g_assert (gtd_task_list_is_removable (list));
 
-  gtd_provider_remove_task_list (provider, list);
+  gtd_provider_remove_task_list (provider,
+                                 list,
+                                 NULL,
+                                 on_provider_task_list_removed_cb,
+                                 NULL);
 }
 
 static void
diff --git a/src/plugins/task-lists-workspace/gtd-task-list-panel.c 
b/src/plugins/task-lists-workspace/gtd-task-list-panel.c
index e48c786..e3fbecc 100644
--- a/src/plugins/task-lists-workspace/gtd-task-list-panel.c
+++ b/src/plugins/task-lists-workspace/gtd-task-list-panel.c
@@ -52,6 +52,10 @@ static void          on_colors_flowbox_child_activated_cb        (GtkFlowBox
                                                                   GtkFlowBoxChild    *child,
                                                                   GtdTaskListPanel   *self);
 
+static void          on_task_list_updated_cb                     (GObject           *source,
+                                                                  GAsyncResult      *result,
+                                                                  gpointer           user_data);
+
 static void          gtd_panel_iface_init                        (GtdPanelInterface  *iface);
 
 
@@ -177,7 +181,11 @@ rename_list (GtdTaskListPanel *self)
   if (g_strcmp0 (new_name, gtd_task_list_get_name (list)) != 0)
     {
       gtd_task_list_set_name (list, new_name);
-      gtd_provider_update_task_list (gtd_task_list_get_provider (list), list);
+      gtd_provider_update_task_list (gtd_task_list_get_provider (list),
+                                     list,
+                                     NULL,
+                                     on_task_list_updated_cb,
+                                     self);
     }
 
   gtk_popover_popdown (self->popover);
@@ -208,6 +216,27 @@ update_archive_button (GtdTaskListPanel *self)
  * Callbacks
  */
 
+static void
+on_task_list_updated_cb (GObject      *source,
+                         GAsyncResult *result,
+                         gpointer      user_data)
+{
+  g_autoptr (GError) error = NULL;
+
+  gtd_provider_update_task_list_finish (GTD_PROVIDER (source), result, &error);
+
+  if (error)
+    {
+      g_warning ("Error creating task: %s", error->message);
+
+      gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                      _("An error occurred while updating a task"),
+                                      error->message,
+                                      NULL,
+                                      NULL);
+    }
+}
+
 static void
 on_archive_button_clicked_cb (GtkButton        *button,
                               GtdTaskListPanel *self)
@@ -227,7 +256,11 @@ on_archive_button_clicked_cb (GtkButton        *button,
   update_archive_button (self);
 
   provider = gtd_task_list_get_provider (list);
-  gtd_provider_update_task_list (provider, list);
+  gtd_provider_update_task_list (provider,
+                                 list,
+                                 NULL,
+                                 on_task_list_updated_cb,
+                                 self);
 
   GTD_EXIT;
 }
@@ -260,7 +293,11 @@ on_colors_flowbox_child_activated_cb (GtkFlowBox       *colors_flowbox,
   color = gtd_color_button_get_color (GTD_COLOR_BUTTON (color_button));
   gtd_task_list_set_color (list, color);
 
-  gtd_provider_update_task_list (gtd_task_list_get_provider (list), list);
+  gtd_provider_update_task_list (gtd_task_list_get_provider (list),
+                                 list,
+                                 NULL,
+                                 on_task_list_updated_cb,
+                                 self);
 
   self->previous_color_button = color_button;
 }
diff --git a/src/provider/gtd-provider-popover.c b/src/provider/gtd-provider-popover.c
index 42b41bb..5fd876c 100644
--- a/src/provider/gtd-provider-popover.c
+++ b/src/provider/gtd-provider-popover.c
@@ -1,6 +1,6 @@
 /* gtd-provider-popover.c
  *
- * Copyright (C) 2015 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ * Copyright (C) 2015-2020 Georges Basile Stavracas Neto <georges stavracas 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
@@ -80,6 +80,27 @@ gtd_provider_popover__closed (GtdProviderPopover *popover)
   gtk_stack_set_visible_child_name (GTK_STACK (popover->stack), "main");
 }
 
+static void
+on_task_list_created_cb (GObject      *source,
+                         GAsyncResult *result,
+                         gpointer      user_data)
+{
+  g_autoptr (GError) error = NULL;
+
+  gtd_provider_create_task_list_finish (GTD_PROVIDER (source), result, &error);
+
+  if (error)
+    {
+      g_warning ("Error creating task list: %s", error->message);
+
+      gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                      _("An error occurred while creating a task list"),
+                                      error->message,
+                                      NULL,
+                                      NULL);
+    }
+}
+
 static void
 create_task_list (GtdProviderPopover *popover)
 {
@@ -89,7 +110,11 @@ create_task_list (GtdProviderPopover *popover)
   provider = gtd_provider_selector_get_selected_provider (GTD_PROVIDER_SELECTOR 
(popover->provider_selector));
   name = gtk_editable_get_text (popover->new_list_name_entry);
 
-  gtd_provider_create_task_list (provider, name);
+  gtd_provider_create_task_list (provider,
+                                 name,
+                                 NULL,
+                                 on_task_list_created_cb,
+                                 popover);
 }
 
 static void
diff --git a/src/task-list-view/gtd-dnd-row.c b/src/task-list-view/gtd-dnd-row.c
index b4d9c73..77825ff 100644
--- a/src/task-list-view/gtd-dnd-row.c
+++ b/src/task-list-view/gtd-dnd-row.c
@@ -1,6 +1,6 @@
 /* gtd-dnd-row.c
  *
- * Copyright (C) 2016 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ * Copyright (C) 2016-2020 Georges Basile Stavracas Neto <georges stavracas 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
@@ -72,6 +72,27 @@ update_row_padding (GtdDndRow *self)
   gtk_widget_set_margin_start (self->box, self->depth * 32);
 }
 
+static void
+on_task_updated_cb (GObject      *object,
+                    GAsyncResult *result,
+                    gpointer      user_data)
+{
+  g_autoptr (GError) error = NULL;
+  GtdDndRow *self;
+
+  self = GTD_DND_ROW (user_data);
+
+  gtd_provider_update_task_finish (GTD_PROVIDER (object), result, &error);
+
+  if (error)
+    {
+      g_warning ("Error updating task: %s", error->message);
+      return;
+    }
+
+  gtk_list_box_invalidate_sort (GTK_LIST_BOX (gtk_widget_get_parent (GTK_WIDGET (self))));
+}
+
 static void
 gtd_dnd_row_finalize (GObject *object)
 {
@@ -269,9 +290,11 @@ gtd_dnd_row_drag_drop (GtkWidget  *widget,
   gtd_task_set_position (row_task, -1);
 
   /* Save the task */
-  gtd_provider_update_task (gtd_task_get_provider (row_task), row_task);
-
-  gtk_list_box_invalidate_sort (GTK_LIST_BOX (gtk_widget_get_parent (widget)));
+  gtd_provider_update_task (gtd_task_get_provider (row_task),
+                            row_task,
+                            NULL,
+                            on_task_updated_cb,
+                            widget);
 
   return FALSE;
 }
diff --git a/src/task-list-view/gtd-new-task-row.c b/src/task-list-view/gtd-new-task-row.c
index 315b83d..f3d0809 100644
--- a/src/task-list-view/gtd-new-task-row.c
+++ b/src/task-list-view/gtd-new-task-row.c
@@ -108,6 +108,33 @@ show_task_list_selector_popover (GtdNewTaskRow *self)
  * Callbacks
  */
 
+static void
+on_task_created_cb (GObject      *object,
+                    GAsyncResult *result,
+                    gpointer      user_data)
+{
+  g_autoptr (GError) error = NULL;
+  GtdNewTaskRow *self;
+  GtdTask *new_task;
+
+  self = GTD_NEW_TASK_ROW (user_data);
+  new_task = gtd_provider_create_task_finish (GTD_PROVIDER (object), result, &error);
+
+  if (!new_task)
+    {
+      g_warning ("Error creating task: %s", error->message);
+
+      gtd_manager_emit_error_message (gtd_manager_get_default (),
+                                      _("An error occurred while creating a task"),
+                                      error->message,
+                                      NULL,
+                                      NULL);
+    }
+
+  gtk_editable_set_text (GTK_EDITABLE (self->entry), "");
+  gtk_widget_set_sensitive (GTK_WIDGET (self->entry), TRUE);
+}
+
 static void
 entry_activated_cb (GtdNewTaskRow *self)
 {
@@ -137,12 +164,15 @@ entry_activated_cb (GtdNewTaskRow *self)
 
   g_return_if_fail (GTD_IS_TASK_LIST (list));
 
+  gtk_widget_set_sensitive (GTK_WIDGET (self->entry), FALSE);
+
   gtd_provider_create_task (gtd_task_list_get_provider (list),
                             list,
                             gtk_editable_get_text (GTK_EDITABLE (self->entry)),
-                            gtd_task_list_view_get_default_date (view));
-
-  gtk_editable_set_text (GTK_EDITABLE (self->entry), "");
+                            gtd_task_list_view_get_default_date (view),
+                            NULL,
+                            on_task_created_cb,
+                            self);
 }
 
 static void
diff --git a/src/task-list-view/gtd-task-list-view.c b/src/task-list-view/gtd-task-list-view.c
index 00a4063..d109c04 100644
--- a/src/task-list-view/gtd-task-list-view.c
+++ b/src/task-list-view/gtd-task-list-view.c
@@ -354,11 +354,28 @@ scroll_to_bottom_cb (gpointer data)
   return G_SOURCE_REMOVE;
 }
 
+static void
+on_task_removed_cb (GObject      *source,
+                    GAsyncResult *result,
+                    gpointer      user_data)
+{
+  g_autoptr (GError) error = NULL;
+
+  gtd_provider_remove_task_finish (GTD_PROVIDER (source), result, &error);
+
+  if (error)
+    g_warning ("Error removing task list: %s", error->message);
+}
+
 static inline gboolean
 remove_task_cb (GtdTaskListView *self,
                 GtdTask         *task)
 {
-  gtd_provider_remove_task (gtd_task_get_provider (task), task);
+  gtd_provider_remove_task (gtd_task_get_provider (task),
+                            task,
+                            NULL,
+                            on_task_removed_cb,
+                            self);
   return TRUE;
 }
 
@@ -907,7 +924,7 @@ on_drop_target_drag_drop_cb (GtkDropTarget   *drop_target,
 
   /* Finally, save the task */
   provider = gtd_task_list_get_provider (gtd_task_get_list (source_task));
-  gtd_provider_update_task (provider, source_task);
+  gtd_provider_update_task (provider, source_task, NULL, NULL, NULL);
 
   check_dnd_scroll (self, TRUE, -1);
   gdk_drop_finish (drop, GDK_ACTION_MOVE);
diff --git a/src/task-list-view/gtd-task-row.c b/src/task-list-view/gtd-task-row.c
index e653ec0..6d6c835 100644
--- a/src/task-list-view/gtd-task-row.c
+++ b/src/task-list-view/gtd-task-row.c
@@ -188,6 +188,22 @@ create_transient_row (GtdTaskRow *self)
  * Callbacks
  */
 
+static void
+on_task_updated_cb (GObject      *object,
+                    GAsyncResult *result,
+                    gpointer      user_data)
+{
+  g_autoptr (GError) error = NULL;
+
+  gtd_provider_update_task_finish (GTD_PROVIDER (object), result, &error);
+
+  if (error)
+    {
+      g_warning ("Error updating task: %s", error->message);
+      return;
+    }
+}
+
 static void
 on_remove_task_cb (GtdEditPane *edit_panel,
                    GtdTask     *task,
@@ -318,7 +334,11 @@ on_complete_check_toggled_cb (GtkToggleButton *button,
   g_assert (GTD_IS_TASK (self->task));
 
   gtd_task_set_complete (self->task, gtk_toggle_button_get_active (button));
-  gtd_provider_update_task (gtd_task_get_provider (self->task), self->task);
+  gtd_provider_update_task (gtd_task_get_provider (self->task),
+                            self->task,
+                            NULL,
+                            on_task_updated_cb,
+                            self);
 
   GTD_EXIT;
 }
@@ -378,7 +398,11 @@ on_star_widget_activated_cb (GtdStarWidget *star_widget,
   g_signal_handlers_block_by_func (self->task, on_task_important_changed_cb, self);
 
   gtd_task_set_important (self->task, gtd_star_widget_get_active (star_widget));
-  gtd_provider_update_task (gtd_task_get_provider (self->task), self->task);
+  gtd_provider_update_task (gtd_task_get_provider (self->task),
+                            self->task,
+                            NULL,
+                            on_task_updated_cb,
+                            self);
 
   g_signal_handlers_unblock_by_func (self->task, on_task_important_changed_cb, self);
 }
@@ -423,7 +447,13 @@ gtd_task_row_finalize (GObject *object)
   if (self->changed)
     {
       if (self->task)
-        gtd_provider_update_task (gtd_task_get_provider (self->task), self->task);
+        {
+          gtd_provider_update_task (gtd_task_get_provider (self->task),
+                                    self->task,
+                                    NULL,
+                                    on_task_updated_cb,
+                                    self);
+        }
       self->changed = FALSE;
     }
 
@@ -862,7 +892,11 @@ gtd_task_row_set_active (GtdTaskRow *self,
     {
       g_debug ("Saving taskā€¦");
 
-      gtd_provider_update_task (gtd_task_get_provider (self->task), self->task);
+      gtd_provider_update_task (gtd_task_get_provider (self->task),
+                                self->task,
+                                NULL,
+                                on_task_updated_cb,
+                                self);
       self->changed = FALSE;
     }
 
diff --git a/tests/dummy-provider.c b/tests/dummy-provider.c
index cd92984..1f1a70b 100644
--- a/tests/dummy-provider.c
+++ b/tests/dummy-provider.c
@@ -129,10 +129,13 @@ dummy_provider_get_icon (GtdProvider *provider)
   return g_themed_icon_new ("face-monkey-symbolic");
 }
 static void
-dummy_provider_create_task (GtdProvider *provider,
-                           GtdTaskList *list,
-                           const gchar *title,
-                           GDateTime   *due_date)
+dummy_provider_create_task (GtdProvider         *provider,
+                            GtdTaskList         *list,
+                            const gchar         *title,
+                            GDateTime           *due_date,
+                            GCancellable        *cancellable,
+                            GAsyncReadyCallback  callback,
+                            gpointer             user_data)
 {
 }
 
@@ -150,8 +153,11 @@ dummy_provider_remove_task (GtdProvider *provider,
 }
 
 static void
-dummy_provider_create_task_list (GtdProvider *provider,
-                                const gchar *name)
+dummy_provider_create_task_list (GtdProvider         *provider,
+                                 const gchar         *name,
+                                 GCancellable        *cancellable,
+                                 GAsyncReadyCallback  callback,
+                                 gpointer             user_data)
 {
   GSequenceIter *iter;
   DummyProvider *self;
@@ -328,7 +334,7 @@ dummy_provider_generate_task_list (DummyProvider *self)
    *    - Task
    */
 
-  gtd_provider_create_task_list (GTD_PROVIDER (self), "List");
+  gtd_provider_create_task_list (GTD_PROVIDER (self), "List", NULL, NULL, NULL);
   iter = g_sequence_iter_prev (g_sequence_get_end_iter (self->lists));
   list = g_sequence_get (iter);
 
@@ -397,7 +403,7 @@ dummy_provider_generate_task_lists (DummyProvider *self)
       guint32 n_tasks;
 
       list_name = g_strdup_printf ("List %u", task_id++ + 1);
-      gtd_provider_create_task_list (GTD_PROVIDER (self), list_name);
+      gtd_provider_create_task_list (GTD_PROVIDER (self), list_name, NULL, NULL, NULL);
 
       /* The new list is the last one */
       iter = g_sequence_iter_prev (g_sequence_get_end_iter (self->lists));


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