[gnome-todo/wip/gbsneto/plugins] eds: stub out eds plugins
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-todo/wip/gbsneto/plugins] eds: stub out eds plugins
- Date: Thu, 24 Dec 2015 02:21:11 +0000 (UTC)
commit f12442296c7b53dc247633a06e4984f07e75ae1b
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Thu Dec 24 00:20:20 2015 -0200
eds: stub out eds plugins
WARNING: this is non-compilable code
Makefile.am | 6 +-
common.am | 8 +
configure.ac | 9 +
plugins/Makefile.am | 3 +
plugins/eds/Makefile.am | 46 ++
plugins/eds/edit-pane.ui | 274 +++++++++++
plugins/eds/eds.gresource.xml | 6 +
plugins/eds/eds.plugin.in | 13 +
plugins/eds/gtd-plugin-eds.c | 343 ++++++++++++++
plugins/eds/gtd-plugin-eds.h | 35 ++
plugins/eds/gtd-provider-eds.c | 958 ++++++++++++++++++++++++++++++++++++++
plugins/eds/gtd-provider-eds.h | 67 +++
plugins/eds/gtd-provider-local.c | 239 ++++++++++
plugins/eds/gtd-provider-local.h | 40 ++
plugins/eds/gtd-task-list-eds.c | 139 ++++++
plugins/eds/gtd-task-list-eds.h | 42 ++
src/gtd-manager.c | 151 ++-----
17 files changed, 2254 insertions(+), 125 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 6bd056d..9851c4b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,9 @@
+include $(top_srcdir)/common.am
+
ACLOCAL_AMFLAGS = --install -I m4 ${ACLOCAL_FLAGS}
-SUBDIRS = src data po
-DIST_SUBDIRS = src data po
+SUBDIRS = src data plugins po
+DIST_SUBDIRS = src data plugins po
INTLTOOL_FILES = \
intltool-extract.in \
diff --git a/common.am b/common.am
new file mode 100644
index 0000000..ce557d1
--- /dev/null
+++ b/common.am
@@ -0,0 +1,8 @@
+plugindir = @GNOME_TODO_PLUGIN_DIR@
+
+GNOME_TODO_PLUGIN_CFLAGS = \
+ $(GNOME_TODO_CFLAGS)
+
+
+GNOME_TODO_PLUGIN_WARN_CFLAGS = \
+ $(GNOME_TODO_WARN_CFLAGS)
diff --git a/configure.ac b/configure.ac
index ce570cb..c9a5e7f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,12 +74,21 @@ PKG_CHECK_MODULES(GNOME_TODO,
APPSTREAM_XML
+
+dnl ================================================================
+dnl Plugins
+dnl ================================================================
+GNOME_TODO_ADD_PLUGIN([eds], [Evolution-Data-Server], [yes])
+
+AC_SUBST([GNOME_TODO_PLUGIN_DIR], [${libdir}])
+
AC_CONFIG_FILES([
Makefile
src/Makefile
data/Makefile
data/icons/Makefile
data/org.gnome.Todo.desktop.in
+ plugins/Makefile
po/Makefile.in
])
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
new file mode 100644
index 0000000..da699ff
--- /dev/null
+++ b/plugins/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = eds
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/plugins/eds/Makefile.am b/plugins/eds/Makefile.am
new file mode 100644
index 0000000..5310323
--- /dev/null
+++ b/plugins/eds/Makefile.am
@@ -0,0 +1,46 @@
+include $(top_srcdir)/common.am
+
+plugindir = $(datadir)/gnome-todo/plugins
+
+plugin_LTLIBRARIES = libeds.la
+plugin_DATA = eds.plugin
+
+BUILT_SOURCES = \
+ gtd-plugin-eds-resources.c
+
+libeds_la_SOURCES = \
+ gtd-plugin-eds.c \
+ gtd-plugin-eds.h \
+ gtd-provider-eds.c \
+ gtd-provider-eds.h \
+ gtd-provider-goa.c \
+ gtd-provider-goa.h \
+ gtd-provider-local.c \
+ gtd-provider-local.h \
+ gtd-task-list-eds.c \
+ gtd-task-list-eds.h \
+ $(BUILT_SOURCES)
+
+libeds_la_CFLAGS = \
+ $(GNOME_TODO_PLUGIN_CFLAGS) \
+ $(GNOME_TODO_PLUGIN_WARN_CFLAGS) \
+ -DGOA_API_IS_SUBJECT_TO_CHANGE \
+ -DG_LOG_DOMAIN='"EDS"'
+
+libeds_la_LIBADD = \
+ $(GNOME_TODO_LIBS)
+
+libeds_la_LDFLAGS = \
+ -Wl -module \
+ $(GNOME_TODO_WARN_LDFLAGS)
+
+# generate binary-bundle resources
+resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies \
+ --sourcedir=$(top_srcdir)/plugins/eds $(top_srcdir)/plugins/eds/eds.gresource.xml)
+
+gtd-plugin-eds-resources.c: eds.gresource.xml $(resource_files)
+ $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(top_srcdir)/plugins/eds
--generate-source $<
+
+
+
+EXTRA_DIST = eds.plugin.in
diff --git a/plugins/eds/edit-pane.ui b/plugins/eds/edit-pane.ui
new file mode 100644
index 0000000..50f039b
--- /dev/null
+++ b/plugins/eds/edit-pane.ui
@@ -0,0 +1,274 @@
+<interface>
+ <object class="GtkGrid" id="eds_edit_grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">12</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkButton" id="close_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <property name="relief">none</property>
+ <signal name="clicked" handler="gtd_edit_pane__close_button_clicked" object="GtdEditPane"
swapped="no"/>
+ <child>
+ <object class="GtkImage" id="close_button_image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">window-close-symbolic</property>
+ </object>
+ </child>
+ <style>
+ <class name="image-button"/>
+ <class name="flat"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="details_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">12</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Details</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator" id="separator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">12</property>
+ <property name="row_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="notes_dim_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Notes</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="notes_scrolled_window">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <property name="min_content_width">325</property>
+ <property name="min_content_height">225</property>
+ <child>
+ <object class="GtkTextView" id="notes_textview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="accepts_tab">False</property>
+ <property name="left-margin">6</property>
+ <property name="right-margin">6</property>
+ <property name="pixels-above-lines">6</property>
+ <property name="wrap-mode">word-char</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="due_date_dim_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Due Date</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="date_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="popover">date_popover</property>
+ <child>
+ <object class="GtkBox" id="date_button_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="date_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="date_button_image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">pan-down-symbolic</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="priority_dim_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Priority</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="priority_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="active">0</property>
+ <items>
+ <item translatable="yes" context="taskpriority">None</item>
+ <item translatable="yes">Low</item>
+ <item translatable="yes">Medium</item>
+ <item translatable="yes">High</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="remove_button">
+ <property name="label" translatable="yes">Delete</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">end</property>
+ <property name="vexpand">True</property>
+ <signal name="clicked" handler="gtd_edit_pane__delete_button_clicked" object="GtdEditPane"
swapped="no" />
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkPopover" id="date_popover">
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="position">bottom</property>
+ <child>
+ <object class="GtkBox" id="date_popover_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkCalendar" id="calendar">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="show_week_numbers">True</property>
+ <signal name="day-selected" handler="gtd_edit_pane__date_selected" object="GtdEditPane"
swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="no_date_button">
+ <property name="label" translatable="yes" context="taskdate">None</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <signal name="clicked" handler="gtd_edit_pane__no_date_button_clicked" object="GtdEditPane"
swapped="no" />
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/plugins/eds/eds.gresource.xml b/plugins/eds/eds.gresource.xml
new file mode 100644
index 0000000..5cc98dd
--- /dev/null
+++ b/plugins/eds/eds.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/todo">
+ <file compressed="true" alias="ui/eds/edit-pane.ui">edit-pane.ui</file>
+ </gresource>
+</gresources>
diff --git a/plugins/eds/eds.plugin.in b/plugins/eds/eds.plugin.in
new file mode 100644
index 0000000..3861a59
--- /dev/null
+++ b/plugins/eds/eds.plugin.in
@@ -0,0 +1,13 @@
+[Plugin]
+Name = Core
+Module = eds
+Description = Evolution-data-server plugin for GNOME To Do
+Version = @VERSION@
+Authors = Georges Basile Stavracas Neto <gbsneto gnome org>
+Copyright = Copyleft © The To Do maintainers
+Website = https://wiki.gnome.org/Apps/Todo
+Builin = true
+Hidden = true
+License = GPL
+Loader = C
+Depends =
diff --git a/plugins/eds/gtd-plugin-eds.c b/plugins/eds/gtd-plugin-eds.c
new file mode 100644
index 0000000..fd92484
--- /dev/null
+++ b/plugins/eds/gtd-plugin-eds.c
@@ -0,0 +1,343 @@
+/* gtd-plugin-eds.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-plugin-eds.h"
+#include "gtd-provider-local.h"
+
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gnome-todo/gnome-todo.h>
+
+/**
+ * The #GtdPluginEds is a class that loads all the
+ * essential providers of GNOME To Do.
+ *
+ * It basically loads #ESourceRegistry which provides
+ * #GtdProviderLocal. Immediately after that, it loads
+ * #GoaClient which provides one #GtdProviderGoa per
+ * supported account.
+ *
+ * The currently supported Online Accounts are Google,
+ * ownCloud and Microsoft Exchange ones.
+ */
+
+struct _GtdPluginEds
+{
+ PeasExtensionBaseClass parent;
+
+ /* Providers */
+ GList *providers;
+};
+
+enum
+{
+ PROP_0,
+ PROP_OBJECT,
+ PROP_PROVIDERS,
+ LAST_PROP
+};
+
+const gchar *supported_accounts[] = {
+ "exchange",
+ "google",
+ "owncloud",
+ NULL
+};
+
+static void gtd_activatable_iface_init (GtdActivatableInterface *iface);
+
+static void peas_activatable_iface_init (PeasActivatableInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GtdPluginEds, gtd_plugin_eds, PEAS_TYPE_EXTENSION_BASE,
+ 0,
+ G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_TYPE_ACTIVATABLE,
+ peas_activatable_iface_init)
+ G_IMPLEMENT_INTERFACE_DYNAMIC (GTD_TYPE_ACTIVATABLE,
+ gtd_activatable_iface_init))
+
+/*
+ * PeasActivatable interface implementation
+ */
+static void
+gtd_plugin_eds_activate (PeasActivatable *activatable)
+{
+ g_message ("activate");
+}
+
+static void
+gtd_plugin_eds_deactivate (PeasActivatable *activatable)
+{
+ g_message ("deactivate");
+}
+
+static void
+peas_activatable_iface_init (PeasActivatableInterface *iface)
+{
+ iface->activate = gtd_plugin_eds_activate;
+ iface->deactivate = gtd_plugin_eds_deactivate;
+}
+
+/*
+ * GtdActivatable interface implementation
+ */
+static GList*
+gtd_plugin_eds_get_providers (GtdActivatable *activatable)
+{
+ GtdPluginEds *plugin = GTD_PLUGIN_EDS (activatable);
+
+ return plugin->providers;
+}
+
+static void
+gtd_activatable_iface_init (GtdActivatableInterface *iface)
+{
+ iface->get_providers = gtd_plugin_eds_get_providers;
+}
+
+
+/*
+ * Init
+ */
+
+static void
+gtd_plugin_eds_goa_client_finish_cb (GObject *client,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GtdPluginEds *self;
+ GoaClient *goa_client;
+ GError *error;
+
+ self = GTD_PLUGIN_EDS (user_data);
+ error = NULL;
+
+ goa_client = goa_client_new_finish (result, &error);
+
+ if (!error)
+ {
+ GList *accounts;
+ GList *l;
+ gchar *default_location;
+
+ /* Load each supported GoaAccount into a GtdStorage */
+ accounts = goa_client_get_accounts (goa_client);
+ default_location = g_settings_get_string (priv->settings, "storage-location");
+
+ for (l = accounts; l != NULL; l = l->next)
+ {
+ GoaObject *object;
+ GoaAccount *account;
+
+ object = l->data;
+ account = goa_object_peek_account (object);
+
+ if (g_strv_contains (supported_accounts, goa_account_get_provider_type (account)))
+ {
+ GtdStorage *storage;
+
+ /* Create the new GOA storage */
+ storage = gtd_storage_goa_new (object);
+ 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);
+
+ 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,
+ (GCompareFunc) gtd_storage_compare);
+
+ g_signal_emit (user_data, signals[STORAGE_ADDED], 0, storage);
+ }
+ }
+
+ /* Connect GoaClient signals */
+ g_signal_connect (priv->goa_client,
+ "account-added",
+ G_CALLBACK (gtd_manager__goa_account_added_cb),
+ user_data);
+
+ g_signal_connect (priv->goa_client,
+ "account-changed",
+ G_CALLBACK (gtd_manager__goa_account_changed_cb),
+ user_data);
+
+ g_signal_connect (priv->goa_client,
+ "account-removed",
+ G_CALLBACK (gtd_manager__goa_account_removed_cb),
+ user_data);
+
+ g_list_free_full (accounts, g_object_unref);
+ g_free (default_location);
+ }
+ else
+ {
+ g_warning ("%s: %s: %s",
+ G_STRFUNC,
+ _("Error loading GNOME Online Accounts"),
+ error->message);
+
+ emit_show_error_message (GTD_MANAGER (user_data),
+ _("Error loading GNOME Online Accounts"),
+ error->message);
+
+ g_clear_error (&error);
+ }
+
+ g_object_notify (user_data, "goa-client-ready");
+ g_object_notify (user_data, "goa-client");
+}
+
+
+
+static void
+gtd_plugin_eds_source_registry_finish_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GtdPluginEds *self = GTD_PLUGIN_EDS (user_data);
+ GtdProviderLocal *provider;
+ ESourceRegistry *registry;
+ GError *error = NULL;
+
+ registry = e_source_registry_new_finish (result, &error);
+
+ /* Abort on error */
+ if (error)
+ {
+ g_warning ("%s: %s",
+ _("Error loading Evolution-Data-Server backend"),
+ error->message);
+
+ g_clear_error (&error);
+ return;
+ }
+
+ /* Load the local provider */
+ provider = gtd_provider_local_new (registry);
+ g_signal_emit_by_name (self, "provider-added", provider);
+
+ self->providers = g_list_append (self->providers, provider);
+
+ g_object_notify (G_OBJECT (self), "providers");
+
+ /* We only start loading Goa accounts after
+ * ESourceRegistry is get, since it'd be way
+ * too hard to synchronize these two asynchronous
+ * calls.
+ */
+ /* online accounts */
+ goa_client_new (NULL,
+ (GAsyncReadyCallback) gtd_plugin_eds_goa_client_finish_cb,
+ self);
+}
+
+static void
+gtd_plugin_eds_finalize (GObject *object)
+{
+ GtdPluginEds *self = (GtdPluginEds *)object;
+
+ g_list_free_full (self->providers, g_object_unref);
+
+ G_OBJECT_CLASS (gtd_plugin_eds_parent_class)->finalize (object);
+}
+
+static void
+gtd_plugin_eds_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtdPluginEds *self = GTD_PLUGIN_EDS (object);
+
+ switch (prop_id)
+ {
+ case PROP_OBJECT:
+ g_value_set_object (value, NULL);
+ break;
+
+ case PROP_PROVIDERS:
+ g_value_set_pointer (value, self->providers);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtd_plugin_eds_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_OBJECT:
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtd_plugin_eds_class_init (GtdPluginEdsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtd_plugin_eds_finalize;
+ object_class->get_property = gtd_plugin_eds_get_property;
+ object_class->set_property = gtd_plugin_eds_set_property;
+
+ g_object_class_override_property (object_class,
+ PROP_OBJECT,
+ "object");
+
+ g_object_class_override_property (object_class,
+ PROP_PROVIDERS,
+ "providers");
+}
+
+static void
+gtd_plugin_eds_init (GtdPluginEds *self)
+{
+ g_message ("%s", G_STRFUNC);
+
+ /* load the source registry */
+ e_source_registry_new (NULL,
+ (GAsyncReadyCallback) gtd_plugin_eds_source_registry_finish_cb,
+ self);
+}
+
+/* Empty class_finalize method */
+static void
+gtd_plugin_eds_class_finalize (GtdPluginEdsClass *klass)
+{
+}
+
+G_MODULE_EXPORT void
+peas_register_types (PeasObjectModule *module)
+{
+ gtd_plugin_eds_register_type (G_TYPE_MODULE (module));
+
+ peas_object_module_register_extension_type (module,
+ GTD_TYPE_ACTIVATABLE,
+ GTD_TYPE_PLUGIN_EDS);
+}
diff --git a/plugins/eds/gtd-plugin-eds.h b/plugins/eds/gtd-plugin-eds.h
new file mode 100644
index 0000000..24ef1d0
--- /dev/null
+++ b/plugins/eds/gtd-plugin-eds.h
@@ -0,0 +1,35 @@
+/* gtd-eds-plugin.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_EDS_PLUGIN_H
+#define GTD_EDS_PLUGIN_H
+
+#include <glib.h>
+#include <gnome-todo/gtd-activatable.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_PLUGIN_EDS (gtd_plugin_eds_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdPluginEds, gtd_plugin_eds, GTD, PLUGIN_EDS, PeasExtensionBase)
+
+G_MODULE_EXPORT void peas_register_types (PeasObjectModule *module);
+
+G_END_DECLS
+
+#endif /* GTD_EDS_PLUGIN_H */
diff --git a/plugins/eds/gtd-provider-eds.c b/plugins/eds/gtd-provider-eds.c
new file mode 100644
index 0000000..5331b80
--- /dev/null
+++ b/plugins/eds/gtd-provider-eds.c
@@ -0,0 +1,958 @@
+/* gtd-provider-eds.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-provider-eds.h"
+
+#include <glib/gi18n.h>
+
+/**
+ * #GtdProviderEds is the base class of #GtdProviderLocal
+ * and #GtdProviderGoa. It provides the common functionality
+ * shared between these two providers.
+ *
+ * The subclasses basically have to implement GtdProviderEds->should_load_source
+ * which decides whether a given #ESource should be loaded (and added to the
+ * sources list) or not. #GtdProviderLocal for example would filter out
+ * sources whose backend is not "local".
+ */
+
+typedef struct
+{
+ GList *task_lists;
+
+ ESourceRegistry *source_registry;
+ ECredentialsPrompter *credentials_prompter;
+
+ GHashTable *clients;
+ gint loaded_sources;
+} GtdProviderEdsPrivate;
+
+/* Auxiliary struct for asyncronous task operations */
+typedef struct _TaskData
+{
+ GtdProviderEds *provider;
+ gpointer *data;
+} TaskData;
+
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtdProviderEds, gtd_provider_eds, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_REGISTRY,
+ N_PROPS
+};
+
+static TaskData*
+task_data_new (GtdProviderEds *provider,
+ gpointer *data)
+{
+ TaskData *tdata;
+
+ tdata = g_new0 (TaskData, 1);
+ tdata->provider = provider;
+ tdata->data = data;
+
+ return tdata;
+}
+
+
+static void
+gtd_provider_eds_fill_task_list (GObject *client,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GtdTaskList *list;
+ TaskData *data = user_data;
+ GSList *component_list;
+ GError *error = NULL;
+
+ g_return_if_fail (GTD_IS_PROVIDER_EDS (data->provider));
+
+ list = GTD_TASK_LIST (data->data);
+
+ e_cal_client_get_object_list_as_comps_finish (E_CAL_CLIENT (client),
+ result,
+ &component_list,
+ &error);
+
+ gtd_object_set_ready (GTD_OBJECT (data->data), TRUE);
+ g_free (data);
+
+ if (!error)
+ {
+ GSList *l;
+
+ for (l = component_list; l != NULL; l = l->next)
+ {
+ GtdTask *task;
+
+ task = gtd_task_new (l->data);
+ gtd_task_set_list (task, list);
+
+ gtd_task_list_save_task (list, task);
+ }
+
+ e_cal_client_free_ecalcomp_slist (component_list);
+ }
+ else
+ {
+ g_warning ("%s: %s: %s",
+ G_STRFUNC,
+ _("Error fetching tasks from list"),
+ error->message);
+/*
+ emit_show_error_message (GTD_MANAGER (user_data),
+ _("Error fetching tasks from list"),
+ error->message);
+*/
+ g_error_free (error);
+ return;
+ }
+}
+
+static void
+gtd_provider_eds_on_client_connected (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GtdProviderEdsPrivate *priv;
+ GtdProviderEds *self;
+ ECalClient *client;
+ ESource *source;
+ GError *error = NULL;
+
+ self = GTD_PROVIDER_EDS (user_data);
+ priv = gtd_provider_eds_get_instance_private (self);
+ source = e_client_get_source (E_CLIENT (source_object));
+ client = E_CAL_CLIENT (e_cal_client_connect_finish (result, &error));
+
+ /* Update ready flag */
+ priv->loaded_sources--;
+ gtd_object_set_ready (GTD_OBJECT (user_data), priv->loaded_sources <= 0);
+
+ if (!error)
+ {
+ GtdTaskList *list;
+ TaskData *data;
+ ESource *parent;
+
+ /* parent source's display name is list's origin */
+ parent = e_source_registry_ref_source (priv->source_registry, e_source_get_parent (source));
+
+ /* creates a new task list */
+ list = gtd_task_list_new (source, e_source_get_display_name (parent));
+
+ /* it's not ready until we fetch the list of tasks from client */
+ gtd_object_set_ready (GTD_OBJECT (list), FALSE);
+
+ /* async data */
+ data = task_data_new (user_data, (gpointer) list);
+
+ /* asyncronously fetch the task list */
+ e_cal_client_get_object_list_as_comps (client,
+ "contains? \"any\" \"\"",
+ NULL,
+ gtd_provider_eds_fill_task_list,
+ data);
+
+ priv->task_lists = g_list_append (priv->task_lists, list);
+
+ g_object_set_data (G_OBJECT (source), "task-list", list);
+ g_hash_table_insert (priv->clients, source, client);
+
+ /* Emit LIST_ADDED signal */
+ g_signal_emit_by_name (self, "list-added", list);
+
+ g_object_unref (parent);
+
+ g_debug ("%s: %s (%s)",
+ G_STRFUNC,
+ _("Task list source successfully connected"),
+ e_source_get_display_name (source));
+ }
+ else
+ {
+ g_debug ("%s: %s (%s): %s",
+ G_STRFUNC,
+ _("Failed to connect to task list source"),
+ e_source_get_uid (source),
+ error->message);
+
+/*
+ emit_show_error_message (gtd_manager_get_default (),
+ _("Failed to connect to task list source"),
+ error->message);
+*/
+
+ g_error_free (error);
+ return;
+ }
+
+}
+
+static void
+gtd_provider_eds_load_source (GtdProviderEds *provider,
+ ESource *source)
+{
+ GtdProviderEdsPrivate *priv;
+
+ priv = gtd_provider_eds_get_instance_private (provider);
+
+ if (e_source_has_extension (source, E_SOURCE_EXTENSION_TASK_LIST) &&
+ !g_hash_table_lookup (priv->clients, source) &&
+ GTD_PROVIDER_EDS_CLASS (G_OBJECT_GET_CLASS (provider))->should_load_source (provider, source))
+ {
+ g_message ("%s: loading local list '%s'",
+ G_STRFUNC,
+ e_source_get_display_name (source));
+
+ e_cal_client_connect (source,
+ E_CAL_CLIENT_SOURCE_TYPE_TASKS,
+ 10, /* seconds to wait */
+ NULL,
+ gtd_provider_eds_on_client_connected,
+ provider);
+ }
+ else
+ {
+ g_warning ("%s: %s %s (%s)",
+ G_STRFUNC,
+ _("Skipping already loaded task list "),
+ e_source_get_display_name (source),
+ e_source_get_uid (source));
+ }
+}
+
+static void
+gtd_provider_eds_remove_source (GtdProviderEds *provider,
+ ESource *source)
+{
+ GtdProviderEdsPrivate *priv;
+ GtdTaskList *list;
+
+ priv = gtd_provider_eds_get_instance_private (provider);
+ list = g_object_get_data (G_OBJECT (source), "task-list");
+
+ g_hash_table_remove (priv->clients, source);
+
+ /* Since all subclasses will have this signal given that they
+ * are all GtdProvider implementations, it's not that bad
+ * to let it stay here.
+ */
+ g_signal_emit_by_name (provider, "list-removed", list);
+}
+
+
+
+
+/************************
+ * Credentials prompter *
+ ************************/
+
+static void
+gtd_manager__invoke_authentication (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ESource *source = E_SOURCE (source_object);
+ GError *error = NULL;
+ gboolean canceled;
+
+ e_source_invoke_authenticate_finish (source,
+ result,
+ &error);
+
+ canceled = g_error_matches (error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED);
+
+ if (!canceled)
+ {
+ g_warning ("%s: %s (%s): %s",
+ G_STRFUNC,
+ _("Failed to prompt for credentials"),
+ e_source_get_uid (source),
+ error->message);
+ }
+
+ g_clear_error (&error);
+}
+
+static void
+gtd_provider_local_credentials_prompt_done (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ETrustPromptResponse response = E_TRUST_PROMPT_RESPONSE_UNKNOWN;
+ ESource *source = E_SOURCE (source_object);
+ GError *error = NULL;
+
+ e_trust_prompt_run_for_source_finish (source, result, &response, &error);
+
+ if (error)
+ {
+ g_warning ("%s: %s '%s': %s",
+ G_STRFUNC,
+ _("Failed to prompt for credentials for"),
+ e_source_get_display_name (source),
+ error->message);
+
+ }
+ else if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT || response ==
E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY)
+ {
+ /* Use NULL credentials to reuse those from the last time. */
+ e_source_invoke_authenticate (source,
+ NULL,
+ NULL /* cancellable */,
+ gtd_manager__invoke_authentication,
+ NULL);
+ }
+
+ g_clear_error (&error);
+}
+
+static void
+gtd_provider_eds_credentials_required (ESourceRegistry *registry,
+ ESource *source,
+ ESourceCredentialsReason reason,
+ const gchar *certificate_pem,
+ GTlsCertificateFlags certificate_errors,
+ const GError *error,
+ gpointer user_data)
+{
+ GtdProviderEdsPrivate *priv;
+ GtdProviderEds *self;
+
+ g_return_if_fail (GTD_IS_PROVIDER_EDS (user_data));
+
+ self = GTD_PROVIDER_EDS (user_data);
+ priv = gtd_provider_eds_get_instance_private (self);
+
+ if (e_credentials_prompter_get_auto_prompt_disabled_for (priv->credentials_prompter, source))
+ return;
+
+ if (reason == E_SOURCE_CREDENTIALS_REASON_SSL_FAILED)
+ {
+ e_trust_prompt_run_for_source (e_credentials_prompter_get_dialog_parent (priv->credentials_prompter),
+ source,
+ certificate_pem,
+ certificate_errors,
+ error ? error->message : NULL,
+ TRUE, // allow saving sources
+ NULL, // we won't cancel the operation
+ gtd_provider_local_credentials_prompt_done,
+ NULL);
+ }
+ else if (error && reason == E_SOURCE_CREDENTIALS_REASON_ERROR)
+ {
+ g_warning ("%s: %s '%s': %s",
+ G_STRFUNC,
+ _("Authentication failure"),
+ e_source_get_display_name (source),
+ error->message);
+ }
+}
+
+
+static void
+gtd_provider_eds_finalize (GObject *object)
+{
+ GtdProviderEds *self = (GtdProviderEds *)object;
+ GtdProviderEdsPrivate *priv = gtd_provider_eds_get_instance_private (self);
+
+ g_clear_pointer (&priv->clients, g_hash_table_destroy);
+ g_clear_object (&priv->credentials_prompter);
+ g_clear_object (&priv->source_registry);
+
+ G_OBJECT_CLASS (gtd_provider_eds_parent_class)->finalize (object);
+}
+
+static void
+gtd_provider_eds_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtdProviderEds *self = GTD_PROVIDER_EDS (object);
+ GtdProviderEdsPrivate *priv = gtd_provider_eds_get_instance_private (self);
+
+ switch (prop_id)
+ {
+ case PROP_REGISTRY:
+ g_value_set_object (value, priv->source_registry);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtd_provider_eds_set_registry (GtdProviderEds *provider,
+ ESourceRegistry *registry)
+{
+ GtdProviderEdsPrivate *priv = gtd_provider_eds_get_instance_private (provider);
+ GList *sources;
+ GList *l;
+ GError *error = NULL;
+
+ g_set_object (&priv->source_registry, registry);
+
+ priv->credentials_prompter = e_credentials_prompter_new (priv->source_registry);
+
+ if (error != NULL)
+ {
+ g_warning ("%s: %s", _("Error loading task manager"), error->message);
+ g_error_free (error);
+ return;
+ }
+
+ /* First of all, disable authentication dialog for non-tasklists sources */
+ sources = e_source_registry_list_sources (priv->source_registry, NULL);
+
+ for (l = sources; l != NULL; l = g_list_next (l))
+ {
+ ESource *source = E_SOURCE (l->data);
+
+ /* Mark for skip also currently disabled sources */
+ e_credentials_prompter_set_auto_prompt_disabled_for (priv->credentials_prompter,
+ source,
+ !e_source_has_extension (source,
E_SOURCE_EXTENSION_TASK_LIST));
+ }
+
+ g_list_free_full (sources, g_object_unref);
+
+ /* Load task list sources */
+ sources = e_source_registry_list_sources (priv->source_registry, E_SOURCE_EXTENSION_TASK_LIST);
+
+ /* While load_sources > 0, Gtd::ready = FALSE */
+ priv->loaded_sources = g_list_length (sources);
+
+ gtd_object_set_ready (GTD_OBJECT (provider), priv->loaded_sources == 0);
+
+ g_debug ("%s: number of sources to load: %d",
+ G_STRFUNC,
+ priv->loaded_sources);
+
+ for (l = sources; l != NULL; l = l->next)
+ gtd_provider_eds_load_source (provider, l->data);
+
+ g_list_free_full (sources, g_object_unref);
+
+ /* listen to the signals, so new sources don't slip by */
+ g_signal_connect_swapped (priv->source_registry,
+ "source-added",
+ G_CALLBACK (gtd_provider_eds_load_source),
+ provider);
+
+ g_signal_connect_swapped (priv->source_registry,
+ "source-removed",
+ G_CALLBACK (gtd_provider_eds_remove_source),
+ provider);
+
+ g_signal_connect (priv->source_registry,
+ "credentials-required",
+ G_CALLBACK (gtd_provider_eds_credentials_required),
+ provider);
+
+ e_credentials_prompter_process_awaiting_credentials (priv->credentials_prompter);
+}
+
+
+static void
+gtd_provider_eds_create_task_finished (GObject *client,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TaskData *data = user_data;
+ gchar *new_uid = NULL;
+ GError *error = NULL;
+
+ e_cal_client_create_object_finish (E_CAL_CLIENT (client),
+ result,
+ &new_uid,
+ &error);
+
+ gtd_object_set_ready (GTD_OBJECT (data->data), TRUE);
+
+ if (error)
+ {
+ g_warning ("%s: %s: %s",
+ G_STRFUNC,
+ _("Error creating task"),
+ error->message);
+
+/*
+ emit_show_error_message (GTD_MANAGER (user_data),
+ _("Error creating task"),
+ error->message);
+*/
+
+ g_error_free (error);
+ g_free (data);
+ return;
+ }
+ else
+ {
+ /*
+ * 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 (data->data), new_uid);
+ g_free (new_uid);
+ }
+
+ g_free (data);
+ }
+}
+
+static void
+gtd_provider_eds_update_task_finished (GObject *client,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TaskData *data = user_data;
+ GtdTask *task;
+ GError *error = NULL;
+
+ task = GTD_TASK (data->data);
+ e_cal_client_modify_object_finish (E_CAL_CLIENT (client),
+ result,
+ &error);
+
+ if (error)
+ {
+ g_warning ("%s: %s: %s",
+ G_STRFUNC,
+ _("Error updating task"),
+ error->message);
+
+/*
+ emit_show_error_message (data->manager,
+ _("Error updating task"),
+ error->message);
+*/
+
+ g_error_free (error);
+ }
+
+ g_free (data);
+
+ gtd_object_set_ready (GTD_OBJECT (data->data), TRUE);
+}
+
+static void
+gtd_provider_eds_remove_task_finished (GObject *client,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TaskData *data = user_data;
+ GError *error = NULL;
+
+ e_cal_client_remove_object_finish (E_CAL_CLIENT (client),
+ result,
+ &error);
+
+ gtd_object_set_ready (GTD_OBJECT (data->data), TRUE);
+
+ g_object_unref ((GtdTask*) data->data);
+ g_free (data);
+
+ if (error)
+ {
+ g_warning ("%s: %s: %s",
+ G_STRFUNC,
+ _("Error removing task"),
+ error->message);
+/*
+ emit_show_error_message (GTD_MANAGER (user_data),
+ _("Error removing task"),
+ error->message);
+*/
+ g_error_free (error);
+ return;
+ }
+}
+
+static void
+gtd_provider_eds_remote_create_source_finished (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error;
+
+ error = NULL;
+
+ e_source_remote_create_finish (E_SOURCE (source),
+ result,
+ &error);
+
+ if (error)
+ {
+ g_warning ("%s: %s: %s",
+ G_STRFUNC,
+ _("Error creating task list"),
+ error->message);
+/*
+ emit_show_error_message (GTD_MANAGER (user_data),
+ _("Error creating task list"),
+ error->message);
+*/
+ g_clear_error (&error);
+ }
+}
+
+static void
+task_list_removal_finished (GtdManager *manager,
+ ESource *source,
+ GError **error)
+{
+ gtd_object_set_ready (GTD_OBJECT (manager), TRUE);
+
+ if (*error)
+ {
+ g_warning ("%s: %s: %s",
+ G_STRFUNC,
+ _("Error removing task list"),
+ (*error)->message);
+/*
+ emit_show_error_message (manager,
+ _("Error removing task list"),
+ (*error)->message);
+*/
+ g_clear_error (error);
+ }
+}
+
+
+static void
+gtd_provider_eds_remote_delete_finished (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ e_source_remote_delete_finish (E_SOURCE (source),
+ result,
+ &error);
+
+ task_list_removal_finished (GTD_MANAGER (user_data),
+ E_SOURCE (source),
+ &error);
+}
+
+static void
+gtd_provider_eds_remove_source_finished (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ e_source_remove_finish (E_SOURCE (source),
+ result,
+ &error);
+
+ task_list_removal_finished (GTD_MANAGER (user_data),
+ E_SOURCE (source),
+ &error);
+}
+
+static void
+gtd_provider_eds_commit_source_finished (GObject *registry,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ g_return_if_fail (GTD_IS_MANAGER (user_data));
+
+ gtd_object_set_ready (GTD_OBJECT (user_data), TRUE);
+ e_source_registry_commit_source_finish (E_SOURCE_REGISTRY (registry),
+ result,
+ &error);
+
+ if (error)
+ {
+ g_warning ("%s: %s: %s",
+ G_STRFUNC,
+ _("Error saving task list"),
+ error->message);
+/*
+ emit_show_error_message (GTD_MANAGER (user_data),
+ _("Error saving task list"),
+ error->message);
+*/
+ g_error_free (error);
+ return;
+ }
+}
+
+static void
+gtd_provider_eds_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtdProviderEds *self = GTD_PROVIDER_EDS (object);
+
+ switch (prop_id)
+ {
+ case PROP_REGISTRY:
+ gtd_provider_eds_set_registry (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtd_provider_eds_class_init (GtdProviderEdsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtd_provider_eds_finalize;
+ object_class->get_property = gtd_provider_eds_get_property;
+ object_class->set_property = gtd_provider_eds_set_property;
+
+ g_object_class_install_property (object_class,
+ PROP_REGISTRY,
+ g_param_spec_object ("registry",
+ "Source registry",
+ "The EDS source registry object",
+ E_TYPE_SOURCE_REGISTRY,
+ G_PARAM_READABLE | G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gtd_provider_eds_init (GtdProviderEds *self)
+{
+ GtdProviderEdsPrivate *priv = gtd_provider_eds_get_instance_private (self);
+
+ /* hash table */
+ priv->clients = g_hash_table_new_full ((GHashFunc) e_source_hash,
+ (GEqualFunc) e_source_equal,
+ g_object_unref,
+ g_object_unref);
+}
+
+GtdProviderEds*
+gtd_provider_eds_new (ESourceRegistry *registry)
+{
+ return g_object_new (GTD_TYPE_PROVIDER_EDS,
+ "registry", registry,
+ NULL);
+}
+
+ESourceRegistry*
+gtd_provider_eds_get_registry (GtdProviderEds *provider)
+{
+ GtdProviderEdsPrivate *priv;
+
+ g_return_val_if_fail (GTD_IS_PROVIDER_EDS (provider), NULL);
+
+ priv = gtd_provider_eds_get_instance_private (provider);
+
+ return priv->source_registry;
+}
+
+void
+gtd_provider_eds_create_task (GtdProviderEds *provider,
+ GtdTask *task)
+{
+ GtdProviderEdsPrivate *priv;
+ ECalComponent *component;
+ ECalClient *client;
+ TaskData *data;
+ ESource *source;
+
+ g_return_if_fail (GTD_IS_TASK (task));
+
+ priv = gtd_provider_eds_get_instance_private (provider);
+ source = gtd_task_list_get_source (gtd_task_get_list (task));
+ client = g_hash_table_lookup (priv->clients, source);
+ component = gtd_task_get_component (task);
+
+ /* Temporary data for async operation */
+ data = task_data_new (provider, (gpointer) task);
+
+ /* The task is not ready until we finish the operation */
+ gtd_object_set_ready (GTD_OBJECT (task), FALSE);
+
+ e_cal_client_create_object (client,
+ e_cal_component_get_icalcomponent (component),
+ NULL, // We won't cancel the operation
+ (GAsyncReadyCallback) gtd_provider_eds_create_task_finished,
+ data);
+}
+
+void
+gtd_provider_eds_update_task (GtdProviderEds *provider,
+ GtdTask *task)
+{
+ GtdProviderEdsPrivate *priv;
+ ECalComponent *component;
+ ECalClient *client;
+ TaskData *data;
+ ESource *source;
+
+ g_return_if_fail (GTD_IS_TASK (task));
+
+ priv = gtd_provider_eds_get_instance_private (provider);
+ source = gtd_task_list_get_source (gtd_task_get_list (task));
+ client = g_hash_table_lookup (priv->clients, source);
+ component = gtd_task_get_component (task);
+
+ /* Temporary data for async operation */
+ data = task_data_new (provider, (gpointer) task);
+
+ /* The task is not ready until we finish the operation */
+ gtd_object_set_ready (GTD_OBJECT (task), FALSE);
+
+ e_cal_client_modify_object (client,
+ e_cal_component_get_icalcomponent (component),
+ E_CAL_OBJ_MOD_THIS,
+ NULL, // We won't cancel the operation
+ (GAsyncReadyCallback) gtd_provider_eds_update_task_finished,
+ data);
+}
+
+void
+gtd_provider_eds_remove_task (GtdProviderEds *provider,
+ GtdTask *task)
+{
+
+ GtdProviderEdsPrivate *priv;
+ ECalComponent *component;
+ ECalComponentId *id;
+ ECalClient *client;
+ TaskData *data;
+ ESource *source;
+
+ g_return_if_fail (GTD_IS_TASK (task));
+
+ priv = gtd_provider_eds_get_instance_private (provider);
+ source = gtd_task_list_get_source (gtd_task_get_list (task));
+ client = g_hash_table_lookup (priv->clients, source);
+ component = gtd_task_get_component (task);
+ id = e_cal_component_get_id (component);
+
+ /* Temporary data for async operation */
+ data = task_data_new (provider, (gpointer) task);
+
+ /* The task is not ready until we finish the operation */
+ gtd_object_set_ready (GTD_OBJECT (task), FALSE);
+
+ e_cal_client_remove_object (client,
+ id->uid,
+ id->rid,
+ E_CAL_OBJ_MOD_THIS,
+ NULL, // We won't cancel the operation
+ (GAsyncReadyCallback) gtd_provider_eds_remove_task_finished,
+ data);
+
+ e_cal_component_free_id (id);
+}
+
+void
+gtd_provider_eds_create_task_list (GtdProviderEds *provider,
+ GtdTaskList *list)
+{
+ GtdProviderEdsPrivate *priv;
+ ESource *source;
+ ESource *parent;
+
+ g_return_if_fail (GTD_IS_TASK_LIST (list));
+ g_return_if_fail (gtd_task_list_get_source (list));
+
+ priv = gtd_provider_eds_get_instance_private (provider);
+ source = gtd_task_list_get_source (list);
+ parent = e_source_registry_ref_source (priv->source_registry, e_source_get_parent (source));
+
+ e_source_remote_create (parent,
+ source,
+ NULL,
+ (GAsyncReadyCallback) gtd_provider_eds_remote_create_source_finished,
+ provider);
+
+ g_object_unref (parent);
+}
+
+void
+gtd_provider_eds_update_task_list (GtdProviderEds *provider,
+ GtdTaskList *list)
+{
+
+ GtdProviderEdsPrivate *priv;
+ ESource *source;
+
+ g_return_if_fail (GTD_IS_TASK_LIST (list));
+ g_return_if_fail (gtd_task_list_get_source (list));
+
+ priv = gtd_provider_eds_get_instance_private (provider);
+ source = gtd_task_list_get_source (list);
+
+ gtd_object_set_ready (GTD_OBJECT (provider), FALSE);
+ e_source_registry_commit_source (priv->source_registry,
+ source,
+ NULL,
+ (GAsyncReadyCallback) gtd_provider_eds_commit_source_finished,
+ provider);
+}
+
+void
+gtd_provider_eds_remove_task_list (GtdProviderEds *provider,
+ GtdTaskList *list)
+{
+ GtdProviderEdsPrivate *priv;
+ ESource *source;
+
+ g_return_if_fail (GTD_IS_TASK_LIST (list));
+ g_return_if_fail (gtd_task_list_get_source (list));
+
+ priv = gtd_provider_eds_get_instance_private (provider);
+ source = gtd_task_list_get_source (list);
+
+ gtd_object_set_ready (GTD_OBJECT (provider), FALSE);
+
+ if (e_source_get_remote_deletable (source))
+ {
+ e_source_remote_delete (source,
+ NULL,
+ (GAsyncReadyCallback) gtd_provider_eds_remote_delete_finished,
+ provider);
+ }
+ else
+ {
+ e_source_remove (source,
+ NULL,
+ (GAsyncReadyCallback) gtd_provider_eds_remove_source_finished,
+ provider);
+ }
+}
+
+GList*
+gtd_provider_eds_get_task_lists (GtdProviderEds *provider)
+{
+ GtdProviderEdsPrivate *priv = gtd_provider_eds_get_instance_private (provider);
+
+ return priv->task_lists;
+}
diff --git a/plugins/eds/gtd-provider-eds.h b/plugins/eds/gtd-provider-eds.h
new file mode 100644
index 0000000..2b53751
--- /dev/null
+++ b/plugins/eds/gtd-provider-eds.h
@@ -0,0 +1,67 @@
+/* gtd-provider-eds.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_PROVIDER_EDS_H
+#define GTD_PROVIDER_EDS_H
+
+#include <glib.h>
+#include <gnome-todo/gnome-todo.h>
+#include <libecal/libecal.h>
+#include <libedataserverui/libedataserverui.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_PROVIDER_EDS (gtd_provider_eds_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (GtdProviderEds, gtd_provider_eds, GTD, PROVIDER_EDS, GtdObject)
+
+struct _GtdProviderEdsClass
+{
+ GtdObjectClass parent;
+
+ gboolean (*should_load_source) (GtdProviderEds *provider,
+ ESource *source);
+};
+
+GtdProviderEds* gtd_provider_eds_new (ESourceRegistry *registry);
+
+ESourceRegistry* gtd_provider_eds_get_registry (GtdProviderEds *local);
+
+void gtd_provider_eds_create_task (GtdProviderEds *provider,
+ GtdTask *task);
+
+void gtd_provider_eds_update_task (GtdProviderEds *provider,
+ GtdTask *task);
+
+void gtd_provider_eds_remove_task (GtdProviderEds *provider,
+ GtdTask *task);
+
+void gtd_provider_eds_create_task_list (GtdProviderEds *provider,
+ GtdTaskList *list);
+
+void gtd_provider_eds_update_task_list (GtdProviderEds *provider,
+ GtdTaskList *list);
+
+void gtd_provider_eds_remove_task_list (GtdProviderEds *provider,
+ GtdTaskList *list);
+
+GList* gtd_provider_eds_get_task_lists (GtdProviderEds *provider);
+
+G_END_DECLS
+
+#endif /* GTD_PROVIDER_EDS_H */
diff --git a/plugins/eds/gtd-provider-local.c b/plugins/eds/gtd-provider-local.c
new file mode 100644
index 0000000..a751477
--- /dev/null
+++ b/plugins/eds/gtd-provider-local.c
@@ -0,0 +1,239 @@
+/* gtd-provider-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-provider-local.h"
+
+#include <glib/gi18n.h>
+
+struct _GtdProviderLocal
+{
+ GtdObject parent;
+
+ GIcon *icon;
+ GList *tasklists;
+};
+
+static void gtd_provider_iface_init (GtdProviderInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtdProviderLocal, gtd_provider_local, GTD_TYPE_PROVIDER_EDS,
+ G_IMPLEMENT_INTERFACE (GTD_TYPE_PROVIDER,
+ gtd_provider_iface_init))
+
+enum {
+ PROP_0,
+ PROP_ENABLED,
+ PROP_ID,
+ PROP_NAME,
+ PROP_DESCRIPTION,
+ LAST_PROP
+};
+
+/*
+ * GtdProviderInterface implementation
+ */
+static const gchar*
+gtd_provider_local_get_id (GtdProvider *provider)
+{
+ return "local";
+}
+
+static const gchar*
+gtd_provider_local_get_name (GtdProvider *provider)
+{
+ return _("Local");
+}
+
+static const gchar*
+gtd_provider_local_get_description (GtdProvider *provider)
+{
+ return _("On This Computer");
+}
+
+
+static gboolean
+gtd_provider_local_get_enabled (GtdProvider *provider)
+{
+ return TRUE;
+}
+
+static const GIcon*
+gtd_provider_local_get_icon_for_list (GtdProvider *provider,
+ GtdTaskList *list)
+{
+ GtdProviderLocal *self;
+
+ self = GTD_PROVIDER_LOCAL (provider);
+
+ return self->icon;
+}
+
+static const GtkWidget*
+gtd_provider_local_get_edit_panel (GtdProvider *provider)
+{
+ return NULL;
+}
+
+static void
+gtd_provider_local_create_task (GtdProvider *provider,
+ GtdTask *task)
+{
+ gtd_provider_eds_create_task (GTD_PROVIDER_EDS (provider), task);
+}
+
+static void
+gtd_provider_local_update_task (GtdProvider *provider,
+ GtdTask *task)
+{
+ gtd_provider_eds_update_task (GTD_PROVIDER_EDS (provider), task);
+}
+
+static void
+gtd_provider_local_remove_task (GtdProvider *provider,
+ GtdTask *task)
+{
+ gtd_provider_eds_remove_task (GTD_PROVIDER_EDS (provider), task);
+}
+
+static void
+gtd_provider_local_create_task_list (GtdProvider *provider,
+ GtdTaskList *list)
+{
+ gtd_provider_eds_create_task_list (GTD_PROVIDER_EDS (provider), list);
+}
+
+static void
+gtd_provider_local_update_task_list (GtdProvider *provider,
+ GtdTaskList *list)
+{
+ gtd_provider_eds_update_task_list (GTD_PROVIDER_EDS (provider), list);
+}
+
+static void
+gtd_provider_local_remove_task_list (GtdProvider *provider,
+ GtdTaskList *list)
+{
+ gtd_provider_eds_remove_task_list (GTD_PROVIDER_EDS (provider), list);
+
+ g_signal_emit_by_name (provider, "list-removed", list);
+}
+
+static GList*
+gtd_provider_local_get_task_lists (GtdProvider *provider)
+{
+ return gtd_provider_eds_get_task_lists (GTD_PROVIDER_EDS (provider));
+}
+
+static void
+gtd_provider_iface_init (GtdProviderInterface *iface)
+{
+ iface->get_id = gtd_provider_local_get_id;
+ iface->get_name = gtd_provider_local_get_name;
+ iface->get_description = gtd_provider_local_get_description;
+ iface->get_enabled = gtd_provider_local_get_enabled;
+ iface->get_icon_for_list = gtd_provider_local_get_icon_for_list;
+ iface->get_edit_panel = gtd_provider_local_get_edit_panel;
+ iface->create_task = gtd_provider_local_create_task;
+ iface->update_task = gtd_provider_local_update_task;
+ iface->remove_task = gtd_provider_local_remove_task;
+ iface->create_task_list = gtd_provider_local_create_task_list;
+ iface->update_task_list = gtd_provider_local_update_task_list;
+ iface->get_task_lists = gtd_provider_local_get_task_lists;
+}
+
+GtdProviderLocal*
+gtd_provider_local_new (ESourceRegistry *registry)
+{
+ return g_object_new (GTD_TYPE_PROVIDER_LOCAL,
+ "registry", registry,
+ NULL);
+}
+
+static void
+gtd_provider_local_finalize (GObject *object)
+{
+ GtdProviderLocal *self = (GtdProviderLocal *)object;
+
+ g_clear_object (&self->icon);
+
+ G_OBJECT_CLASS (gtd_provider_local_parent_class)->finalize (object);
+}
+
+static void
+gtd_provider_local_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtdProvider *provider = GTD_PROVIDER (object);
+
+ switch (prop_id)
+ {
+ case PROP_DESCRIPTION:
+ g_value_set_string (value, gtd_provider_local_get_description (provider));
+ break;
+
+ case PROP_ENABLED:
+ g_value_set_boolean (value, gtd_provider_local_get_enabled (provider));
+ break;
+
+ case PROP_ID:
+ g_value_set_string (value, gtd_provider_local_get_id (provider));
+ break;
+
+ case PROP_NAME:
+ g_value_set_string (value, gtd_provider_local_get_name (provider));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static gboolean
+gtd_provider_local_should_load_source (GtdProviderEds *provider,
+ ESource *source)
+{
+ if (e_source_has_extension (source, E_SOURCE_EXTENSION_TASK_LIST))
+ return g_strcmp0 (e_source_get_parent (source), "local-stub") == 0;
+
+ return FALSE;
+}
+
+static void
+gtd_provider_local_class_init (GtdProviderLocalClass *klass)
+{
+ GtdProviderEdsClass *eds_class = GTD_PROVIDER_EDS_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ eds_class->should_load_source = gtd_provider_local_should_load_source;
+
+ object_class->finalize = gtd_provider_local_finalize;
+ object_class->get_property = gtd_provider_local_get_property;
+
+ g_object_class_override_property (object_class, PROP_DESCRIPTION, "description");
+ g_object_class_override_property (object_class, PROP_ENABLED, "enabled");
+ g_object_class_override_property (object_class, PROP_ID, "id");
+ g_object_class_override_property (object_class, PROP_NAME, "name");
+}
+
+static void
+gtd_provider_local_init (GtdProviderLocal *self)
+{
+ /* icon */
+ self->icon = G_ICON (g_themed_icon_new_with_default_fallbacks ("computer-symbolic"));
+}
diff --git a/plugins/eds/gtd-provider-local.h b/plugins/eds/gtd-provider-local.h
new file mode 100644
index 0000000..fab47d8
--- /dev/null
+++ b/plugins/eds/gtd-provider-local.h
@@ -0,0 +1,40 @@
+/* gtd-provider-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_PROVIDER_LOCAL_H
+#define GTD_PROVIDER_LOCAL_H
+
+#include "gtd-provider-eds.h"
+
+#include <glib.h>
+
+#include <gnome-todo/gnome-todo.h>
+#include <libecal/libecal.h>
+#include <libedataserverui/libedataserverui.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_PROVIDER_LOCAL (gtd_provider_local_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdProviderLocal, gtd_provider_local, GTD, PROVIDER_LOCAL, GtdProviderEds)
+
+GtdProviderLocal* gtd_provider_local_new (ESourceRegistry *source_registry);
+
+G_END_DECLS
+
+#endif /* GTD_PROVIDER_LOCAL_H */
diff --git a/plugins/eds/gtd-task-list-eds.c b/plugins/eds/gtd-task-list-eds.c
new file mode 100644
index 0000000..520d3ae
--- /dev/null
+++ b/plugins/eds/gtd-task-list-eds.c
@@ -0,0 +1,139 @@
+/* gtd-task-list-eds.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-task-list-eds.h"
+
+struct _GtdTaskListEds
+{
+ ESource *source;
+};
+
+G_DEFINE_TYPE (GtdTaskListEds, gtd_task_list_eds, GTD_TYPE_TASK_LIST)
+
+enum {
+ PROP_0,
+ PROP_SOURCE,
+ N_PROPS
+};
+
+static void
+gtd_task_list_eds_finalize (GObject *object)
+{
+ GtdTaskListEds *self = GTD_TASK_LIST_EDS (object);
+
+ g_clear_object (&self->source);
+
+ G_OBJECT_CLASS (gtd_task_list_eds_parent_class)->finalize (object);
+}
+
+static void
+gtd_task_list_eds_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtdTaskListEds *self = GTD_TASK_LIST_EDS (object);
+
+ switch (prop_id)
+ {
+ case PROP_SOURCE:
+ g_value_set_object (value, self->source);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtd_task_list_eds_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtdTaskListEds *self = GTD_TASK_LIST_EDS (object);
+
+ switch (prop_id)
+ {
+ case PROP_SOURCE:
+ gtd_task_list_eds_set_source (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtd_task_list_eds_class_init (GtdTaskListEdsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtd_task_list_eds_finalize;
+ object_class->get_property = gtd_task_list_eds_get_property;
+ object_class->set_property = gtd_task_list_eds_set_property;
+
+ /**
+ * GtdTaskListEds::source:
+ *
+ * The #ESource of this #GtdTaskListEds
+ */
+ g_object_class_install_property (object_class,
+ PROP_SOURCE,
+ g_param_spec_object ("source",
+ "ESource of this list",
+ "The ESource of this list",
+ E_TYPE_SOURCE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+}
+
+static void
+gtd_task_list_eds_init (GtdTaskListEds *self)
+{
+}
+
+GtdTaskListEds*
+gtd_task_list_eds_new (GtdProvider *provider,
+ ESource *source)
+{
+ return g_object_new (GTD_TYPE_TASK_LIST_EDS,
+ "provider", provider,
+ "source", source,
+ NULL);
+}
+
+ESource*
+gtd_task_list_eds_get_source (GtdTaskListEds *list)
+{
+ g_return_val_if_fail (GTD_IS_TASK_LIST_EDS (list), NULL);
+
+ return list->source;
+}
+
+void
+gtd_task_list_eds_set_source (GtdTaskListEds *list,
+ ESource *source)
+{
+ g_return_if_fail (GTD_IS_TASK_LIST_EDS (list));
+
+ if (g_set_object (&list->source, source))
+ {
+ // TODO: bind color & name
+ g_object_notify (G_OBJECT (list), "source");
+ }
+}
diff --git a/plugins/eds/gtd-task-list-eds.h b/plugins/eds/gtd-task-list-eds.h
new file mode 100644
index 0000000..2579f37
--- /dev/null
+++ b/plugins/eds/gtd-task-list-eds.h
@@ -0,0 +1,42 @@
+/* gtd-task-list-eds.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_TASK_LIST_EDS_H
+#define GTD_TASK_LIST_EDS_H
+
+#include <glib-object.h>
+#include <gnome-todo/gnome-todo.h>
+#include <libecal/libecal.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_TASK_LIST_EDS (gtd_task_list_eds_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdTaskListEds, gtd_task_list_eds, GTD, TASK_LIST_EDS, GtdTaskList)
+
+GtdTaskListEds* gtd_task_list_eds_new (GtdProvider *provider,
+ ESource *source);
+
+ESource* gtd_task_list_eds_get_source (GtdTaskListEds *list);
+
+void gtd_task_list_eds_set_source (GtdTaskListEds *list,
+ ESource *source);
+
+G_END_DECLS
+
+#endif /* GTD_TASK_LIST_EDS_H */
diff --git a/src/gtd-manager.c b/src/gtd-manager.c
index 3a543fb..d92cefa 100644
--- a/src/gtd-manager.c
+++ b/src/gtd-manager.c
@@ -17,6 +17,7 @@
*/
#include "gtd-manager.h"
+#include "gtd-plugin-manager.h"
#include "gtd-storage-goa.h"
#include "gtd-storage-local.h"
#include "gtd-storage.h"
@@ -29,30 +30,14 @@
typedef struct
{
- GHashTable *clients;
- GList *task_lists;
- ECredentialsPrompter *credentials_prompter;
- ESourceRegistry *source_registry;
-
/*
* Today & Scheduled lists
*/
GtdTaskList *today_tasks_list;
GtdTaskList *scheduled_tasks_list;
- /* Online accounts */
- GoaClient *goa_client;
- gboolean goa_client_ready;
- GList *storage_locations;
-
GSettings *settings;
-
- /*
- * Small flag that contains the number of sources
- * that still have to be loaded. When this number
- * reaches 0, all sources are loaded.
- */
- gint load_sources;
+ GtdPluginManager *plugin_manager;
} GtdManagerPrivate;
struct _GtdManager
@@ -1321,6 +1306,8 @@ gtd_manager_init (GtdManager *self)
/* fixed task lists */
self->priv->scheduled_tasks_list = g_object_new (GTD_TYPE_TASK_LIST, NULL);
self->priv->today_tasks_list = g_object_new (GTD_TYPE_TASK_LIST, NULL);
+
+ self->priv->plugin_manager = gtd_plugin_manager_new ();
}
/**
@@ -1359,30 +1346,16 @@ void
gtd_manager_create_task (GtdManager *manager,
GtdTask *task)
{
- GtdManagerPrivate *priv = GTD_MANAGER (manager)->priv;
- ECalComponent *component;
- ECalClient *client;
- TaskData *data;
- ESource *source;
+ GtdTaskList *list;
+ GtdProvider *provider;
g_return_if_fail (GTD_IS_MANAGER (manager));
g_return_if_fail (GTD_IS_TASK (task));
- source = gtd_task_list_get_source (gtd_task_get_list (task));
- client = g_hash_table_lookup (priv->clients, source);
- component = gtd_task_get_component (task);
+ list = gtd_task_get_list (task);
+ provider = gtd_task_list_get_provider (list);
- /* Temporary data for async operation */
- data = task_data_new (manager, (gpointer) task);
-
- /* The task is not ready until we finish the operation */
- gtd_object_set_ready (GTD_OBJECT (task), FALSE);
-
- e_cal_client_create_object (client,
- e_cal_component_get_icalcomponent (component),
- NULL, // We won't cancel the operation
- (GAsyncReadyCallback) gtd_manager__create_task_finished,
- data);
+ gtd_provider_create_task (provider, task);
}
/**
@@ -1398,36 +1371,16 @@ void
gtd_manager_remove_task (GtdManager *manager,
GtdTask *task)
{
- GtdManagerPrivate *priv = GTD_MANAGER (manager)->priv;
- ECalComponent *component;
- ECalComponentId *id;
- ECalClient *client;
- TaskData *data;
- ESource *source;
+ GtdTaskList *list;
+ GtdProvider *provider;
g_return_if_fail (GTD_IS_MANAGER (manager));
g_return_if_fail (GTD_IS_TASK (task));
- source = gtd_task_list_get_source (gtd_task_get_list (task));
- client = g_hash_table_lookup (priv->clients, source);
- component = gtd_task_get_component (task);
- id = e_cal_component_get_id (component);
-
- /* Temporary data for async operation */
- data = task_data_new (manager, (gpointer) task);
-
- /* The task is not ready until we finish the operation */
- gtd_object_set_ready (GTD_OBJECT (task), FALSE);
-
- e_cal_client_remove_object (client,
- id->uid,
- id->rid,
- E_CAL_OBJ_MOD_THIS,
- NULL, // We won't cancel the operation
- (GAsyncReadyCallback) gtd_manager__remove_task_finished,
- data);
+ list = gtd_task_get_list (task);
+ provider = gtd_task_list_get_provider (list);
- e_cal_component_free_id (id);
+ gtd_provider_remove_task (provider, task);
}
/**
@@ -1443,31 +1396,16 @@ void
gtd_manager_update_task (GtdManager *manager,
GtdTask *task)
{
- GtdManagerPrivate *priv = GTD_MANAGER (manager)->priv;
- ECalComponent *component;
- ECalClient *client;
- TaskData *data;
- ESource *source;
+ GtdTaskList *list;
+ GtdProvider *provider;
g_return_if_fail (GTD_IS_MANAGER (manager));
g_return_if_fail (GTD_IS_TASK (task));
- source = gtd_task_list_get_source (gtd_task_get_list (task));
- client = g_hash_table_lookup (priv->clients, source);
- component = gtd_task_get_component (task);
-
- /* Temporary data for async operation */
- data = task_data_new (manager, (gpointer) task);
-
- /* The task is not ready until we finish the operation */
- gtd_object_set_ready (GTD_OBJECT (task), FALSE);
+ list = gtd_task_get_list (task);
+ provider = gtd_task_list_get_provider (list);
- e_cal_client_modify_object (client,
- e_cal_component_get_icalcomponent (component),
- E_CAL_OBJ_MOD_THIS,
- NULL, // We won't cancel the operation
- (GAsyncReadyCallback) gtd_manager__update_task_finished,
- data);
+ gtd_provider_update_task (provider, task);
}
/**
@@ -1482,25 +1420,14 @@ void
gtd_manager_create_task_list (GtdManager *manager,
GtdTaskList *list)
{
- GtdManagerPrivate *priv;
- ESource *source;
- ESource *parent;
+ GtdProvider *provider;
g_return_if_fail (GTD_IS_MANAGER (manager));
g_return_if_fail (GTD_IS_TASK_LIST (list));
- g_return_if_fail (gtd_task_list_get_source (list));
-
- priv = manager->priv;
- source = gtd_task_list_get_source (list);
- parent = e_source_registry_ref_source (priv->source_registry, e_source_get_parent (source));
- e_source_remote_create (parent,
- source,
- NULL,
- (GAsyncReadyCallback) gtd_manager__remote_create_source_finished,
- manager);
+ provider = gtd_task_list_get_provider (list);
- g_object_unref (parent);
+ gtd_provider_create_task_list (provider, list);
}
/**
@@ -1516,30 +1443,14 @@ void
gtd_manager_remove_task_list (GtdManager *manager,
GtdTaskList *list)
{
- ESource *source;
+ GtdProvider *provider;
g_return_if_fail (GTD_IS_MANAGER (manager));
g_return_if_fail (GTD_IS_TASK_LIST (list));
- g_return_if_fail (gtd_task_list_get_source (list));
-
- source = gtd_task_list_get_source (list);
- gtd_object_set_ready (GTD_OBJECT (manager), FALSE);
+ provider = gtd_task_list_get_provider (list);
- if (e_source_get_remote_deletable (source))
- {
- e_source_remote_delete (source,
- NULL,
- (GAsyncReadyCallback) gtd_manager__remote_delete_finished,
- manager);
- }
- else
- {
- e_source_remove (source,
- NULL,
- (GAsyncReadyCallback) gtd_manager__remove_source_finished,
- manager);
- }
+ gtd_provider_remove_task_list (provider, list);
g_signal_emit (manager,
signals[LIST_REMOVED],
@@ -1560,20 +1471,14 @@ void
gtd_manager_save_task_list (GtdManager *manager,
GtdTaskList *list)
{
- ESource *source;
+ GtdProvider *provider;
g_return_if_fail (GTD_IS_MANAGER (manager));
g_return_if_fail (GTD_IS_TASK_LIST (list));
- g_return_if_fail (gtd_task_list_get_source (list));
- source = gtd_task_list_get_source (list);
+ provider = gtd_task_list_get_provider (list);
- gtd_object_set_ready (GTD_OBJECT (manager), FALSE);
- e_source_registry_commit_source (manager->priv->source_registry,
- source,
- NULL,
- (GAsyncReadyCallback) gtd_manager__commit_source_finished,
- manager);
+ gtd_provider_update_task_list (provider, list);
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]