[gnome-todo] storage: refactor hierarchy



commit 9446942b0880dd1075fd96553d1849103693a35c
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Mon Aug 24 12:07:51 2015 -0300

    storage: refactor hierarchy
    
    To make GtdStorage more flexible and to prepare ouselves
    for the future, make GtdStorage and abstract class and
    implement it for local and GOA.

 po/POTFILES.in                     |    2 +
 src/Makefile.am                    |    4 +
 src/gtd-manager.c                  |   30 ++--
 src/storage/gtd-storage-goa.c      |  314 +++++++++++++++++++++++++++++++
 src/storage/gtd-storage-goa.h      |   45 +++++
 src/storage/gtd-storage-local.c    |  136 ++++++++++++++
 src/storage/gtd-storage-local.h    |   38 ++++
 src/storage/gtd-storage-row.c      |    2 +-
 src/storage/gtd-storage-selector.c |   15 ++-
 src/storage/gtd-storage.c          |  359 +++++++++---------------------------
 src/storage/gtd-storage.h          |   35 ++--
 11 files changed, 671 insertions(+), 309 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9cc33ab..a7a4557 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -27,6 +27,8 @@ src/gtd-window.c
 src/main.c
 src/storage/gtd-storage.c
 src/storage/gtd-storage-dialog.c
+src/storage/gtd-storage-goa.c
+src/storage/gtd-storage-local.c
 src/storage/gtd-storage-popover.c
 src/storage/gtd-storage-row.c
 src/storage/gtd-storage-selector.c
diff --git a/src/Makefile.am b/src/Makefile.am
index acf0e11..de45715 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,6 +28,10 @@ gnome_todo_SOURCES = \
        storage/gtd-storage.h \
        storage/gtd-storage-dialog.c \
        storage/gtd-storage-dialog.h \
+       storage/gtd-storage-goa.c \
+       storage/gtd-storage-goa.h \
+       storage/gtd-storage-local.c \
+       storage/gtd-storage-local.h \
        storage/gtd-storage-popover.c \
        storage/gtd-storage-popover.h \
        storage/gtd-storage-row.c \
diff --git a/src/gtd-manager.c b/src/gtd-manager.c
index 2c6a024..038bbd1 100644
--- a/src/gtd-manager.c
+++ b/src/gtd-manager.c
@@ -17,6 +17,8 @@
  */
 
 #include "gtd-manager.h"
+#include "gtd-storage-goa.h"
+#include "gtd-storage-local.h"
 #include "gtd-storage.h"
 #include "gtd-task.h"
 #include "gtd-task-list.h"
@@ -134,7 +136,7 @@ is_today (GDateTime *dt)
 
 static void
 gtd_manager__setup_url (GtdManager *manager,
-                        GtdStorage *storage)
+                        GtdStorageGoa *storage)
 {
   GtdManagerPrivate *priv;
   GList *sources;
@@ -171,9 +173,9 @@ gtd_manager__setup_url (GtdManager *manager,
           goa_ext = e_source_get_extension (goa_source, E_SOURCE_EXTENSION_GOA);
 
           /* Found an ESourceGoa with the same uid of storage */
-          if (g_strcmp0 (e_source_goa_get_account_id (goa_ext), gtd_storage_get_id (storage)) == 0)
+          if (g_strcmp0 (e_source_goa_get_account_id (goa_ext), gtd_storage_get_id (GTD_STORAGE (storage))) 
== 0)
             {
-              gtd_storage_set_parent (storage, e_source_get_uid (source));
+              gtd_storage_goa_set_parent (storage, e_source_get_uid (source));
               break;
             }
         }
@@ -273,15 +275,12 @@ gtd_manager__goa_account_added_cb (GoaClient  *client,
 
       default_location = g_settings_get_string (priv->settings, "storage-location");
 
-      storage = gtd_storage_new (goa_account_get_id (account),
-                                 goa_account_get_provider_type (account),
-                                 goa_account_get_provider_name (account),
-                                 goa_account_get_identity (account));
+      storage = gtd_storage_goa_new (account);
 
       gtd_storage_set_enabled (storage, !goa_account_get_calendar_disabled (account));
       gtd_storage_set_is_default (storage, g_strcmp0 (gtd_storage_get_id (storage), default_location) == 0);
 
-      gtd_manager__setup_url (manager, storage);
+      gtd_manager__setup_url (manager, GTD_STORAGE_GOA (storage));
 
       priv->storage_locations = g_list_insert_sorted (priv->storage_locations,
                                                       storage,
@@ -331,15 +330,13 @@ gtd_manager__goa_client_finish_cb (GObject      *client,
             {
               GtdStorage *storage;
 
-              storage = gtd_storage_new (goa_account_get_id (account),
-                                         goa_account_get_provider_type (account),
-                                         goa_account_get_provider_name (account),
-                                         goa_account_get_identity (account));
-
+              storage = gtd_storage_goa_new (account);
               gtd_storage_set_enabled (storage, !goa_account_get_calendar_disabled (account));
               gtd_storage_set_is_default (storage, g_strcmp0 (gtd_storage_get_id (storage), 
default_location) == 0);
 
-              gtd_manager__setup_url (GTD_MANAGER (user_data), storage);
+              g_assert (gtd_storage_goa_get_account (GTD_STORAGE_GOA (storage)) == account);
+
+              gtd_manager__setup_url (GTD_MANAGER (user_data), GTD_STORAGE_GOA (storage));
 
               priv->storage_locations = g_list_insert_sorted (priv->storage_locations,
                                                               storage,
@@ -1032,10 +1029,7 @@ gtd_manager_constructed (GObject *object)
                          object);
 
   /* local storage location */
-  local_storage = gtd_storage_new ("local",
-                                   "local",
-                                   _("Local"),
-                                   _("On This Computer"));
+  local_storage = gtd_storage_local_new ();
   gtd_storage_set_enabled (local_storage, TRUE);
   gtd_storage_set_is_default (local_storage, g_strcmp0 (default_location, "local") == 0);
 
diff --git a/src/storage/gtd-storage-goa.c b/src/storage/gtd-storage-goa.c
new file mode 100644
index 0000000..0f303dd
--- /dev/null
+++ b/src/storage/gtd-storage-goa.c
@@ -0,0 +1,314 @@
+/* gtd-storage-goa.c
+ *
+ * Copyright (C) 2015 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gtd-storage-goa.h"
+#include "gtd-storage.h"
+#include "gtd-task-list.h"
+
+#include <glib/gi18n.h>
+
+struct _GtdStorageGoa
+{
+  GtdStorage          parent;
+
+  GoaAccount         *account;
+  GIcon              *icon;
+  gchar              *parent_source;
+};
+
+G_DEFINE_TYPE (GtdStorageGoa, gtd_storage_goa, GTD_TYPE_STORAGE)
+
+enum {
+  PROP_0,
+  PROP_ACCOUNT,
+  PROP_PARENT,
+  LAST_PROP
+};
+
+static GIcon*
+gtd_storage_goa_get_icon (GtdStorage *storage)
+{
+  g_return_val_if_fail (GTD_IS_STORAGE_GOA (storage), NULL);
+
+  return GTD_STORAGE_GOA (storage)->icon;
+}
+
+static GtdTaskList*
+gtd_storage_goa_create_list (GtdStorage  *storage,
+                             const gchar *name)
+{
+  GtdStorageGoa *self;
+  GtdTaskList *task_list;
+  ESource *source;
+  GError *error;
+
+  g_return_val_if_fail (GTD_IS_STORAGE_GOA (storage), NULL);
+
+  self = GTD_STORAGE_GOA (storage);
+  error = NULL;
+  source = e_source_new (NULL,
+                         NULL,
+                         &error);
+
+  if (error)
+    {
+      g_warning ("%s: %s: %s",
+                 G_STRFUNC,
+                 _("Error creating new task list"),
+                 error->message);
+
+      g_clear_error (&error);
+      return NULL;
+    }
+
+  /* Some properties */
+  e_source_set_display_name (source, name);
+  e_source_set_parent (source, self->parent_source);
+
+  /* TODO: create source for GOA account */
+  e_source_get_extension (source, E_SOURCE_EXTENSION_TASK_LIST);
+
+  /* Create task list */
+  task_list = gtd_task_list_new (source, gtd_storage_get_name (storage));
+
+  return task_list;
+}
+
+static gint
+gtd_storage_goa_compare (GtdStorage *a,
+                         GtdStorage *b)
+{
+  GoaAccount *account_a;
+  GoaAccount *account_b;
+  gint retval;
+
+  /*
+   * If any of the compared storages is not a GOA storage, we have
+   * no means to properly compare them. Simply return 0 and let the
+   * parent class' call decide what to do.
+   */
+  if (!GTD_IS_STORAGE_GOA (a) || !GTD_IS_STORAGE_GOA (b))
+    return 0;
+
+  account_a = gtd_storage_goa_get_account (GTD_STORAGE_GOA (a));
+  account_b = gtd_storage_goa_get_account (GTD_STORAGE_GOA (b));
+
+  retval = g_strcmp0 (goa_account_get_provider_type (account_b), goa_account_get_provider_type (account_a));
+
+  if (retval != 0)
+    return retval;
+
+  retval = g_strcmp0 (gtd_storage_get_id (b), gtd_storage_get_id (a));
+
+  return retval;
+}
+
+static void
+gtd_storage_goa_finalize (GObject *object)
+{
+  GtdStorageGoa *self = (GtdStorageGoa *)object;
+
+  g_clear_object (&self->account);
+  g_clear_object (&self->icon);
+  g_clear_pointer (&self->parent_source, g_free);
+
+  G_OBJECT_CLASS (gtd_storage_goa_parent_class)->finalize (object);
+}
+
+static void
+gtd_storage_goa_get_property (GObject    *object,
+                              guint       prop_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+  GtdStorageGoa *self = GTD_STORAGE_GOA (object);
+
+  switch (prop_id)
+    {
+    case PROP_ACCOUNT:
+      g_value_set_object (value, self->account);
+      break;
+
+    case PROP_PARENT:
+      g_value_set_string (value, gtd_storage_goa_get_parent (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_storage_goa_set_property (GObject      *object,
+                              guint         prop_id,
+                              const GValue *value,
+                              GParamSpec   *pspec)
+{
+  GtdStorageGoa *self = GTD_STORAGE_GOA (object);
+
+  g_message ("%s", G_STRFUNC);
+
+  switch (prop_id)
+    {
+    case PROP_ACCOUNT:
+      g_set_object (&self->account, g_value_get_object (value));
+      g_object_notify (object, "account");
+
+      if (self->account)
+        {
+          gchar *icon_name;
+
+          icon_name = g_strdup_printf ("goa-account-%s", goa_account_get_provider_type (self->account));
+
+          g_message ("Creating GOA storage: %s (%s)", goa_account_get_identity (self->account), 
goa_account_get_id (self->account));
+
+          gtd_storage_set_name (GTD_STORAGE (object), goa_account_get_identity (self->account));
+          gtd_storage_set_provider (GTD_STORAGE (object), goa_account_get_id (self->account));
+
+          g_set_object (&self->icon, g_themed_icon_new (icon_name));
+          g_object_notify (object, "icon");
+
+          g_free (icon_name);
+        }
+
+      break;
+
+    case PROP_PARENT:
+      gtd_storage_goa_set_parent (self, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_storage_goa_class_init (GtdStorageGoaClass *klass)
+{
+  GtdStorageClass *storage_class = GTD_STORAGE_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gtd_storage_goa_finalize;
+  object_class->get_property = gtd_storage_goa_get_property;
+  object_class->set_property = gtd_storage_goa_set_property;
+
+  storage_class->get_icon = gtd_storage_goa_get_icon;
+  storage_class->compare = gtd_storage_goa_compare;
+  storage_class->create_list = gtd_storage_goa_create_list;
+
+  /**
+   * GtdStorageGoa::account:
+   *
+   * The #GoaAccount of this storage.
+   */
+  g_object_class_install_property (
+        object_class,
+        PROP_ACCOUNT,
+        g_param_spec_object ("account",
+                             _("Account of the storage"),
+                             _("The account of the storage location."),
+                             GOA_TYPE_ACCOUNT,
+                             G_PARAM_READWRITE));
+
+  /**
+   * GtdStorageGoa::parent:
+   *
+   * The parent source of this storage.
+   */
+  g_object_class_install_property (
+        object_class,
+        PROP_PARENT,
+        g_param_spec_string ("parent",
+                             _("Parent of the storage"),
+                             _("The parent source identifier of the storage location."),
+                             NULL,
+                             G_PARAM_READWRITE));
+}
+
+static void
+gtd_storage_goa_init (GtdStorageGoa *self)
+{
+}
+
+GtdStorage*
+gtd_storage_goa_new (GoaAccount *account)
+{
+  GtdStorageGoa *self;
+  GtdStorage *storage;
+
+  storage =  g_object_new (GTD_TYPE_STORAGE_GOA,
+                           "account", account,
+                           NULL);
+  self = GTD_STORAGE_GOA (storage);
+
+  /*
+   * HACK: for any esoteric reason, gtd_storage_goa_set_property
+   * is not called when we set ::account property.
+   */
+  g_set_object (&self->account, account);
+  g_object_notify (G_OBJECT (self), "account");
+
+  if (self->account)
+    {
+      gchar *icon_name;
+
+      icon_name = g_strdup_printf ("goa-account-%s", goa_account_get_provider_type (self->account));
+
+      gtd_storage_set_name (storage, goa_account_get_identity (account));
+      gtd_storage_set_provider (storage, goa_account_get_provider_name (account));
+
+      g_set_object (&self->icon, g_themed_icon_new (icon_name));
+      g_object_notify (G_OBJECT (self), "icon");
+
+      g_free (icon_name);
+    }
+
+  return storage;
+}
+
+GoaAccount*
+gtd_storage_goa_get_account (GtdStorageGoa *goa_storage)
+{
+  g_return_val_if_fail (GTD_IS_STORAGE_GOA (goa_storage), NULL);
+
+  return goa_storage->account;
+}
+
+const gchar*
+gtd_storage_goa_get_parent (GtdStorageGoa *goa_storage)
+{
+  g_return_val_if_fail (GTD_IS_STORAGE_GOA (goa_storage), NULL);
+
+  return goa_storage->parent_source;
+}
+
+void
+gtd_storage_goa_set_parent (GtdStorageGoa *goa_storage,
+                            const gchar   *parent)
+{
+  g_return_if_fail (GTD_IS_STORAGE_GOA (goa_storage));
+
+  if (g_strcmp0 (goa_storage->parent_source, parent) != 0)
+    {
+      g_clear_pointer (&goa_storage->parent_source, g_free);
+
+      goa_storage->parent_source = g_strdup (parent);
+
+      g_object_notify (G_OBJECT (goa_storage), "parent");
+    }
+}
diff --git a/src/storage/gtd-storage-goa.h b/src/storage/gtd-storage-goa.h
new file mode 100644
index 0000000..b146b01
--- /dev/null
+++ b/src/storage/gtd-storage-goa.h
@@ -0,0 +1,45 @@
+/* gtd-storage-goa.h
+ *
+ * Copyright (C) 2015 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTD_STORAGE_GOA_H
+#define GTD_STORAGE_GOA_H
+
+#include "gtd-types.h"
+#include "gtd-storage.h"
+
+#include <glib.h>
+#include <goa/goa.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_STORAGE_GOA (gtd_storage_goa_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdStorageGoa, gtd_storage_goa, GTD, STORAGE_GOA, GtdStorage)
+
+GtdStorage*          gtd_storage_goa_new                         (GoaAccount         *account);
+
+GoaAccount*          gtd_storage_goa_get_account                 (GtdStorageGoa      *goa_storage);
+
+const gchar*         gtd_storage_goa_get_parent                  (GtdStorageGoa      *goa_storage);
+
+void                 gtd_storage_goa_set_parent                  (GtdStorageGoa      *goa_storage,
+                                                                  const gchar        *parent);
+
+G_END_DECLS
+
+#endif /* GTD_STORAGE_GOA_H */
diff --git a/src/storage/gtd-storage-local.c b/src/storage/gtd-storage-local.c
new file mode 100644
index 0000000..8ce984f
--- /dev/null
+++ b/src/storage/gtd-storage-local.c
@@ -0,0 +1,136 @@
+/* gtd-storage-local.c
+ *
+ * Copyright (C) 2015 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gtd-storage-local.h"
+#include "gtd-storage.h"
+#include "gtd-task-list.h"
+
+#include <glib/gi18n.h>
+
+struct _GtdStorageLocal
+{
+  GtdStorage          parent;
+
+  GIcon              *icon;
+};
+
+G_DEFINE_TYPE (GtdStorageLocal, gtd_storage_local, GTD_TYPE_STORAGE)
+
+enum {
+  PROP_0,
+  LAST_PROP
+};
+
+static GIcon*
+gtd_storage_local_get_icon (GtdStorage *storage)
+{
+  g_return_val_if_fail (GTD_IS_STORAGE_LOCAL (storage), NULL);
+
+  return GTD_STORAGE_LOCAL (storage)->icon;
+}
+
+static GtdTaskList*
+gtd_storage_local_create_list (GtdStorage  *storage,
+                               const gchar *name)
+{
+  ESourceExtension *extension;
+  GtdTaskList *task_list;
+  ESource *source;
+  GError *error;
+
+  g_return_val_if_fail (GTD_IS_STORAGE_LOCAL (storage), NULL);
+
+  error = NULL;
+
+  /* Create the source */
+  source = e_source_new (NULL,
+                         NULL,
+                         &error);
+
+  if (error)
+    {
+      g_warning ("%s: %s: %s",
+                 G_STRFUNC,
+                 _("Error creating new task list"),
+                 error->message);
+
+      g_clear_error (&error);
+      return NULL;
+    }
+
+  /* EDS properties */
+  e_source_set_display_name (source, name);
+
+  /* Make it a local source */
+  extension = e_source_get_extension (source, E_SOURCE_EXTENSION_TASK_LIST);
+
+  e_source_set_parent (source, "local-stub");
+  e_source_backend_set_backend_name (E_SOURCE_BACKEND (extension), "local");
+
+  /* Create task list */
+  task_list = gtd_task_list_new (source, _("On This Computer"));
+
+  return task_list;
+}
+
+static gint
+gtd_storage_local_compare (GtdStorage *a,
+                           GtdStorage *b)
+{
+  /* The local storage is always the first one */
+  return GTD_IS_STORAGE_LOCAL (a) - GTD_IS_STORAGE_LOCAL (b);
+}
+
+static void
+gtd_storage_local_finalize (GObject *object)
+{
+  GtdStorageLocal *self = GTD_STORAGE_LOCAL (object);
+
+  g_clear_object (&self->icon);
+
+  G_OBJECT_CLASS (gtd_storage_local_parent_class)->finalize (object);
+}
+
+static void
+gtd_storage_local_class_init (GtdStorageLocalClass *klass)
+{
+  GtdStorageClass *storage_class = GTD_STORAGE_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gtd_storage_local_finalize;
+
+  storage_class->get_icon = gtd_storage_local_get_icon;
+  storage_class->compare = gtd_storage_local_compare;
+  storage_class->create_list = gtd_storage_local_create_list;
+}
+
+static void
+gtd_storage_local_init (GtdStorageLocal *self)
+{
+  self->icon = G_ICON (g_themed_icon_new_with_default_fallbacks ("computer-symbolic"));
+}
+
+GtdStorage*
+gtd_storage_local_new (void)
+{
+  return g_object_new (GTD_TYPE_STORAGE_LOCAL,
+                       "id", "local",
+                       "name", _("Local"),
+                       "provider", _("On This Computer"),
+                       NULL);
+}
diff --git a/src/storage/gtd-storage-local.h b/src/storage/gtd-storage-local.h
new file mode 100644
index 0000000..a0efc7a
--- /dev/null
+++ b/src/storage/gtd-storage-local.h
@@ -0,0 +1,38 @@
+/* gtd-storage-local.h
+ *
+ * Copyright (C) 2015 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTD_STORAGE_LOCAL_H
+#define GTD_STORAGE_LOCAL_H
+
+#include "gtd-storage.h"
+#include "gtd-types.h"
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_STORAGE_LOCAL (gtd_storage_local_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdStorageLocal, gtd_storage_local, GTD, STORAGE_LOCAL, GtdStorage)
+
+GtdStorage*          gtd_storage_local_new                       (void);
+
+G_END_DECLS
+
+#endif /* GTD_STORAGE_LOCAL_H */
diff --git a/src/storage/gtd-storage-row.c b/src/storage/gtd-storage-row.c
index 598d38d..26a9498 100644
--- a/src/storage/gtd-storage-row.c
+++ b/src/storage/gtd-storage-row.c
@@ -103,7 +103,7 @@ gtd_storage_row_set_property (GObject      *object,
                               G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
 
       g_object_bind_property (self->priv->storage,
-                              "provider-name",
+                              "provider",
                               self->priv->provider,
                               "label",
                               G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
diff --git a/src/storage/gtd-storage-selector.c b/src/storage/gtd-storage-selector.c
index 62752b8..ac76a06 100644
--- a/src/storage/gtd-storage-selector.c
+++ b/src/storage/gtd-storage-selector.c
@@ -19,6 +19,7 @@
 #include "gtd-application.h"
 #include "gtd-manager.h"
 #include "gtd-storage.h"
+#include "gtd-storage-goa.h"
 #include "gtd-storage-row.h"
 #include "gtd-storage-selector.h"
 
@@ -824,12 +825,20 @@ gtd_storage_selector_set_show_stub_rows (GtdStorageSelector *selector,
               if (GTD_IS_STORAGE_ROW (l->data))
                 {
                   GtdStorage *storage = gtd_storage_row_get_storage (l->data);
+                  GoaAccount *account;
+                  const gchar *type;
 
-                  if (g_strcmp0 (gtd_storage_get_provider (storage), "google") == 0)
+                  if (!GTD_IS_STORAGE_GOA (storage))
+                    continue;
+
+                  account = gtd_storage_goa_get_account (GTD_STORAGE_GOA (storage));
+                  type = goa_account_get_provider_type (account);
+
+                  if (g_strcmp0 (type, "google") == 0)
                     google_counter++;
-                  else if (g_strcmp0 (gtd_storage_get_provider (storage), "exchange") == 0)
+                  else if (g_strcmp0 (type, "exchange") == 0)
                     exchange_counter++;
-                  else if (g_strcmp0 (gtd_storage_get_provider (storage), "owncloud") == 0)
+                  else if (g_strcmp0 (type, "owncloud") == 0)
                     owncloud_counter++;
                 }
             }
diff --git a/src/storage/gtd-storage.c b/src/storage/gtd-storage.c
index a3865c2..73c0810 100644
--- a/src/storage/gtd-storage.c
+++ b/src/storage/gtd-storage.c
@@ -23,26 +23,15 @@
 
 typedef struct
 {
-  GIcon                 *icon;
   gchar                 *id;
   gchar                 *name;
-  gchar                 *parent;
   gchar                 *provider;
-  gchar                 *provider_name;
 
   gint                   enabled : 1;
   gint                   is_default : 1;
 } GtdStoragePrivate;
 
-struct _GtdStorage
-{
-  GObject            parent;
-
-  /*<private>*/
-  GtdStoragePrivate *priv;
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE (GtdStorage, gtd_storage, G_TYPE_OBJECT)
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtdStorage, gtd_storage, G_TYPE_OBJECT)
 
 enum {
   PROP_0,
@@ -51,9 +40,7 @@ enum {
   PROP_ID,
   PROP_IS_DEFAULT,
   PROP_NAME,
-  PROP_PARENT,
   PROP_PROVIDER,
-  PROP_PROVIDER_NAME,
   LAST_PROP
 };
 
@@ -63,12 +50,9 @@ gtd_storage_finalize (GObject *object)
   GtdStorage *self = (GtdStorage *)object;
   GtdStoragePrivate *priv = gtd_storage_get_instance_private (self);
 
-  g_clear_object (&priv->icon);
   g_clear_pointer (&priv->id, g_free);
   g_clear_pointer (&priv->name, g_free);
-  g_clear_pointer (&priv->parent, g_free);
   g_clear_pointer (&priv->provider, g_free);
-  g_clear_pointer (&priv->provider_name, g_free);
 
   G_OBJECT_CLASS (gtd_storage_parent_class)->finalize (object);
 }
@@ -80,11 +64,12 @@ gtd_storage_get_property (GObject    *object,
                           GParamSpec *pspec)
 {
   GtdStorage *self = GTD_STORAGE (object);
+  GtdStoragePrivate *priv = gtd_storage_get_instance_private (self);
 
   switch (prop_id)
     {
     case PROP_ENABLED:
-      g_value_set_boolean (value, self->priv->enabled);
+      g_value_set_boolean (value, priv->enabled);
       break;
 
     case PROP_ICON:
@@ -92,27 +77,19 @@ gtd_storage_get_property (GObject    *object,
       break;
 
     case PROP_ID:
-      g_value_set_string (value, self->priv->id);
+      g_value_set_string (value, gtd_storage_get_id (self));
       break;
 
     case PROP_IS_DEFAULT:
-      g_value_set_boolean (value, self->priv->is_default);
+      g_value_set_boolean (value, priv->is_default);
       break;
 
     case PROP_NAME:
-      g_value_set_string (value, self->priv->name);
-      break;
-
-    case PROP_PARENT:
-      g_value_set_string (value, self->priv->parent);
+      g_value_set_string (value, gtd_storage_get_name (self));
       break;
 
     case PROP_PROVIDER:
-      g_value_set_string (value, self->priv->provider);
-      break;
-
-    case PROP_PROVIDER_NAME:
-      g_value_set_string (value, self->priv->provider_name);
+      g_value_set_string (value, gtd_storage_get_provider (self));
       break;
 
     default:
@@ -135,12 +112,7 @@ gtd_storage_set_property (GObject      *object,
       break;
 
     case PROP_ID:
-      if (self->priv->id)
-        g_free (self->priv->id);
-
-      self->priv->id = g_strdup (g_value_get_string (value));
-
-      g_object_notify (object, "id");
+      gtd_storage_set_id (self, g_value_get_string (value));
       break;
 
     case PROP_IS_DEFAULT:
@@ -151,18 +123,10 @@ gtd_storage_set_property (GObject      *object,
       gtd_storage_set_name (self, g_value_get_string (value));
       break;
 
-    case PROP_PARENT:
-      gtd_storage_set_parent (self, g_value_get_string (value));
-      break;
-
     case PROP_PROVIDER:
       gtd_storage_set_provider (self, g_value_get_string (value));
       break;
 
-    case PROP_PROVIDER_NAME:
-      gtd_storage_set_provider_name (self, g_value_get_string (value));
-      break;
-
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -217,7 +181,7 @@ gtd_storage_class_init (GtdStorageClass *klass)
                              _("Identifier of the storage"),
                              _("The unique identifier of the storage location."),
                              NULL,
-                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+                             G_PARAM_READWRITE));
 
   /**
    * GtdStorage::is-default:
@@ -248,44 +212,16 @@ gtd_storage_class_init (GtdStorageClass *klass)
                              G_PARAM_READWRITE));
 
   /**
-   * GtdStorage::parent:
-   *
-   * The parent source of this storage.
-   */
-  g_object_class_install_property (
-        object_class,
-        PROP_PARENT,
-        g_param_spec_string ("parent",
-                             _("Parent of the storage"),
-                             _("The parent source identifier of the storage location."),
-                             NULL,
-                             G_PARAM_READWRITE));
-
-  /**
    * GtdStorage::provider:
    *
-   * The provider of this storage.
+   * The user-visible provider name of this storage.
    */
   g_object_class_install_property (
         object_class,
         PROP_PROVIDER,
         g_param_spec_string ("provider",
-                             _("Provider type of the storage"),
-                             _("The provider type of the storage location."),
-                             NULL,
-                             G_PARAM_READWRITE));
-
-  /**
-   * GtdStorage::provider-name:
-   *
-   * The name of the provider of this storage.
-   */
-  g_object_class_install_property (
-        object_class,
-        PROP_PROVIDER_NAME,
-        g_param_spec_string ("provider-name",
-                             _("Provider name of the storage"),
-                             _("The name of the provider of the storage location."),
+                             _("Name of the data provider of the storage"),
+                             _("The user-visible name of the data provider of the storage location."),
                              NULL,
                              G_PARAM_READWRITE));
 }
@@ -293,30 +229,6 @@ gtd_storage_class_init (GtdStorageClass *klass)
 static void
 gtd_storage_init (GtdStorage *self)
 {
-  self->priv = gtd_storage_get_instance_private (self);
-}
-
-/**
- * gtd_storage_new:
- * @id: a %NULL-terminated string
- * @name: a %NULL-terminated string
- *
- * Creates a new #GtdStorage from the given @id.
- *
- * Returns: (transfer full): a new #GtdStorage
- */
-GtdStorage*
-gtd_storage_new (const gchar *id,
-                 const gchar *provider,
-                 const gchar *provider_name,
-                 const gchar *name)
-{
-  return g_object_new (GTD_TYPE_STORAGE,
-                       "id", id,
-                       "name", name,
-                       "provider", provider,
-                       "provider-name", provider_name,
-                       NULL);
 }
 
 /**
@@ -330,9 +242,13 @@ gtd_storage_new (const gchar *id,
 gboolean
 gtd_storage_get_enabled (GtdStorage *storage)
 {
+  GtdStoragePrivate *priv;
+
   g_return_val_if_fail (GTD_IS_STORAGE (storage), FALSE);
 
-  return storage->priv->enabled;
+  priv = gtd_storage_get_instance_private (storage);
+
+  return priv->enabled;
 }
 
 /**
@@ -348,12 +264,15 @@ void
 gtd_storage_set_enabled (GtdStorage *storage,
                          gboolean    enabled)
 {
+  GtdStoragePrivate *priv;
+
   g_return_if_fail (GTD_IS_STORAGE (storage));
 
-  if (storage->priv->enabled != enabled)
-    {
-      storage->priv->enabled = enabled;
+  priv = gtd_storage_get_instance_private (storage);
 
+  if (priv->enabled != enabled)
+    {
+      priv->enabled = enabled;
       g_object_notify (G_OBJECT (storage), "enabled");
     }
 }
@@ -371,9 +290,9 @@ gtd_storage_set_enabled (GtdStorage *storage,
 GIcon*
 gtd_storage_get_icon (GtdStorage *storage)
 {
-  g_return_val_if_fail (GTD_IS_STORAGE (storage), NULL);
+  g_return_val_if_fail (GTD_STORAGE_CLASS (G_OBJECT_GET_CLASS (storage))->get_icon, NULL);
 
-  return storage->priv->icon;
+  return GTD_STORAGE_CLASS (G_OBJECT_GET_CLASS (storage))->get_icon (storage);
 }
 
 /**
@@ -387,9 +306,42 @@ gtd_storage_get_icon (GtdStorage *storage)
 const gchar*
 gtd_storage_get_id (GtdStorage *storage)
 {
-  g_return_val_if_fail (GTD_IS_STORAGE (storage), NULL);
+  GtdStoragePrivate *priv;
+
+  g_return_val_if_fail (GTD_IS_STORAGE (storage), FALSE);
+
+  priv = gtd_storage_get_instance_private (storage);
+
+  return priv->id;
+}
+
+/**
+ * gtd_storage_set_id:
+ * @storage: a #GtdStorage
+ * @id: the id of @storage
+ *
+ * Sets the unique identifier of @storage.
+ *
+ * Returns:
+ */
+void
+gtd_storage_set_id (GtdStorage  *storage,
+                    const gchar *id)
+{
+  GtdStoragePrivate *priv;
+
+  g_return_if_fail (GTD_IS_STORAGE (storage));
+
+  priv = gtd_storage_get_instance_private (storage);
+
+  if (g_strcmp0 (priv->id, id) != 0)
+    {
+      g_clear_pointer (&priv->id, g_free);
 
-  return storage->priv->id;
+      priv->id = g_strdup (id);
+
+      g_object_notify (G_OBJECT (storage), "id");
+    }
 }
 
 /**
@@ -403,9 +355,13 @@ gtd_storage_get_id (GtdStorage *storage)
 gboolean
 gtd_storage_get_is_default (GtdStorage *storage)
 {
+  GtdStoragePrivate *priv;
+
   g_return_val_if_fail (GTD_IS_STORAGE (storage), FALSE);
 
-  return storage->priv->is_default;
+  priv = gtd_storage_get_instance_private (storage);
+
+  return priv->is_default;
 }
 
 /**
@@ -425,7 +381,7 @@ gtd_storage_set_is_default (GtdStorage *storage,
 
   g_return_if_fail (GTD_IS_STORAGE (storage));
 
-  priv = storage->priv;
+  priv = gtd_storage_get_instance_private (storage);
 
   if (priv->is_default != is_default)
     {
@@ -446,9 +402,13 @@ gtd_storage_set_is_default (GtdStorage *storage,
 const gchar*
 gtd_storage_get_name (GtdStorage *storage)
 {
+  GtdStoragePrivate *priv;
+
   g_return_val_if_fail (GTD_IS_STORAGE (storage), NULL);
 
-  return storage->priv->name;
+  priv = gtd_storage_get_instance_private (storage);
+
+  return priv->name;
 }
 
 /**
@@ -467,7 +427,7 @@ gtd_storage_set_name (GtdStorage  *storage,
 
   g_return_if_fail (GTD_IS_STORAGE (storage));
 
-  priv = storage->priv;
+  priv = gtd_storage_get_instance_private (storage);
 
   if (g_strcmp0 (priv->name, name) != 0)
     {
@@ -480,62 +440,23 @@ gtd_storage_set_name (GtdStorage  *storage,
 }
 
 /**
- * gtd_storage_get_parent:
- * @storage: a #GtdStorage
- *
- * Retrieves the parent source identifier of @storage.
- *
- * Returns: (transfer none): the parent uid of @storage, or %NULL if none is set.
- */
-const gchar*
-gtd_storage_get_parent (GtdStorage *storage)
-{
-  g_return_val_if_fail (GTD_IS_STORAGE (storage), NULL);
-
-  return storage->priv->parent;
-}
-
-/**
- * gtd_storage_set_parent:
- *
- * Sets the #GtdStorage::parent property of @storage.
- *
- * Returns:
- */
-void
-gtd_storage_set_parent (GtdStorage  *storage,
-                        const gchar *parent)
-{
-  GtdStoragePrivate *priv;
-
-  g_return_if_fail (GTD_IS_STORAGE (storage));
-
-  priv = storage->priv;
-
-  if (g_strcmp0 (priv->parent, parent) != 0)
-    {
-      g_clear_pointer (&priv->parent, g_free);
-
-      priv->parent = g_strdup (parent);
-
-      g_object_notify (G_OBJECT (storage), "parent");
-    }
-}
-
-/**
  * gtd_storage_get_provider:
  * @storage: a #GtdStorage
  *
- * Retrieves the storage provider of @storage.
+ * Retrieves the user-visible name of @storage's provider
  *
- * Returns: (transfer none): retrieves the storage provider of @storage.
+ * Returns: (transfer none): the user-visible name of @storage's provider.
  */
 const gchar*
 gtd_storage_get_provider (GtdStorage *storage)
 {
+  GtdStoragePrivate *priv;
+
   g_return_val_if_fail (GTD_IS_STORAGE (storage), NULL);
 
-  return storage->priv->provider;
+  priv = gtd_storage_get_instance_private (storage);
+
+  return priv->provider;
 }
 
 /**
@@ -556,76 +477,19 @@ gtd_storage_set_provider (GtdStorage  *storage,
 
   g_return_if_fail (GTD_IS_STORAGE (storage));
 
-  priv = storage->priv;
+  priv = gtd_storage_get_instance_private (storage);
 
   if (g_strcmp0 (priv->provider, provider) != 0)
     {
       g_clear_pointer (&priv->provider, g_free);
-      g_clear_object (&priv->icon);
 
       priv->provider = g_strdup (provider);
 
-      if (g_strcmp0 (provider, "local") == 0)
-        {
-          priv->icon = G_ICON (g_themed_icon_new ("computer-symbolic"));
-        }
-      else
-        {
-          gchar *icon_name;
-
-          icon_name = g_strdup_printf ("goa-account-%s", provider);
-
-          priv->icon = G_ICON (g_themed_icon_new (icon_name));
-
-          g_free (icon_name);
-        }
-
       g_object_notify (G_OBJECT (storage), "provider");
     }
 }
 
 /**
- * gtd_storage_get_provider_name:
- * @storage: a #GtdStorage
- *
- * Retrieves the provider name of @storage.
- *
- * Returns: (transfer none): the provider name of @storage.
- */
-const gchar*
-gtd_storage_get_provider_name (GtdStorage *storage)
-{
-  g_return_val_if_fail (GTD_IS_STORAGE (storage), NULL);
-
-  return storage->priv->provider_name;
-}
-
-/**
- * gtd_storage_set_provider_name:
- * @storage: a #GtdStorage
- * @provider_name: the name of the provider.
- *
- * Sets the #GtdStorage::provider-name property.
- *
- * Returns:
- */
-void
-gtd_storage_set_provider_name (GtdStorage  *storage,
-                               const gchar *provider_name)
-{
-  g_return_if_fail (GTD_IS_STORAGE (storage));
-
-  if (g_strcmp0 (storage->priv->provider_name, provider_name) != 0)
-    {
-      g_clear_pointer (&storage->priv->provider_name, g_free);
-
-      storage->priv->provider_name = g_strdup (provider_name);
-
-      g_object_notify (G_OBJECT (storage), "provider-name");
-    }
-}
-
-/**
  * gtd_storage_compare:
  * @a: a #GtdStorage
  * @b: a #GtdStorage
@@ -643,71 +507,22 @@ gtd_storage_compare (GtdStorage *a,
   g_return_val_if_fail (GTD_IS_STORAGE (a), 0);
   g_return_val_if_fail (GTD_IS_STORAGE (b), 0);
 
-  /* Compare by providers first */
-  retval = g_strcmp0 (gtd_storage_get_provider (b), gtd_storage_get_provider (a));
+  /* Let subclasses decide */
+  retval = GTD_STORAGE_CLASS (G_OBJECT_GET_CLASS (a))->compare (a, b);
 
   if (retval != 0)
-    return -1 * retval;
+    return retval;
 
-  /* Then, by identifiers */
-  retval = g_strcmp0 (gtd_storage_get_id (b), gtd_storage_get_id (a));
+  retval = GTD_STORAGE_CLASS (G_OBJECT_GET_CLASS (b))->compare (a, b);
 
-  return -1 * retval;
+  return retval;
 }
 
 GtdTaskList*
 gtd_storage_create_task_list (GtdStorage  *storage,
                               const gchar *name)
 {
-  GtdStoragePrivate *priv;
-  ESourceExtension *extension;
-  GtdTaskList *task_list;
-  ESource *source;
-  GError *error;
-
-  g_return_val_if_fail (GTD_IS_STORAGE (storage), NULL);
-
-  priv = storage->priv;
-  error = NULL;
-  source = e_source_new (NULL,
-                         NULL,
-                         &error);
-
-  if (error)
-    {
-      g_warning ("%s: %s: %s",
-                 G_STRFUNC,
-                 _("Error creating new task list"),
-                 error->message);
-
-      g_clear_error (&error);
-      return NULL;
-    }
-
-  /* Some properties */
-  e_source_set_display_name (source, name);
-
-  /*
-   * The only special case is "local" provider, which is treated
-   * differently here.
-   */
-  if (g_strcmp0 (priv->provider, "local") == 0)
-    {
-      extension = e_source_get_extension (source, E_SOURCE_EXTENSION_TASK_LIST);
-
-      e_source_set_parent (source, "local-stub");
-      e_source_backend_set_backend_name (E_SOURCE_BACKEND (extension), "local");
-    }
-  else
-    {
-      /* TODO: create source for GOA account */
-      extension = e_source_get_extension (source, E_SOURCE_EXTENSION_TASK_LIST);
-
-      e_source_set_parent (source, priv->parent);
-    }
-
-  /* Create task list */
-  task_list = gtd_task_list_new (source, priv->name);
+  g_return_val_if_fail (GTD_STORAGE_CLASS (G_OBJECT_GET_CLASS (storage))->create_list, NULL);
 
-  return task_list;
+  return GTD_STORAGE_CLASS (G_OBJECT_GET_CLASS (storage))->create_list (storage, name);
 }
diff --git a/src/storage/gtd-storage.h b/src/storage/gtd-storage.h
index 8015fbf..61d12c6 100644
--- a/src/storage/gtd-storage.h
+++ b/src/storage/gtd-storage.h
@@ -28,13 +28,25 @@ G_BEGIN_DECLS
 
 #define GTD_TYPE_STORAGE (gtd_storage_get_type())
 
-G_DECLARE_FINAL_TYPE (GtdStorage, gtd_storage, GTD, STORAGE, GObject)
+G_DECLARE_DERIVABLE_TYPE (GtdStorage, gtd_storage, GTD, STORAGE, GObject)
 
-GtdStorage*        gtd_storage_new                               (const gchar        *id,
-                                                                  const gchar        *provider,
-                                                                  const gchar        *provider_name,
+struct _GtdStorageClass
+{
+  GObject            parent;
+
+  /* Abstract methods */
+  GIcon*             (*get_icon)                                 (GtdStorage         *storage);
+
+  gint               (*compare)                                  (GtdStorage         *a,
+                                                                  GtdStorage         *b);
+
+  GtdTaskList*       (*create_list)                              (GtdStorage         *storage,
                                                                   const gchar        *name);
 
+  /* Padding for future expansions */
+  gpointer           padding[12];
+};
+
 gboolean           gtd_storage_get_enabled                       (GtdStorage         *storage);
 
 void               gtd_storage_set_enabled                       (GtdStorage         *storage,
@@ -44,6 +56,9 @@ GIcon*             gtd_storage_get_icon                          (GtdStorage
 
 const gchar*       gtd_storage_get_id                            (GtdStorage         *storage);
 
+void               gtd_storage_set_id                            (GtdStorage         *storage,
+                                                                  const gchar        *id);
+
 gboolean           gtd_storage_get_is_default                    (GtdStorage         *storage);
 
 void               gtd_storage_set_is_default                    (GtdStorage         *storage,
@@ -54,20 +69,10 @@ const gchar*       gtd_storage_get_name                          (GtdStorage
 void               gtd_storage_set_name                          (GtdStorage         *storage,
                                                                   const gchar        *name);
 
-const gchar*       gtd_storage_get_parent                        (GtdStorage         *storage);
-
-void               gtd_storage_set_parent                        (GtdStorage         *storage,
-                                                                  const gchar        *url);
-
 const gchar*       gtd_storage_get_provider                      (GtdStorage         *storage);
 
 void               gtd_storage_set_provider                      (GtdStorage         *storage,
-                                                                  const gchar        *provider);
-
-const gchar*       gtd_storage_get_provider_name                 (GtdStorage         *storage);
-
-void               gtd_storage_set_provider_name                 (GtdStorage         *storage,
-                                                                  const gchar        *provider_name);
+                                                                  const gchar        *name);
 
 gint               gtd_storage_compare                           (GtdStorage         *a,
                                                                   GtdStorage         *b);



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