[evolution-data-server/account-mgmt: 4/28] Add new ESource classes.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/account-mgmt: 4/28] Add new ESource classes.
- Date: Wed, 2 Mar 2011 03:45:22 +0000 (UTC)
commit be162028f24c5f54c0b491d30c8edcc1341e5f58
Author: Matthew Barnes <mbarnes redhat com>
Date: Fri Nov 12 10:19:34 2010 -0500
Add new ESource classes.
ESource
ESourceExtension
ESourceRegistry
addressbook/libebook/Makefile.am | 4 +-
addressbook/libebook/e-book.c | 4 +
addressbook/libebook/e-source-address-book.c | 65 +
addressbook/libebook/e-source-address-book.h | 67 +
calendar/libecal/Makefile.am | 6 +-
calendar/libecal/e-cal.c | 6 +
calendar/libecal/e-source-calendar.c | 111 ++
calendar/libecal/e-source-calendar.h | 135 ++
configure.ac | 2 +-
.../addressbook/libebook/libebook-docs.sgml | 1 +
.../addressbook/libebook/libebook-sections.txt | 19 +
docs/reference/addressbook/libebook/libebook.types | 2 +
.../addressbook/libebook/tmpl/e-book.sgml | 10 -
.../libebook/tmpl/e-source-address-book.sgml | 35 +
.../addressbook/libebook/tmpl/libebook-unused.sgml | 9 +
docs/reference/calendar/libecal/libecal-docs.sgml | 3 +
.../calendar/libecal/libecal-sections.txt | 55 +-
docs/reference/calendar/libecal/libecal.types | 4 +
docs/reference/calendar/libecal/tmpl/e-cal.sgml | 11 -
.../calendar/libecal/tmpl/e-source-calendar.sgml | 35 +
.../calendar/libecal/tmpl/e-source-memo-list.sgml | 35 +
.../calendar/libecal/tmpl/e-source-memo_list.sgml | 35 +
.../calendar/libecal/tmpl/e-source-task-list.sgml | 35 +
.../calendar/libecal/tmpl/e-source-task_list.sgml | 35 +
.../calendar/libecal/tmpl/libecal-unused.sgml | 64 +-
docs/reference/libedataserver/Makefile.am | 1 +
.../libedataserver/libedataserver-docs.sgml | 15 +
.../libedataserver/libedataserver-sections.txt | 301 ++++-
docs/reference/libedataserver/libedataserver.types | 14 +
.../libedataserver/tmpl/e-source-alarms.sgml | 71 +
.../tmpl/e-source-authentication.sgml | 182 +++
.../libedataserver/tmpl/e-source-autocomplete.sgml | 53 +
.../libedataserver/tmpl/e-source-extension.sgml | 49 +
.../libedataserver/tmpl/e-source-offline.sgml | 58 +
.../libedataserver/tmpl/e-source-password.sgml | 145 ++
.../libedataserver/tmpl/e-source-refresh.sgml | 58 +
.../libedataserver/tmpl/e-source-registry.sgml | 263 +++
.../libedataserver/tmpl/e-source-security.sgml | 81 +
.../libedataserver/tmpl/e-source-selectable.sgml | 97 ++
.../libedataserver/tmpl/e-source-webdav.sgml | 89 +
docs/reference/libedataserver/tmpl/e-source.sgml | 160 +--
.../libedataserverui/libedataserverui-sections.txt | 4 +-
libedataserver/Makefile.am | 32 +-
libedataserver/e-marshal.list | 1 +
libedataserver/e-source-alarms.c | 174 ++
libedataserver/e-source-alarms.h | 72 +
libedataserver/e-source-authentication.c | 408 +++++
libedataserver/e-source-authentication.h | 96 ++
libedataserver/e-source-autocomplete.c | 126 ++
libedataserver/e-source-autocomplete.h | 69 +
libedataserver/e-source-extension.c | 167 ++
libedataserver/e-source-extension.h | 65 +
libedataserver/e-source-offline.c | 126 ++
libedataserver/e-source-offline.h | 69 +
libedataserver/e-source-password.c | 412 +++++
libedataserver/e-source-password.h | 72 +
libedataserver/e-source-refresh.c | 126 ++
libedataserver/e-source-refresh.h | 69 +
libedataserver/e-source-registry.c | 1319 +++++++++++++++
libedataserver/e-source-registry.h | 127 ++
libedataserver/e-source-security.c | 203 +++
libedataserver/e-source-security.h | 70 +
libedataserver/e-source-selectable.c | 235 +++
libedataserver/e-source-selectable.h | 73 +
libedataserver/e-source-webdav.c | 552 +++++++
libedataserver/e-source-webdav.h | 95 ++
libedataserver/e-source.c | 1698 ++++++++++++--------
libedataserver/e-source.h | 164 +-
libedataserver/e-system-source.c | 117 ++
libedataserver/e-system-source.h | 63 +
libedataserver/libedataserver.pc.in | 2 +-
71 files changed, 8280 insertions(+), 951 deletions(-)
---
diff --git a/addressbook/libebook/Makefile.am b/addressbook/libebook/Makefile.am
index 07b3475..6e8d9a3 100644
--- a/addressbook/libebook/Makefile.am
+++ b/addressbook/libebook/Makefile.am
@@ -28,7 +28,8 @@ libebook_1_2_la_SOURCES = \
e-contact.c \
e-destination.c \
e-name-western.c \
- e-name-western-tables.h \
+ e-name-western-tables.h \
+ e-source-address-book.c \
e-vcard.c \
e-error.h
@@ -53,6 +54,7 @@ libebookinclude_HEADERS = \
e-contact.h \
e-destination.h \
e-name-western.h \
+ e-source-address-book.h \
e-vcard.h
%-$(API_VERSION).pc: %.pc
diff --git a/addressbook/libebook/e-book.c b/addressbook/libebook/e-book.c
index e63cce8..60eaf36 100644
--- a/addressbook/libebook/e-book.c
+++ b/addressbook/libebook/e-book.c
@@ -40,6 +40,7 @@
#include "e-error.h"
#include "e-contact.h"
#include "e-name-western.h"
+#include "e-source-address-book.h"
#include "e-book-view-private.h"
#include "e-book-marshal.h"
@@ -244,6 +245,9 @@ e_book_class_init (EBookClass *e_book_class)
gobject_class->finalize = e_book_finalize;
g_type_class_add_private (e_book_class, sizeof (EBookPrivate));
+
+ /* Register relevant ESource extensions. */
+ E_TYPE_SOURCE_ADDRESS_BOOK;
}
static void
diff --git a/addressbook/libebook/e-source-address-book.c b/addressbook/libebook/e-source-address-book.c
new file mode 100644
index 0000000..dcd3e11
--- /dev/null
+++ b/addressbook/libebook/e-source-address-book.c
@@ -0,0 +1,65 @@
+/*
+ * e-source-address-book.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-address-book.h"
+
+#include <libedataserver/e-data-server-util.h>
+
+G_DEFINE_TYPE (
+ ESourceAddressBook,
+ e_source_address_book,
+ E_TYPE_SOURCE_SELECTABLE)
+
+static void
+source_address_book_constructed (GObject *object)
+{
+ ESource *source;
+ ESourceExtension *extension;
+ GFile *user_data_dir;
+ GFile *user_sources_dir;
+
+ extension = E_SOURCE_EXTENSION (object);
+ source = e_source_extension_get_source (extension);
+
+ /* Redirect changes to the user's sources directory.
+ * That way built-in address books like "system" can
+ * be renamed or tweaked. */
+ user_data_dir = g_file_new_for_path (e_get_user_data_dir ());
+ user_sources_dir = g_file_get_child (user_data_dir, "sources");
+ e_source_redirect (source, user_sources_dir);
+ g_object_unref (user_sources_dir);
+ g_object_unref (user_data_dir);
+}
+
+static void
+e_source_address_book_class_init (ESourceAddressBookClass *class)
+{
+ GObjectClass *object_class;
+ ESourceExtensionClass *extension_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->constructed = source_address_book_constructed;
+
+ extension_class = E_SOURCE_EXTENSION_CLASS (class);
+ extension_class->name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
+}
+
+static void
+e_source_address_book_init (ESourceAddressBook *extension)
+{
+}
diff --git a/addressbook/libebook/e-source-address-book.h b/addressbook/libebook/e-source-address-book.h
new file mode 100644
index 0000000..eb7a45a
--- /dev/null
+++ b/addressbook/libebook/e-source-address-book.h
@@ -0,0 +1,67 @@
+/*
+ * e-source-address-book.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_ADDRESS_BOOK_H
+#define E_SOURCE_ADDRESS_BOOK_H
+
+/* This is a trivial but important ESourceSelectable subclass.
+ * It identifies an ESource as an address book. */
+
+#include <libedataserver/e-source-selectable.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_ADDRESS_BOOK \
+ (e_source_address_book_get_type ())
+#define E_SOURCE_ADDRESS_BOOK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_ADDRESS_BOOK, ESourceAddressBook))
+#define E_SOURCE_ADDRESS_BOOK_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_ADDRESS_BOOK, ESourceAddressBookClass))
+#define E_IS_SOURCE_ADDRESS_BOOK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_ADDRESS_BOOK))
+#define E_IS_SOURCE_ADDRESS_BOOK_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_ADDRESS_BOOK))
+#define E_SOURCE_ADDRESS_BOOK_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_ADDRESS_BOOK, ESourceAddressBookClass))
+
+#define E_SOURCE_EXTENSION_ADDRESS_BOOK "Address Book"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceAddressBook ESourceAddressBook;
+typedef struct _ESourceAddressBookClass ESourceAddressBookClass;
+typedef struct _ESourceAddressBookPrivate ESourceAddressBookPrivate;
+
+struct _ESourceAddressBook {
+ ESourceSelectable parent;
+ ESourceAddressBookPrivate *priv;
+};
+
+struct _ESourceAddressBookClass {
+ ESourceSelectableClass parent_class;
+};
+
+GType e_source_address_book_get_type (void);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_ADDRESS_BOOK_H */
diff --git a/calendar/libecal/Makefile.am b/calendar/libecal/Makefile.am
index 215c4bf..1d58ba9 100644
--- a/calendar/libecal/Makefile.am
+++ b/calendar/libecal/Makefile.am
@@ -31,7 +31,8 @@ libecal_1_2_la_SOURCES = \
e-cal-system-timezone.h \
e-cal-util.c \
e-cal-view.c \
- e-cal-view-private.h
+ e-cal-view-private.h \
+ e-source-calendar.c
libecal_1_2_la_LIBADD = \
$(top_builddir)/libedataserver/libedataserver-1.2.la \
@@ -53,7 +54,8 @@ libecalinclude_HEADERS = \
e-cal-system-timezone.h \
e-cal-types.h \
e-cal-util.h \
- e-cal-view.h
+ e-cal-view.h \
+ e-source-calendar.h
%-$(API_VERSION).pc: %.pc
cp $< $@
diff --git a/calendar/libecal/e-cal.c b/calendar/libecal/e-cal.c
index d5e87e4..f1efd8c 100644
--- a/calendar/libecal/e-cal.c
+++ b/calendar/libecal/e-cal.c
@@ -51,6 +51,7 @@
#include "e-cal-time-util.h"
#include "e-cal-view-private.h"
#include "e-cal.h"
+#include "e-source-calendar.h"
#include "e-gdbus-egdbuscalfactory.h"
#include "e-gdbus-egdbuscal.h"
@@ -644,6 +645,11 @@ e_cal_class_init (ECalClass *klass)
object_class->finalize = e_cal_finalize;
g_type_class_add_private (klass, sizeof (ECalPrivate));
+
+ /* Register relevant ESource extensions. */
+ E_TYPE_SOURCE_CALENDAR;
+ E_TYPE_SOURCE_MEMO_LIST;
+ E_TYPE_SOURCE_TASK_LIST;
}
static void
diff --git a/calendar/libecal/e-source-calendar.c b/calendar/libecal/e-source-calendar.c
new file mode 100644
index 0000000..7f9472d
--- /dev/null
+++ b/calendar/libecal/e-source-calendar.c
@@ -0,0 +1,111 @@
+/*
+ * e-source-calendar.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-calendar.h"
+
+#include <libedataserver/e-data-server-util.h>
+
+G_DEFINE_TYPE (
+ ESourceCalendar,
+ e_source_calendar,
+ E_TYPE_SOURCE_SELECTABLE)
+
+G_DEFINE_TYPE (
+ ESourceMemoList,
+ e_source_memo_list,
+ E_TYPE_SOURCE_SELECTABLE)
+
+G_DEFINE_TYPE (
+ ESourceTaskList,
+ e_source_task_list,
+ E_TYPE_SOURCE_SELECTABLE)
+
+static void
+source_common_constructed (GObject *object)
+{
+ ESource *source;
+ ESourceExtension *extension;
+ GFile *user_data_dir;
+ GFile *user_sources_dir;
+
+ extension = E_SOURCE_EXTENSION (object);
+ source = e_source_extension_get_source (extension);
+
+ /* Redirect changes to the user's sources directory.
+ * That way built-in calendars, task lists and memo
+ * lists like "system" can be renamed or tweaked. */
+ user_data_dir = g_file_new_for_path (e_get_user_data_dir ());
+ user_sources_dir = g_file_get_child (user_data_dir, "sources");
+ e_source_redirect (source, user_sources_dir);
+ g_object_unref (user_sources_dir);
+ g_object_unref (user_data_dir);
+}
+
+static void
+e_source_calendar_class_init (ESourceCalendarClass *class)
+{
+ GObjectClass *object_class;
+ ESourceExtensionClass *extension_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->constructed = source_common_constructed;
+
+ extension_class = E_SOURCE_EXTENSION_CLASS (class);
+ extension_class->name = E_SOURCE_EXTENSION_CALENDAR;
+}
+
+static void
+e_source_calendar_init (ESourceCalendar *extension)
+{
+}
+
+static void
+e_source_memo_list_class_init (ESourceMemoListClass *class)
+{
+ GObjectClass *object_class;
+ ESourceExtensionClass *extension_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->constructed = source_common_constructed;
+
+ extension_class = E_SOURCE_EXTENSION_CLASS (class);
+ extension_class->name = E_SOURCE_EXTENSION_MEMO_LIST;
+}
+
+static void
+e_source_memo_list_init (ESourceMemoList *extension)
+{
+}
+
+static void
+e_source_task_list_class_init (ESourceTaskListClass *class)
+{
+ GObjectClass *object_class;
+ ESourceExtensionClass *extension_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->constructed = source_common_constructed;
+
+ extension_class = E_SOURCE_EXTENSION_CLASS (class);
+ extension_class->name = E_SOURCE_EXTENSION_TASK_LIST;
+}
+
+static void
+e_source_task_list_init (ESourceTaskList *extension)
+{
+}
diff --git a/calendar/libecal/e-source-calendar.h b/calendar/libecal/e-source-calendar.h
new file mode 100644
index 0000000..a7fabea
--- /dev/null
+++ b/calendar/libecal/e-source-calendar.h
@@ -0,0 +1,135 @@
+/*
+ * e-source-calendar.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_CALENDAR_H
+#define E_SOURCE_CALENDAR_H
+
+/* These are trivial but important ESourceSelectable subclasses.
+ * They identify an ESource as a calendar, memo list or task list. */
+
+#include <libedataserver/e-source-selectable.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_CALENDAR \
+ (e_source_calendar_get_type ())
+#define E_SOURCE_CALENDAR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_CALENDAR, ESourceCalendar))
+#define E_SOURCE_CALENDAR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_CALENDAR, ESourceCalendarClass))
+#define E_IS_SOURCE_CALENDAR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_CALENDAR))
+#define E_IS_SOURCE_CALENDAR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_CALENDAR))
+#define E_SOURCE_CALENDAR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_CALENDAR, ESourceCalendarClass))
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_MEMO_LIST \
+ (e_source_memo_list_get_type ())
+#define E_SOURCE_MEMO_LIST(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_MEMO_LIST, ESourceMemoList))
+#define E_SOURCE_MEMO_LIST_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_MEMO_LIST, ESourceMemoListClass))
+#define E_IS_SOURCE_MEMO_LIST(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_MEMO_LIST))
+#define E_IS_SOURCE_MEMO_LIST_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_MEMO_LIST))
+#define E_SOURCE_MEMO_LIST_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_MEMO_LIST, ESourceMemoListClass))
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_TASK_LIST \
+ (e_source_task_list_get_type ())
+#define E_SOURCE_TASK_LIST(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_TASK_LIST, ESourceTaskList))
+#define E_SOURCE_TASK_LIST_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_TASK_LIST, ESourceTaskListClass))
+#define E_IS_SOURCE_TASK_LIST(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_TASK_LIST))
+#define E_IS_SOURCE_TASK_LIST_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_TASK_LIST))
+#define E_SOURCE_TASK_LIST_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_TASK_LIST, ESourceTaskListClass))
+
+#define E_SOURCE_EXTENSION_CALENDAR "Calendar"
+#define E_SOURCE_EXTENSION_MEMO_LIST "Memo List"
+#define E_SOURCE_EXTENSION_TASK_LIST "Task List"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceCalendar ESourceCalendar;
+typedef struct _ESourceCalendarClass ESourceCalendarClass;
+typedef struct _ESourceCalendarPrivate ESourceCalendarPrivate;
+
+typedef struct _ESourceMemoList ESourceMemoList;
+typedef struct _ESourceMemoListClass ESourceMemoListClass;
+typedef struct _ESourceMemoListPrivate ESourceMemoListPrivate;
+
+typedef struct _ESourceTaskList ESourceTaskList;
+typedef struct _ESourceTaskListClass ESourceTaskListClass;
+typedef struct _ESourceTaskListPrivate ESourceTaskListPrivate;
+
+struct _ESourceCalendar {
+ ESourceSelectable parent;
+ ESourceCalendarPrivate *priv;
+};
+
+struct _ESourceCalendarClass {
+ ESourceSelectableClass parent_class;
+};
+
+struct _ESourceMemoList {
+ ESourceSelectable parent;
+ ESourceMemoListPrivate *priv;
+};
+
+struct _ESourceMemoListClass {
+ ESourceSelectableClass parent_class;
+};
+
+struct _ESourceTaskList {
+ ESourceSelectable parent;
+ ESourceTaskListPrivate *priv;
+};
+
+struct _ESourceTaskListClass {
+ ESourceSelectableClass parent_class;
+};
+
+GType e_source_calendar_get_type (void);
+GType e_source_memo_list_get_type (void);
+GType e_source_task_list_get_type (void);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_CALENDAR_H */
diff --git a/configure.ac b/configure.ac
index 368834c..2dca9da 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1179,7 +1179,7 @@ AC_DEFUN([EVO_SET_COMPILE_FLAGS], [
dnl ******************************
dnl libedataserver flags
dnl ******************************
-E_DATA_SERVER_DEPS="gio-2.0 libxml-2.0 libsoup-2.4 gconf-2.0 $mozilla_nspr"
+E_DATA_SERVER_DEPS="gio-2.0 gnome-keyring-1 libxml-2.0 libsoup-2.4 gconf-2.0 $mozilla_nspr"
EVO_SET_COMPILE_FLAGS(E_DATA_SERVER, $E_DATA_SERVER_DEPS, $MANUAL_NSPR_CFLAGS, $MANUAL_NSPR_LIBS)
AC_SUBST(E_DATA_SERVER_CFLAGS)
diff --git a/docs/reference/addressbook/libebook/libebook-docs.sgml b/docs/reference/addressbook/libebook/libebook-docs.sgml
index aef65b4..7bfcd83 100644
--- a/docs/reference/addressbook/libebook/libebook-docs.sgml
+++ b/docs/reference/addressbook/libebook/libebook-docs.sgml
@@ -19,6 +19,7 @@
<xi:include href="xml/e-destination.xml"/>
<xi:include href="xml/e-address-western.xml"/>
<xi:include href="xml/e-name-western.xml"/>
+ <xi:include href="xml/e-source-address-book.xml"/>
</chapter>
<index id="api-index-full">
diff --git a/docs/reference/addressbook/libebook/libebook-sections.txt b/docs/reference/addressbook/libebook/libebook-sections.txt
index c13e406..7352302 100644
--- a/docs/reference/addressbook/libebook/libebook-sections.txt
+++ b/docs/reference/addressbook/libebook/libebook-sections.txt
@@ -409,3 +409,22 @@ E_DESTINATION_GET_CLASS
E_IS_DESTINATION
E_IS_DESTINATION_CLASS
</SECTION>
+
+<SECTION>
+<FILE>e-source-address-book</FILE>
+<TITLE>ESourceAddressBook</TITLE>
+ESourceAddressBook
+E_SOURCE_EXTENSION_ADDRESS_BOOK
+<SUBSECTION Standard>
+E_SOURCE_ADDRESS_BOOK
+E_IS_SOURCE_ADDRESS_BOOK
+E_TYPE_SOURCE_ADDRESS_BOOK
+E_SOURCE_ADDRESS_BOOK_CLASS
+E_IS_SOURCE_ADDRESS_BOOK_CLASS
+E_SOURCE_ADDRESS_BOOK_GET_CLASS
+ESourceAddressBookClass
+<SUBSECTION Private>
+ESourceAddressBookPrivate
+e_source_address_book_get_type
+</SECTION>
+
diff --git a/docs/reference/addressbook/libebook/libebook.types b/docs/reference/addressbook/libebook/libebook.types
index 4dd5f9f..c331ec8 100644
--- a/docs/reference/addressbook/libebook/libebook.types
+++ b/docs/reference/addressbook/libebook/libebook.types
@@ -3,9 +3,11 @@
#include <libebook/e-contact.h>
#include <libebook/e-destination.h>
#include <libebook/e-vcard.h>
+#include <libebook/e-source-address-book.h>
e_book_get_type
e_book_view_get_type
e_contact_get_type
e_destination_get_type
e_vcard_get_type
+e_source_address_book_get_type
diff --git a/docs/reference/addressbook/libebook/tmpl/e-book.sgml b/docs/reference/addressbook/libebook/tmpl/e-book.sgml
index 2d7a8fe..7b34c99 100644
--- a/docs/reference/addressbook/libebook/tmpl/e-book.sgml
+++ b/docs/reference/addressbook/libebook/tmpl/e-book.sgml
@@ -401,16 +401,6 @@ The writable status for this book is being reported.
@Returns:
-<!-- ##### FUNCTION e_book_get_addressbooks ##### -->
-<para>
-
-</para>
-
- addressbook_sources:
- error:
- Returns:
-
-
<!-- ##### MACRO e_return_error_if_fail ##### -->
<para>
diff --git a/docs/reference/addressbook/libebook/tmpl/e-source-address-book.sgml b/docs/reference/addressbook/libebook/tmpl/e-source-address-book.sgml
new file mode 100644
index 0000000..8384390
--- /dev/null
+++ b/docs/reference/addressbook/libebook/tmpl/e-source-address-book.sgml
@@ -0,0 +1,35 @@
+<!-- ##### SECTION Title ##### -->
+ESourceAddressBook
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceAddressBook ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_SOURCE_EXTENSION_ADDRESS_BOOK ##### -->
+<para>
+
+</para>
+
+
+
diff --git a/docs/reference/addressbook/libebook/tmpl/libebook-unused.sgml b/docs/reference/addressbook/libebook/tmpl/libebook-unused.sgml
index 416a567..e8fe0b8 100644
--- a/docs/reference/addressbook/libebook/tmpl/libebook-unused.sgml
+++ b/docs/reference/addressbook/libebook/tmpl/libebook-unused.sgml
@@ -493,6 +493,15 @@ Data sent back to the e-book object.
@book:
+<!-- ##### FUNCTION e_book_get_addressbooks ##### -->
+<para>
+
+</para>
+
+ addressbook_sources:
+ error:
+ Returns:
+
<!-- ##### FUNCTION e_book_get_default_addressbook ##### -->
<para>
diff --git a/docs/reference/calendar/libecal/libecal-docs.sgml b/docs/reference/calendar/libecal/libecal-docs.sgml
index c3dd228..09f45fc 100644
--- a/docs/reference/calendar/libecal/libecal-docs.sgml
+++ b/docs/reference/calendar/libecal/libecal-docs.sgml
@@ -19,6 +19,9 @@
<xi:include href="xml/e-cal-util.xml"/>
<xi:include href="xml/e-cal-system-timezone.xml"/>
<xi:include href="xml/e-cal-check-timezones.xml"/>
+ <xi:include href="xml/e-source-calendar.xml"/>
+ <xi:include href="xml/e-source-memo-list.xml"/>
+ <xi:include href="xml/e-source-task-list.xml"/>
</chapter>
<index id="api-index-full">
diff --git a/docs/reference/calendar/libecal/libecal-sections.txt b/docs/reference/calendar/libecal/libecal-sections.txt
index 77f88b4..54d645f 100644
--- a/docs/reference/calendar/libecal/libecal-sections.txt
+++ b/docs/reference/calendar/libecal/libecal-sections.txt
@@ -232,7 +232,6 @@ e_cal_get_error_message
e_cal_open_default
e_cal_set_default
e_cal_set_default_source
-e_cal_get_sources
e_cal_get_local_attachment_store
e_cal_get_recurrences_no_master
e_cal_get_attachments_for_comp
@@ -391,3 +390,57 @@ e_cal_tzlookup_ecal
e_cal_tzlookup_icomp
e_cal_match_tzid
</SECTION>
+
+<SECTION>
+<FILE>e-source-calendar</FILE>
+<TITLE>ESourceCalendar</TITLE>
+ESourceCalendar
+E_SOURCE_EXTENSION_CALENDAR
+<SUBSECTION Standard>
+E_SOURCE_CALENDAR
+E_IS_SOURCE_CALENDAR
+E_TYPE_SOURCE_CALENDAR
+E_SOURCE_CALENDAR_CLASS
+E_IS_SOURCE_CALENDAR_CLASS
+E_SOURCE_CALENDAR_GET_CLASS
+ESourceCalendarClass
+<SUBSECTION Private>
+ESourceCalendarPrivate
+e_source_calendar_get_type
+</SECTION>
+
+<SECTION>
+<FILE>e-source-memo-list</FILE>
+<TITLE>ESourceMemoList</TITLE>
+ESourceMemoList
+E_SOURCE_EXTENSION_MEMO_LIST
+<SUBSECTION Standard>
+E_SOURCE_MEMO_LIST
+E_IS_SOURCE_MEMO_LIST
+E_TYPE_SOURCE_MEMO_LIST
+E_SOURCE_MEMO_LIST_CLASS
+E_IS_SOURCE_MEMO_LIST_CLASS
+E_SOURCE_MEMO_LIST_GET_CLASS
+ESourceMemoListClass
+<SUBSECTION Private>
+ESourceMemoListPrivate
+e_source_memo_list_get_type
+</SECTION>
+
+<SECTION>
+<FILE>e-source-task-list</FILE>
+<TITLE>ESourceTaskList</TITLE>
+ESourceTaskList
+E_SOURCE_EXTENSION_TASK_LIST
+<SUBSECTION Standard>
+E_SOURCE_TASK_LIST
+E_IS_SOURCE_TASK_LIST
+E_TYPE_SOURCE_TASK_LIST
+E_SOURCE_TASK_LIST_CLASS
+E_IS_SOURCE_TASK_LIST_CLASS
+E_SOURCE_TASK_LIST_GET_CLASS
+ESourceTaskListClass
+<SUBSECTION Private>
+ESourceTaskListPrivate
+e_source_task_list_get_type
+</SECTION>
diff --git a/docs/reference/calendar/libecal/libecal.types b/docs/reference/calendar/libecal/libecal.types
index 1286092..c32c6bb 100644
--- a/docs/reference/calendar/libecal/libecal.types
+++ b/docs/reference/calendar/libecal/libecal.types
@@ -1,7 +1,11 @@
#include <libecal/e-cal.h>
#include <libecal/e-cal-component.h>
#include <libecal/e-cal-view.h>
+#include <libecal/e-source-calendar.h>
e_cal_get_type
e_cal_component_get_type
e_cal_view_get_type
+e_source_calendar_get_type
+e_source_memo_list_get_type
+e_source_task_list_get_type
diff --git a/docs/reference/calendar/libecal/tmpl/e-cal.sgml b/docs/reference/calendar/libecal/tmpl/e-cal.sgml
index 231c89c..f360005 100644
--- a/docs/reference/calendar/libecal/tmpl/e-cal.sgml
+++ b/docs/reference/calendar/libecal/tmpl/e-cal.sgml
@@ -711,17 +711,6 @@ Represents an entire calendar or task list, not individual items within them.2
@Returns:
-<!-- ##### FUNCTION e_cal_get_sources ##### -->
-<para>
-
-</para>
-
- sources:
- type:
- error:
- Returns:
-
-
<!-- ##### FUNCTION e_cal_get_local_attachment_store ##### -->
<para>
diff --git a/docs/reference/calendar/libecal/tmpl/e-source-calendar.sgml b/docs/reference/calendar/libecal/tmpl/e-source-calendar.sgml
new file mode 100644
index 0000000..b1aa2fc
--- /dev/null
+++ b/docs/reference/calendar/libecal/tmpl/e-source-calendar.sgml
@@ -0,0 +1,35 @@
+<!-- ##### SECTION Title ##### -->
+ESourceCalendar
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceCalendar ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_SOURCE_EXTENSION_CALENDAR ##### -->
+<para>
+
+</para>
+
+
+
diff --git a/docs/reference/calendar/libecal/tmpl/e-source-memo-list.sgml b/docs/reference/calendar/libecal/tmpl/e-source-memo-list.sgml
new file mode 100644
index 0000000..a582fa7
--- /dev/null
+++ b/docs/reference/calendar/libecal/tmpl/e-source-memo-list.sgml
@@ -0,0 +1,35 @@
+<!-- ##### SECTION Title ##### -->
+ESourceMemoList
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceMemoList ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_SOURCE_EXTENSION_MEMO_LIST ##### -->
+<para>
+
+</para>
+
+
+
diff --git a/docs/reference/calendar/libecal/tmpl/e-source-memo_list.sgml b/docs/reference/calendar/libecal/tmpl/e-source-memo_list.sgml
new file mode 100644
index 0000000..a582fa7
--- /dev/null
+++ b/docs/reference/calendar/libecal/tmpl/e-source-memo_list.sgml
@@ -0,0 +1,35 @@
+<!-- ##### SECTION Title ##### -->
+ESourceMemoList
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceMemoList ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_SOURCE_EXTENSION_MEMO_LIST ##### -->
+<para>
+
+</para>
+
+
+
diff --git a/docs/reference/calendar/libecal/tmpl/e-source-task-list.sgml b/docs/reference/calendar/libecal/tmpl/e-source-task-list.sgml
new file mode 100644
index 0000000..9cb620b
--- /dev/null
+++ b/docs/reference/calendar/libecal/tmpl/e-source-task-list.sgml
@@ -0,0 +1,35 @@
+<!-- ##### SECTION Title ##### -->
+ESourceTaskList
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceTaskList ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_SOURCE_EXTENSION_TASK_LIST ##### -->
+<para>
+
+</para>
+
+
+
diff --git a/docs/reference/calendar/libecal/tmpl/e-source-task_list.sgml b/docs/reference/calendar/libecal/tmpl/e-source-task_list.sgml
new file mode 100644
index 0000000..9cb620b
--- /dev/null
+++ b/docs/reference/calendar/libecal/tmpl/e-source-task_list.sgml
@@ -0,0 +1,35 @@
+<!-- ##### SECTION Title ##### -->
+ESourceTaskList
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceTaskList ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_SOURCE_EXTENSION_TASK_LIST ##### -->
+<para>
+
+</para>
+
+
+
diff --git a/docs/reference/calendar/libecal/tmpl/libecal-unused.sgml b/docs/reference/calendar/libecal/tmpl/libecal-unused.sgml
index df0f1a7..b77d556 100644
--- a/docs/reference/calendar/libecal/tmpl/libecal-unused.sgml
+++ b/docs/reference/calendar/libecal/tmpl/libecal-unused.sgml
@@ -46,6 +46,62 @@ Listens for responses and event notifications sent by #e-cal-view.
ECalViewListener
+<!-- ##### SECTION ./tmpl/e-source-memo_list.sgml:Image ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/e-source-memo_list.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/e-source-memo_list.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/e-source-memo_list.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/e-source-memo_list.sgml:Stability_Level ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/e-source-memo_list.sgml:Title ##### -->
+ESourceMemoList
+
+
+<!-- ##### SECTION ./tmpl/e-source-task_list.sgml:Image ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/e-source-task_list.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/e-source-task_list.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/e-source-task_list.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/e-source-task_list.sgml:Stability_Level ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/e-source-task_list.sgml:Title ##### -->
+ESourceTaskList
+
+
<!-- ##### SECTION ./tmpl/libecal-unused.sgml:Stability_Level ##### -->
@@ -516,14 +572,6 @@ ECalViewListener
@error:
@Returns:
-<!-- ##### FUNCTION e_cal_get_uri ##### -->
-<para>
-
-</para>
-
- ecal:
- Returns:
-
<!-- ##### FUNCTION e_cal_listener_construct ##### -->
<para>
diff --git a/docs/reference/libedataserver/Makefile.am b/docs/reference/libedataserver/Makefile.am
index 176a76c..2f5b531 100644
--- a/docs/reference/libedataserver/Makefile.am
+++ b/docs/reference/libedataserver/Makefile.am
@@ -14,6 +14,7 @@ DOC_SOURCE_DIR = $(top_srcdir)/libedataserver
HFILE_GLOB = $(top_srcdir)/libedataserver/*.h
CFILE_GLOB = $(top_srcdir)/libedataserver/*.c
IGNORE_HFILES = \
+ e-marshal.h \
libedataserver-private.h
GTKDOC_CFLAGS = \
diff --git a/docs/reference/libedataserver/libedataserver-docs.sgml b/docs/reference/libedataserver/libedataserver-docs.sgml
index 11e8df0..61e45e7 100644
--- a/docs/reference/libedataserver/libedataserver-docs.sgml
+++ b/docs/reference/libedataserver/libedataserver-docs.sgml
@@ -23,6 +23,17 @@
<xi:include href="xml/e-sexp.xml"/>
<xi:include href="xml/e-soap-message.xml"/>
<xi:include href="xml/e-source.xml"/>
+ <xi:include href="xml/e-source-password.xml"/>
+ <xi:include href="xml/e-source-registry.xml"/>
+ <xi:include href="xml/e-source-extension.xml"/>
+ <xi:include href="xml/e-source-alarms.xml"/>
+ <xi:include href="xml/e-source-authentication.xml"/>
+ <xi:include href="xml/e-source-autocomplete.xml"/>
+ <xi:include href="xml/e-source-offline.xml"/>
+ <xi:include href="xml/e-source-refresh.xml"/>
+ <xi:include href="xml/e-source-security.xml"/>
+ <xi:include href="xml/e-source-selectable.xml"/>
+ <xi:include href="xml/e-source-webdav.xml"/>
<xi:include href="xml/e-time-utils.xml"/>
<xi:include href="xml/e-uid.xml"/>
<xi:include href="xml/e-util.xml"/>
@@ -39,6 +50,10 @@
<title>Index of deprecated symbols</title>
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
</index>
+ <index id="api-index-2.92" role="2.92">
+ <title>Index of new symbols in 2.92</title>
+ <xi:include href="xml/api-index-2.92.xml"><xi:fallback /></xi:include>
+ </index>
<index id="api-index-2.32" role="2.32">
<title>Index of new symbols in 2.32</title>
<xi:include href="xml/api-index-2.32.xml"><xi:fallback /></xi:include>
diff --git a/docs/reference/libedataserver/libedataserver-sections.txt b/docs/reference/libedataserver/libedataserver-sections.txt
index 4cf7f11..486b095 100644
--- a/docs/reference/libedataserver/libedataserver-sections.txt
+++ b/docs/reference/libedataserver/libedataserver-sections.txt
@@ -189,41 +189,31 @@ e_proxy_get_type
<TITLE>ESource</TITLE>
ESource
e_source_new
-e_source_new_with_absolute_uri
-e_source_new_from_xml_node
-e_source_new_from_standalone_xml
-e_source_copy
-e_source_update_from_xml_node
-e_source_uid_from_xml_node
-e_source_set_group
-e_source_set_name
-e_source_set_relative_uri
-e_source_set_absolute_uri
-e_source_set_color_spec
-e_source_set_readonly
-e_source_peek_group
-e_source_peek_uid
-e_source_peek_name
-e_source_peek_relative_uri
-e_source_peek_absolute_uri
-e_source_peek_color_spec
-e_source_get_readonly
-e_source_get_uri
-e_source_dump_to_xml_node
-e_source_to_standalone_xml
-e_source_get_property
-e_source_set_property
-e_source_foreach_property
-e_source_get_duped_property
-e_source_build_absolute_uri
+e_source_hash
e_source_equal
-e_source_xmlstr_equal
+e_source_sync
+e_source_reload
+e_source_changed
+e_source_redirect
+e_source_get_uid
+e_source_get_file
+e_source_get_node
+e_source_get_parent
+e_source_set_parent
+e_source_get_extension
+e_source_has_extension
+e_source_get_backend_name
+e_source_set_backend_name
+e_source_get_display_name
+e_source_set_display_name
+e_source_compare_by_display_name
<SUBSECTION Standard>
E_SOURCE
E_IS_SOURCE
E_TYPE_SOURCE
E_SOURCE_CLASS
E_IS_SOURCE_CLASS
+E_SOURCE_GET_CLASS
ESourceClass
<SUBSECTION Private>
ESourcePrivate
@@ -231,6 +221,261 @@ e_source_get_type
</SECTION>
<SECTION>
+<FILE>e-source-alarms</FILE>
+<TITLE>ESourceAlarms</TITLE>
+ESourceAlarms
+E_SOURCE_EXTENSION_ALARMS
+e_source_alarms_get_include_me
+e_source_alarms_set_include_me
+e_source_alarms_get_last_notified
+e_source_alarms_set_last_notified
+<SUBSECTION Standard>
+E_SOURCE_ALARMS
+E_IS_SOURCE_ALARMS
+E_TYPE_SOURCE_ALARMS
+E_SOURCE_ALARMS_CLASS
+E_IS_SOURCE_ALARMS_CLASS
+E_SOURCE_ALARMS_GET_CLASS
+ESourceAlarmsClass
+<SUBSECTION Private>
+ESourceAlarmsPrivate
+e_source_alarms_get_type
+</SECTION>
+
+<SECTION>
+<FILE>e-source-authentication</FILE>
+<TITLE>ESourceAuthentication</TITLE>
+ESourceAuthentication
+E_SOURCE_EXTENSION_AUTHENTICATION
+e_source_authentication_required
+e_source_authentication_get_domain
+e_source_authentication_set_domain
+e_source_authentication_get_host
+e_source_authentication_set_host
+e_source_authentication_get_method
+e_source_authentication_set_method
+e_source_authentication_get_port
+e_source_authentication_set_port
+e_source_authentication_get_remember_password
+e_source_authentication_set_remember_password
+e_source_authentication_get_user
+e_source_authentication_set_user
+<SUBSECTION Standard>
+E_SOURCE_AUTHENTICATION
+E_IS_SOURCE_AUTHENTICATION
+E_TYPE_SOURCE_AUTHENTICATION
+E_SOURCE_AUTHENTICATION_CLASS
+E_IS_SOURCE_AUTHENTICATION_CLASS
+E_SOURCE_AUTHENTICATION_GET_CLASS
+ESourceAuthenticationClass
+<SUBSECTION Private>
+ESourceAuthenticationPrivate
+e_source_authentication_get_type
+</SECTION>
+
+<SECTION>
+<FILE>e-source-autocomplete</FILE>
+<TITLE>ESourceAutocomplete</TITLE>
+ESourceAutocomplete
+E_SOURCE_EXTENSION_AUTOCOMPLETE
+e_source_autocomplete_get_include_me
+e_source_autocomplete_set_include_me
+<SUBSECTION Standard>
+E_SOURCE_AUTOCOMPLETE
+E_IS_SOURCE_AUTOCOMPLETE
+E_TYPE_SOURCE_AUTOCOMPLETE
+E_SOURCE_AUTOCOMPLETE_CLASS
+E_IS_SOURCE_AUTOCOMPLETE_CLASS
+E_SOURCE_AUTOCOMPLETE_GET_CLASS
+ESourceAutocompleteClass
+<SUBSECTION Private>
+ESourceAutocompletePrivate
+e_source_autocomplete_get_type
+</SECTION>
+
+<SECTION>
+<FILE>e-source-extension</FILE>
+<TITLE>ESourceExtension</TITLE>
+ESourceExtension
+E_SOURCE_PARAM_SETTING
+e_source_extension_get_source
+<SUBSECTION Standard>
+E_SOURCE_EXTENSION
+E_IS_SOURCE_EXTENSION
+E_TYPE_SOURCE_EXTENSION
+E_SOURCE_EXTENSION_CLASS
+E_IS_SOURCE_EXTENSION_CLASS
+E_SOURCE_EXTENSION_GET_CLASS
+ESourceExtensionClass
+<SUBSECTION Private>
+ESourceExtensionPrivate
+e_source_extension_get_type
+</SECTION>
+
+<SECTION>
+<FILE>e-source-offline</FILE>
+<TITLE>ESourceOffline</TITLE>
+ESourceOffline
+E_SOURCE_EXTENSION_OFFLINE
+e_source_offline_get_stay_synchronized
+e_source_offline_set_stay_synchronized
+<SUBSECTION Standard>
+E_SOURCE_OFFLINE
+E_IS_SOURCE_OFFLINE
+E_TYPE_SOURCE_OFFLINE
+E_SOURCE_OFFLINE_CLASS
+E_IS_SOURCE_OFFLINE_CLASS
+E_SOURCE_OFFLINE_GET_CLASS
+ESourceOfflineClass
+<SUBSECTION Private>
+ESourceOfflinePrivate
+e_source_offline_get_type
+</SECTION>
+
+<SECTION>
+<FILE>e-source-password</FILE>
+<TITLE>ESource Passwords</TITLE>
+E_SOURCE_PASSWORD_ERROR
+e_source_password_store
+e_source_password_store_finish
+e_source_password_store_sync
+e_source_password_lookup
+e_source_password_lookup_finish
+e_source_password_lookup_sync
+e_source_password_delete
+e_source_password_delete_finish
+e_source_password_delete_sync
+e_source_password_free
+<SUBSECTION Private>
+e_source_password_error_quark
+</SECTION>
+
+<SECTION>
+<FILE>e-source-refresh</FILE>
+<TITLE>ESourceRefresh</TITLE>
+ESourceRefresh
+E_SOURCE_EXTENSION_REFRESH
+e_source_refresh_get_interval_minutes
+e_source_refresh_set_interval_minutes
+<SUBSECTION Standard>
+E_SOURCE_REFRESH
+E_IS_SOURCE_REFRESH
+E_TYPE_SOURCE_REFRESH
+E_SOURCE_REFRESH_CLASS
+E_IS_SOURCE_REFRESH_CLASS
+E_SOURCE_REFRESH_GET_CLASS
+ESourceRefreshClass
+<SUBSECTION Private>
+ESourceRefreshPrivate
+e_source_refresh_get_type
+</SECTION>
+
+<SECTION>
+<FILE>e-source-registry</FILE>
+<TITLE>ESourceRegistry</TITLE>
+ESourceRegistry
+e_source_registry_get_default
+e_source_registry_add_source
+e_source_registry_remove_source
+e_source_registry_load_sources
+e_source_registry_load_directory
+e_source_registry_load_file
+e_source_registry_load_error
+e_source_registry_lookup_by_file
+e_source_registry_lookup_by_uid
+e_source_registry_list_sources
+e_source_registry_build_display_tree
+e_source_registry_get_default_address_book
+e_source_registry_set_default_address_book
+e_source_registry_get_default_calendar
+e_source_registry_set_default_calendar
+e_source_registry_get_default_memo_list
+e_source_registry_set_default_memo_list
+e_source_registry_get_default_task_list
+e_source_registry_set_default_task_list
+<SUBSECTION Standard>
+E_SOURCE_REGISTRY
+E_IS_SOURCE_REGISTRY
+E_TYPE_SOURCE_REGISTRY
+E_SOURCE_REGISTRY_CLASS
+E_IS_SOURCE_REGISTRY_CLASS
+E_SOURCE_REGISTRY_GET_CLASS
+ESourceRegistryClass
+<SUBSECTION Private>
+ESourceRegistryPrivate
+e_source_registry_get_type
+</SECTION>
+
+<SECTION>
+<FILE>e-source-security</FILE>
+<TITLE>ESourceSecurity</TITLE>
+ESourceSecurity
+E_SOURCE_EXTENSION_SECURITY
+e_source_security_get_method
+e_source_security_set_method
+e_source_security_get_secure
+e_source_security_set_secure
+<SUBSECTION Standard>
+E_SOURCE_SECURITY
+E_IS_SOURCE_SECURITY
+E_TYPE_SOURCE_SECURITY
+E_SOURCE_SECURITY_CLASS
+E_IS_SOURCE_SECURITY_CLASS
+E_SOURCE_SECURITY_GET_CLASS
+ESourceSecurityClass
+<SUBSECTION Private>
+ESourceSecurityPrivate
+e_source_security_get_type
+</SECTION>
+
+<SECTION>
+<FILE>e-source-selectable</FILE>
+<TITLE>ESourceSelectable</TITLE>
+ESourceSelectable
+e_source_selectable_get_color
+e_source_selectable_set_color
+e_source_selectable_get_enabled
+e_source_selectable_set_enabled
+e_source_selectable_get_writable_hint
+e_source_selectable_set_writable_hint
+<SUBSECTION Standard>
+E_SOURCE_SELECTABLE
+E_IS_SOURCE_SELECTABLE
+E_TYPE_SOURCE_SELECTABLE
+E_SOURCE_SELECTABLE_CLASS
+E_IS_SOURCE_SELECTABLE_CLASS
+E_SOURCE_SELECTABLE_GET_CLASS
+ESourceSelectableClass
+<SUBSECTION Private>
+ESourceSelectablePrivate
+e_source_selectable_get_type
+</SECTION>
+
+<SECTION>
+<FILE>e-source-webdav</FILE>
+<TITLE>ESourceWebdav</TITLE>
+ESourceWebdav
+E_SOURCE_EXTENSION_WEBDAV_BACKEND
+e_source_webdav_get_display_name
+e_source_webdav_set_display_name
+e_source_webdav_get_soup_uri
+e_source_webdav_set_soup_uri
+e_source_webdav_get_avoid_ifmatch
+e_source_webdav_set_avoid_ifmatch
+<SUBSECTION Standard>
+E_SOURCE_WEBDAV
+E_IS_SOURCE_WEBDAV
+E_TYPE_SOURCE_WEBDAV
+E_SOURCE_WEBDAV_CLASS
+E_IS_SOURCE_WEBDAV_CLASS
+E_SOURCE_WEBDAV_GET_CLASS
+ESourceWebdavClass
+<SUBSECTION Private>
+ESourceWebdavPrivate
+e_source_webdav_get_type
+</SECTION>
+
+<SECTION>
<FILE>e-categories</FILE>
e_categories_get_list
e_categories_add
diff --git a/docs/reference/libedataserver/libedataserver.types b/docs/reference/libedataserver/libedataserver.types
index 89ce70f..b07e098 100644
--- a/docs/reference/libedataserver/libedataserver.types
+++ b/docs/reference/libedataserver/libedataserver.types
@@ -4,6 +4,13 @@
#include <libedataserver/e-list.h>
#include <libedataserver/e-list-iterator.h>
#include <libedataserver/e-source.h>
+#include <libedataserver/e-source-authentication.h>
+#include <libedataserver/e-source-extension.h>
+#include <libedataserver/e-source-offline.h>
+#include <libedataserver/e-source-refresh.h>
+#include <libedataserver/e-source-registry.h>
+#include <libedataserver/e-source-security.h>
+#include <libedataserver/e-source-selectable.h>
e_account_get_type
e_account_list_get_type
@@ -11,3 +18,10 @@ e_iterator_get_type
e_list_get_type
e_list_iterator_get_type
e_source_get_type
+e_source_authentication_get_type
+e_source_extension_get_type
+e_source_offline_get_type
+e_source_refresh_get_type
+e_source_registry_get_type
+e_source_security_get_type
+e_source_selectable_get_type
diff --git a/docs/reference/libedataserver/tmpl/e-source-alarms.sgml b/docs/reference/libedataserver/tmpl/e-source-alarms.sgml
new file mode 100644
index 0000000..4e519fd
--- /dev/null
+++ b/docs/reference/libedataserver/tmpl/e-source-alarms.sgml
@@ -0,0 +1,71 @@
+<!-- ##### SECTION Title ##### -->
+ESourceAlarm
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceAlarms ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_SOURCE_EXTENSION_ALARMS ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION e_source_alarms_get_include_me ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_alarms_set_include_me ##### -->
+<para>
+
+</para>
+
+ extension:
+ include_me:
+
+
+<!-- ##### FUNCTION e_source_alarms_get_last_notified ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_alarms_set_last_notified ##### -->
+<para>
+
+</para>
+
+ extension:
+ last_notified:
+
+
diff --git a/docs/reference/libedataserver/tmpl/e-source-authentication.sgml b/docs/reference/libedataserver/tmpl/e-source-authentication.sgml
new file mode 100644
index 0000000..4b66f0c
--- /dev/null
+++ b/docs/reference/libedataserver/tmpl/e-source-authentication.sgml
@@ -0,0 +1,182 @@
+<!-- ##### SECTION Title ##### -->
+ESourceAuthentication
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceAuthentication ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG ESourceAuthentication:domain ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG ESourceAuthentication:host ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG ESourceAuthentication:method ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG ESourceAuthentication:port ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG ESourceAuthentication:remember-password ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG ESourceAuthentication:user ##### -->
+<para>
+
+</para>
+
+<!-- ##### MACRO E_SOURCE_EXTENSION_AUTHENTICATION ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION e_source_authentication_required ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_authentication_get_domain ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_authentication_set_domain ##### -->
+<para>
+
+</para>
+
+ extension:
+ domain:
+
+
+<!-- ##### FUNCTION e_source_authentication_get_host ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_authentication_set_host ##### -->
+<para>
+
+</para>
+
+ extension:
+ host:
+
+
+<!-- ##### FUNCTION e_source_authentication_get_method ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_authentication_set_method ##### -->
+<para>
+
+</para>
+
+ extension:
+ method:
+
+
+<!-- ##### FUNCTION e_source_authentication_get_port ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_authentication_set_port ##### -->
+<para>
+
+</para>
+
+ extension:
+ port:
+
+
+<!-- ##### FUNCTION e_source_authentication_get_remember_password ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_authentication_set_remember_password ##### -->
+<para>
+
+</para>
+
+ extension:
+ remember_password:
+
+
+<!-- ##### FUNCTION e_source_authentication_get_user ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_authentication_set_user ##### -->
+<para>
+
+</para>
+
+ extension:
+ user:
+
+
diff --git a/docs/reference/libedataserver/tmpl/e-source-autocomplete.sgml b/docs/reference/libedataserver/tmpl/e-source-autocomplete.sgml
new file mode 100644
index 0000000..6f2ecbf
--- /dev/null
+++ b/docs/reference/libedataserver/tmpl/e-source-autocomplete.sgml
@@ -0,0 +1,53 @@
+<!-- ##### SECTION Title ##### -->
+ESourceAutocomplete
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceAutocomplete ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_SOURCE_EXTENSION_AUTOCOMPLETE ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION e_source_autocomplete_get_include_me ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_autocomplete_set_include_me ##### -->
+<para>
+
+</para>
+
+ extension:
+ include_me:
+
+
diff --git a/docs/reference/libedataserver/tmpl/e-source-extension.sgml b/docs/reference/libedataserver/tmpl/e-source-extension.sgml
new file mode 100644
index 0000000..61ac733
--- /dev/null
+++ b/docs/reference/libedataserver/tmpl/e-source-extension.sgml
@@ -0,0 +1,49 @@
+<!-- ##### SECTION Title ##### -->
+ESourceExtension
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceExtension ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG ESourceExtension:source ##### -->
+<para>
+
+</para>
+
+<!-- ##### MACRO E_SOURCE_PARAM_SETTING ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION e_source_extension_get_source ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
diff --git a/docs/reference/libedataserver/tmpl/e-source-offline.sgml b/docs/reference/libedataserver/tmpl/e-source-offline.sgml
new file mode 100644
index 0000000..ce1a005
--- /dev/null
+++ b/docs/reference/libedataserver/tmpl/e-source-offline.sgml
@@ -0,0 +1,58 @@
+<!-- ##### SECTION Title ##### -->
+ESourceOffline
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceOffline ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG ESourceOffline:stay-synchronized ##### -->
+<para>
+
+</para>
+
+<!-- ##### MACRO E_SOURCE_EXTENSION_OFFLINE ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION e_source_offline_get_stay_synchronized ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_offline_set_stay_synchronized ##### -->
+<para>
+
+</para>
+
+ extension:
+ stay_synchronized:
+
+
diff --git a/docs/reference/libedataserver/tmpl/e-source-password.sgml b/docs/reference/libedataserver/tmpl/e-source-password.sgml
new file mode 100644
index 0000000..485bd71
--- /dev/null
+++ b/docs/reference/libedataserver/tmpl/e-source-password.sgml
@@ -0,0 +1,145 @@
+<!-- ##### SECTION Title ##### -->
+ESource Passwords
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### MACRO E_SOURCE_PASSWORD_ERROR ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION e_source_password_store ##### -->
+<para>
+
+</para>
+
+ source:
+ password:
+ permanently:
+ io_priority:
+ cancellable:
+ callback:
+ user_data:
+
+
+<!-- ##### FUNCTION e_source_password_store_finish ##### -->
+<para>
+
+</para>
+
+ source:
+ result:
+ error:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_password_store_sync ##### -->
+<para>
+
+</para>
+
+ source:
+ password:
+ permanently:
+ cancellable:
+ error:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_password_lookup ##### -->
+<para>
+
+</para>
+
+ source:
+ io_priority:
+ cancellable:
+ callback:
+ user_data:
+
+
+<!-- ##### FUNCTION e_source_password_lookup_finish ##### -->
+<para>
+
+</para>
+
+ source:
+ result:
+ password:
+ error:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_password_lookup_sync ##### -->
+<para>
+
+</para>
+
+ source:
+ cancellable:
+ password:
+ error:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_password_delete ##### -->
+<para>
+
+</para>
+
+ source:
+ io_priority:
+ cancellable:
+ callback:
+ user_data:
+
+
+<!-- ##### FUNCTION e_source_password_delete_finish ##### -->
+<para>
+
+</para>
+
+ source:
+ result:
+ error:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_password_delete_sync ##### -->
+<para>
+
+</para>
+
+ source:
+ cancellable:
+ error:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_password_free ##### -->
+<para>
+
+</para>
+
+ password:
+
+
diff --git a/docs/reference/libedataserver/tmpl/e-source-refresh.sgml b/docs/reference/libedataserver/tmpl/e-source-refresh.sgml
new file mode 100644
index 0000000..5b3201b
--- /dev/null
+++ b/docs/reference/libedataserver/tmpl/e-source-refresh.sgml
@@ -0,0 +1,58 @@
+<!-- ##### SECTION Title ##### -->
+ESourceRefresh
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceRefresh ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG ESourceRefresh:interval-minutes ##### -->
+<para>
+
+</para>
+
+<!-- ##### MACRO E_SOURCE_EXTENSION_REFRESH ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION e_source_refresh_get_interval_minutes ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_refresh_set_interval_minutes ##### -->
+<para>
+
+</para>
+
+ extension:
+ interval_in_minutes:
+
+
diff --git a/docs/reference/libedataserver/tmpl/e-source-registry.sgml b/docs/reference/libedataserver/tmpl/e-source-registry.sgml
new file mode 100644
index 0000000..8ebda9c
--- /dev/null
+++ b/docs/reference/libedataserver/tmpl/e-source-registry.sgml
@@ -0,0 +1,263 @@
+<!-- ##### SECTION Title ##### -->
+ESourceRegistry
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceRegistry ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SIGNAL ESourceRegistry::load-error ##### -->
+<para>
+
+</para>
+
+ esourceregistry: the object which received the signal.
+ arg1:
+ arg2:
+
+<!-- ##### SIGNAL ESourceRegistry::source-added ##### -->
+<para>
+
+</para>
+
+ esourceregistry: the object which received the signal.
+ arg1:
+
+<!-- ##### SIGNAL ESourceRegistry::source-changed ##### -->
+<para>
+
+</para>
+
+ esourceregistry: the object which received the signal.
+ arg1:
+
+<!-- ##### SIGNAL ESourceRegistry::source-removed ##### -->
+<para>
+
+</para>
+
+ esourceregistry: the object which received the signal.
+ arg1:
+
+<!-- ##### ARG ESourceRegistry:default-address-book ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG ESourceRegistry:default-calendar ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG ESourceRegistry:default-memo-list ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG ESourceRegistry:default-task-list ##### -->
+<para>
+
+</para>
+
+<!-- ##### FUNCTION e_source_registry_get_default ##### -->
+<para>
+
+</para>
+
+ void:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_registry_add_source ##### -->
+<para>
+
+</para>
+
+ registry:
+ source:
+
+
+<!-- ##### FUNCTION e_source_registry_remove_source ##### -->
+<para>
+
+</para>
+
+ registry:
+ source:
+
+
+<!-- ##### FUNCTION e_source_registry_load_sources ##### -->
+<para>
+
+</para>
+
+ registry:
+ error:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_registry_load_directory ##### -->
+<para>
+
+</para>
+
+ registry:
+ path:
+ monitor_for_changes:
+ error:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_registry_load_file ##### -->
+<para>
+
+</para>
+
+ registry:
+ file:
+ error:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_registry_load_error ##### -->
+<para>
+
+</para>
+
+ registry:
+ file:
+ error:
+
+
+<!-- ##### FUNCTION e_source_registry_lookup_by_file ##### -->
+<para>
+
+</para>
+
+ registry:
+ file:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_registry_lookup_by_uid ##### -->
+<para>
+
+</para>
+
+ registry:
+ uid:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_registry_list_sources ##### -->
+<para>
+
+</para>
+
+ registry:
+ extension_name:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_registry_build_display_tree ##### -->
+<para>
+
+</para>
+
+ registry:
+ extension_name:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_registry_get_default_address_book ##### -->
+<para>
+
+</para>
+
+ registry:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_registry_set_default_address_book ##### -->
+<para>
+
+</para>
+
+ registry:
+ default_source:
+
+
+<!-- ##### FUNCTION e_source_registry_get_default_calendar ##### -->
+<para>
+
+</para>
+
+ registry:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_registry_set_default_calendar ##### -->
+<para>
+
+</para>
+
+ registry:
+ default_source:
+
+
+<!-- ##### FUNCTION e_source_registry_get_default_memo_list ##### -->
+<para>
+
+</para>
+
+ registry:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_registry_set_default_memo_list ##### -->
+<para>
+
+</para>
+
+ registry:
+ default_source:
+
+
+<!-- ##### FUNCTION e_source_registry_get_default_task_list ##### -->
+<para>
+
+</para>
+
+ registry:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_registry_set_default_task_list ##### -->
+<para>
+
+</para>
+
+ registry:
+ default_source:
+
+
diff --git a/docs/reference/libedataserver/tmpl/e-source-security.sgml b/docs/reference/libedataserver/tmpl/e-source-security.sgml
new file mode 100644
index 0000000..87aca15
--- /dev/null
+++ b/docs/reference/libedataserver/tmpl/e-source-security.sgml
@@ -0,0 +1,81 @@
+<!-- ##### SECTION Title ##### -->
+ESourceSecurity
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceSecurity ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG ESourceSecurity:method ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG ESourceSecurity:secure ##### -->
+<para>
+
+</para>
+
+<!-- ##### MACRO E_SOURCE_EXTENSION_SECURITY ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION e_source_security_get_method ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_security_set_method ##### -->
+<para>
+
+</para>
+
+ extension:
+ method:
+
+
+<!-- ##### FUNCTION e_source_security_get_secure ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_security_set_secure ##### -->
+<para>
+
+</para>
+
+ extension:
+ secure:
+
+
diff --git a/docs/reference/libedataserver/tmpl/e-source-selectable.sgml b/docs/reference/libedataserver/tmpl/e-source-selectable.sgml
new file mode 100644
index 0000000..bbcce4a
--- /dev/null
+++ b/docs/reference/libedataserver/tmpl/e-source-selectable.sgml
@@ -0,0 +1,97 @@
+<!-- ##### SECTION Title ##### -->
+ESourceSelectable
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceSelectable ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG ESourceSelectable:color ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG ESourceSelectable:enabled ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG ESourceSelectable:writable-hint ##### -->
+<para>
+
+</para>
+
+<!-- ##### FUNCTION e_source_selectable_get_color ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_selectable_set_color ##### -->
+<para>
+
+</para>
+
+ extension:
+ color:
+
+
+<!-- ##### FUNCTION e_source_selectable_get_enabled ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_selectable_set_enabled ##### -->
+<para>
+
+</para>
+
+ extension:
+ enabled:
+
+
+<!-- ##### FUNCTION e_source_selectable_get_writable_hint ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_selectable_set_writable_hint ##### -->
+<para>
+
+</para>
+
+ extension:
+ writable_hint:
+
+
diff --git a/docs/reference/libedataserver/tmpl/e-source-webdav.sgml b/docs/reference/libedataserver/tmpl/e-source-webdav.sgml
new file mode 100644
index 0000000..aa3dce9
--- /dev/null
+++ b/docs/reference/libedataserver/tmpl/e-source-webdav.sgml
@@ -0,0 +1,89 @@
+<!-- ##### SECTION Title ##### -->
+ESourceWebdav
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT ESourceWebdav ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO E_SOURCE_EXTENSION_WEBDAV_BACKEND ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION e_source_webdav_get_display_name ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_webdav_set_display_name ##### -->
+<para>
+
+</para>
+
+ extension:
+ display_name:
+
+
+<!-- ##### FUNCTION e_source_webdav_get_soup_uri ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_webdav_set_soup_uri ##### -->
+<para>
+
+</para>
+
+ extension:
+ uri:
+
+
+<!-- ##### FUNCTION e_source_webdav_get_avoid_ifmatch ##### -->
+<para>
+
+</para>
+
+ extension:
+ Returns:
+
+
+<!-- ##### FUNCTION e_source_webdav_set_avoid_ifmatch ##### -->
+<para>
+
+</para>
+
+ extension:
+ avoid_ifmatch:
+
+
diff --git a/docs/reference/libedataserver/tmpl/e-source.sgml b/docs/reference/libedataserver/tmpl/e-source.sgml
index ec60c8f..504ce9e 100644
--- a/docs/reference/libedataserver/tmpl/e-source.sgml
+++ b/docs/reference/libedataserver/tmpl/e-source.sgml
@@ -33,164 +33,98 @@ ESource
@esource: the object which received the signal.
-<!-- ##### FUNCTION e_source_new ##### -->
+<!-- ##### ARG ESource:backend-name ##### -->
<para>
</para>
- name:
- relative_uri:
- Returns:
-
-
-<!-- ##### FUNCTION e_source_new_with_absolute_uri ##### -->
+<!-- ##### ARG ESource:display-name ##### -->
<para>
</para>
- name:
- absolute_uri:
- Returns:
-
-
-<!-- ##### FUNCTION e_source_new_from_xml_node ##### -->
+<!-- ##### ARG ESource:file ##### -->
<para>
</para>
- node:
- Returns:
-
-
-<!-- ##### FUNCTION e_source_new_from_standalone_xml ##### -->
+<!-- ##### ARG ESource:parent ##### -->
<para>
</para>
- xml:
- Returns:
-
-
-<!-- ##### FUNCTION e_source_copy ##### -->
+<!-- ##### ARG ESource:uid ##### -->
<para>
</para>
- source:
- Returns:
-
-
-<!-- ##### FUNCTION e_source_update_from_xml_node ##### -->
-<para>
-
-</para>
-
- source:
- node:
- changed_return:
- Returns:
-
-
-<!-- ##### FUNCTION e_source_uid_from_xml_node ##### -->
+<!-- ##### FUNCTION e_source_new ##### -->
<para>
</para>
- node:
+ file:
+ error:
@Returns:
-<!-- ##### FUNCTION e_source_set_group ##### -->
-<para>
-
-</para>
-
- source:
- group:
-
-
-<!-- ##### FUNCTION e_source_set_name ##### -->
-<para>
-
-</para>
-
- source:
- name:
-
-
-<!-- ##### FUNCTION e_source_set_relative_uri ##### -->
-<para>
-
-</para>
-
- source:
- relative_uri:
-
-
-<!-- ##### FUNCTION e_source_set_absolute_uri ##### -->
+<!-- ##### FUNCTION e_source_hash ##### -->
<para>
</para>
@source:
- absolute_uri:
-
-
-<!-- ##### FUNCTION e_source_set_color_spec ##### -->
-<para>
-
-</para>
-
- source:
- color_spec:
+ Returns:
-<!-- ##### FUNCTION e_source_set_readonly ##### -->
+<!-- ##### FUNCTION e_source_equal ##### -->
<para>
</para>
- source:
- readonly:
+ source1:
+ source2:
+ Returns:
-<!-- ##### FUNCTION e_source_peek_group ##### -->
+<!-- ##### FUNCTION e_source_sync ##### -->
<para>
</para>
@source:
+ error:
@Returns:
-<!-- ##### FUNCTION e_source_peek_uid ##### -->
+<!-- ##### FUNCTION e_source_reload ##### -->
<para>
</para>
@source:
+ error:
@Returns:
-<!-- ##### FUNCTION e_source_peek_name ##### -->
+<!-- ##### FUNCTION e_source_changed ##### -->
<para>
</para>
@source:
- Returns:
-<!-- ##### FUNCTION e_source_peek_relative_uri ##### -->
+<!-- ##### FUNCTION e_source_redirect ##### -->
<para>
</para>
@source:
- Returns:
+ directory:
-<!-- ##### FUNCTION e_source_peek_absolute_uri ##### -->
+<!-- ##### FUNCTION e_source_get_uid ##### -->
<para>
</para>
@@ -199,7 +133,7 @@ ESource
@Returns:
-<!-- ##### FUNCTION e_source_peek_color_spec ##### -->
+<!-- ##### FUNCTION e_source_get_file ##### -->
<para>
</para>
@@ -208,7 +142,7 @@ ESource
@Returns:
-<!-- ##### FUNCTION e_source_get_readonly ##### -->
+<!-- ##### FUNCTION e_source_get_node ##### -->
<para>
</para>
@@ -217,7 +151,7 @@ ESource
@Returns:
-<!-- ##### FUNCTION e_source_get_uri ##### -->
+<!-- ##### FUNCTION e_source_get_parent ##### -->
<para>
</para>
@@ -226,90 +160,78 @@ ESource
@Returns:
-<!-- ##### FUNCTION e_source_dump_to_xml_node ##### -->
+<!-- ##### FUNCTION e_source_set_parent ##### -->
<para>
</para>
@source:
- parent_node:
+ parent:
-<!-- ##### FUNCTION e_source_to_standalone_xml ##### -->
+<!-- ##### FUNCTION e_source_get_extension ##### -->
<para>
</para>
@source:
+ extension_name:
@Returns:
-<!-- ##### FUNCTION e_source_get_property ##### -->
+<!-- ##### FUNCTION e_source_has_extension ##### -->
<para>
</para>
@source:
- property:
+ extension_name:
@Returns:
-<!-- ##### FUNCTION e_source_set_property ##### -->
+<!-- ##### FUNCTION e_source_get_backend_name ##### -->
<para>
</para>
@source:
- property:
- value:
+ Returns:
-<!-- ##### FUNCTION e_source_foreach_property ##### -->
+<!-- ##### FUNCTION e_source_set_backend_name ##### -->
<para>
</para>
@source:
- func:
- data:
+ backend_name:
-<!-- ##### FUNCTION e_source_get_duped_property ##### -->
+<!-- ##### FUNCTION e_source_get_display_name ##### -->
<para>
</para>
@source:
- property:
@Returns:
-<!-- ##### FUNCTION e_source_build_absolute_uri ##### -->
+<!-- ##### FUNCTION e_source_set_display_name ##### -->
<para>
</para>
@source:
- Returns:
-
-
-<!-- ##### FUNCTION e_source_equal ##### -->
-<para>
-
-</para>
-
- a:
- b:
- Returns:
+ display_name:
-<!-- ##### FUNCTION e_source_xmlstr_equal ##### -->
+<!-- ##### FUNCTION e_source_compare_by_display_name ##### -->
<para>
</para>
- a:
- b:
+ source1:
+ source2:
@Returns:
diff --git a/docs/reference/libedataserverui/libedataserverui-sections.txt b/docs/reference/libedataserverui/libedataserverui-sections.txt
index 6165102..4acca16 100644
--- a/docs/reference/libedataserverui/libedataserverui-sections.txt
+++ b/docs/reference/libedataserverui/libedataserverui-sections.txt
@@ -306,7 +306,8 @@ e_tree_model_generator_get_type
<TITLE>ESourceSelector</TITLE>
ESourceSelector
e_source_selector_new
-e_source_selector_get_source_list
+e_source_selector_get_registry
+e_source_selector_get_extension_name
e_source_selector_select_source
e_source_selector_unselect_source
e_source_selector_select_exclusive
@@ -319,7 +320,6 @@ e_source_selector_set_select_new
e_source_selector_edit_primary_selection
e_source_selector_get_primary_selection
e_source_selector_set_primary_selection
-e_source_selector_get_primary_source_group
e_source_selector_peek_primary_selection
e_source_selector_get_source_by_path
<SUBSECTION Standard>
diff --git a/libedataserver/Makefile.am b/libedataserver/Makefile.am
index cfbee47..2d04207 100644
--- a/libedataserver/Makefile.am
+++ b/libedataserver/Makefile.am
@@ -1,5 +1,8 @@
lib_LTLIBRARIES = libedataserver-1.2.la
+MARSHAL_GENERATED = e-marshal.c e-marshal.h
+ EVO_MARSHAL_RULE@
+
libedataserver_1_2_la_CPPFLAGS = \
$(AM_CPPFLAGS) \
-I$(top_srcdir) \
@@ -8,12 +11,14 @@ libedataserver_1_2_la_CPPFLAGS = \
-DE_DATA_SERVER_LOCALEDIR=\""$(localedir)"\" \
-DE_DATA_SERVER_EXTENSIONDIR=\"$(extensiondir)\" \
-DE_DATA_SERVER_IMAGESDIR=\"$(imagesdir)\" \
+ -DE_DATA_SERVER_PRIVDATADIR=\"$(privdatadir)\" \
-DE_DATA_SERVER_UI_UIDIR=\""$(uidir)"\" \
-DDEFAULT_EDS_DBUS_TIMEOUT=$(DEFAULT_EDS_DBUS_TIMEOUT) \
$(E_DATA_SERVER_CFLAGS) \
$(SOUP_CFLAGS)
libedataserver_1_2_la_SOURCES = \
+ $(MARSHAL_GENERATED) \
e-account-list.c \
e-account.c \
e-categories.c \
@@ -27,6 +32,17 @@ libedataserver_1_2_la_SOURCES = \
e-soap-response.c \
e-sexp.c \
e-source.c \
+ e-source-extension.c \
+ e-source-alarms.c \
+ e-source-authentication.c \
+ e-source-autocomplete.c \
+ e-source-offline.c \
+ e-source-password.c \
+ e-source-refresh.c \
+ e-source-registry.c \
+ e-source-security.c \
+ e-source-selectable.c \
+ e-source-webdav.c \
e-debug-log.c \
e-time-utils.c \
e-uid.c \
@@ -62,6 +78,17 @@ libedataserverinclude_HEADERS = \
e-soap-response.h \
e-sexp.h \
e-source.h \
+ e-source-alarms.h \
+ e-source-authentication.h \
+ e-source-autocomplete.h \
+ e-source-extension.h \
+ e-source-offline.h \
+ e-source-password.h \
+ e-source-refresh.h \
+ e-source-registry.h \
+ e-source-security.h \
+ e-source-selectable.h \
+ e-source-webdav.h \
e-debug-log.h \
e-time-utils.h \
e-uid.h \
@@ -77,9 +104,12 @@ libedataserverinclude_HEADERS = \
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libedataserver-$(API_VERSION).pc
+BUILT_SOURCES = $(MARSHAL_GENERATED)
+
EXTRA_DIST = \
$(pkgconfig_DATA:-$(API_VERSION).pc=.pc.in) \
- eds-version.h.in
+ eds-version.h.in \
+ e-marshal.list
CLEANFILES =
DISTCLEANFILES = eds-version.h $(pkgconfig_DATA)
diff --git a/libedataserver/e-marshal.list b/libedataserver/e-marshal.list
new file mode 100644
index 0000000..4abc0be
--- /dev/null
+++ b/libedataserver/e-marshal.list
@@ -0,0 +1 @@
+NONE:OBJECT,BOXED
diff --git a/libedataserver/e-source-alarms.c b/libedataserver/e-source-alarms.c
new file mode 100644
index 0000000..5068454
--- /dev/null
+++ b/libedataserver/e-source-alarms.c
@@ -0,0 +1,174 @@
+/*
+ * e-source-alarms.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-alarms.h"
+
+#define E_SOURCE_ALARMS_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SOURCE_ALARMS, ESourceAlarmsPrivate))
+
+struct _ESourceAlarmsPrivate {
+ gboolean include_me;
+ gchar *last_notified;
+};
+
+enum {
+ PROP_0,
+ PROP_INCLUDE_ME,
+ PROP_LAST_NOTIFIED
+};
+
+G_DEFINE_TYPE (
+ ESourceAlarms,
+ e_source_alarms,
+ E_TYPE_SOURCE_EXTENSION)
+
+static void
+source_alarms_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_INCLUDE_ME:
+ e_source_alarms_set_include_me (
+ E_SOURCE_ALARMS (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_LAST_NOTIFIED:
+ e_source_alarms_set_last_notified (
+ E_SOURCE_ALARMS (object),
+ g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_alarms_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_INCLUDE_ME:
+ g_value_set_boolean (
+ value,
+ e_source_alarms_get_include_me (
+ E_SOURCE_ALARMS (object)));
+ return;
+
+ case PROP_LAST_NOTIFIED:
+ g_value_set_string (
+ value,
+ e_source_alarms_get_last_notified (
+ E_SOURCE_ALARMS (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_source_alarms_class_init (ESourceAlarmsClass *class)
+{
+ GObjectClass *object_class;
+ ESourceExtensionClass *extension_class;
+
+ g_type_class_add_private (class, sizeof (ESourceAlarmsPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = source_alarms_set_property;
+ object_class->get_property = source_alarms_get_property;
+
+ extension_class = E_SOURCE_EXTENSION_CLASS (class);
+ extension_class->name = E_SOURCE_EXTENSION_ALARMS;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_INCLUDE_ME,
+ g_param_spec_boolean (
+ "include-me",
+ "IncludeMe",
+ "Include this source in alarm notifications",
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_LAST_NOTIFIED,
+ g_param_spec_string (
+ "last-notified",
+ "LastNotified",
+ "Last alarm notification (in ISO 8601 format)",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+}
+
+static void
+e_source_alarms_init (ESourceAlarms *extension)
+{
+ extension->priv = E_SOURCE_ALARMS_GET_PRIVATE (extension);
+}
+
+gboolean
+e_source_alarms_get_include_me (ESourceAlarms *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_ALARMS (extension), FALSE);
+
+ return extension->priv->include_me;
+}
+
+void
+e_source_alarms_set_include_me (ESourceAlarms *extension,
+ gboolean include_me)
+{
+ g_return_if_fail (E_IS_SOURCE_ALARMS (extension));
+
+ extension->priv->include_me = include_me;
+
+ g_object_notify (G_OBJECT (extension), "include-me");
+}
+
+const gchar *
+e_source_alarms_get_last_notified (ESourceAlarms *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_ALARMS (extension), FALSE);
+
+ return extension->priv->last_notified;
+}
+
+void
+e_source_alarms_set_last_notified (ESourceAlarms *extension,
+ const gchar *last_notified)
+{
+ g_return_if_fail (E_IS_SOURCE_ALARMS (extension));
+
+ g_free (extension->priv->last_notified);
+ extension->priv->last_notified = g_strdup (last_notified);
+
+ g_object_notify (G_OBJECT (extension), "last-notified");
+}
diff --git a/libedataserver/e-source-alarms.h b/libedataserver/e-source-alarms.h
new file mode 100644
index 0000000..39ee006
--- /dev/null
+++ b/libedataserver/e-source-alarms.h
@@ -0,0 +1,72 @@
+/*
+ * e-source-alarms.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_ALARMS_H
+#define E_SOURCE_ALARMS_H
+
+#include <libedataserver/e-source-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_ALARMS \
+ (e_source_alarms_get_type ())
+#define E_SOURCE_ALARMS(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_ALARMS, ESourceAlarms))
+#define E_SOURCE_ALARMS_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_ALARMS, ESourceAlarmsClass))
+#define E_IS_SOURCE_ALARMS(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_ALARMS))
+#define E_IS_SOURCE_ALARMS_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_ALARMS))
+#define E_SOURCE_ALARMS_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_ALARMS, ESourceAlarmsClass))
+
+#define E_SOURCE_EXTENSION_ALARMS "Alarms"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceAlarms ESourceAlarms;
+typedef struct _ESourceAlarmsClass ESourceAlarmsClass;
+typedef struct _ESourceAlarmsPrivate ESourceAlarmsPrivate;
+
+struct _ESourceAlarms {
+ ESourceExtension parent;
+ ESourceAlarmsPrivate *priv;
+};
+
+struct _ESourceAlarmsClass {
+ ESourceExtensionClass parent_class;
+};
+
+GType e_source_alarms_get_type (void);
+gboolean e_source_alarms_get_include_me (ESourceAlarms *extension);
+void e_source_alarms_set_include_me (ESourceAlarms *extension,
+ gboolean include_me);
+const gchar * e_source_alarms_get_last_notified
+ (ESourceAlarms *extension);
+void e_source_alarms_set_last_notified
+ (ESourceAlarms *extension,
+ const gchar *last_notified);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_ALARMS_H */
diff --git a/libedataserver/e-source-authentication.c b/libedataserver/e-source-authentication.c
new file mode 100644
index 0000000..0d39af6
--- /dev/null
+++ b/libedataserver/e-source-authentication.c
@@ -0,0 +1,408 @@
+/*
+ * e-source-authentication.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-authentication.h"
+
+#define E_SOURCE_AUTHENTICATION_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SOURCE_AUTHENTICATION, ESourceAuthenticationPrivate))
+
+struct _ESourceAuthenticationPrivate {
+ gchar *domain;
+ gchar *host;
+ gchar *method;
+ guint16 port;
+ gboolean remember_password;
+ gchar *user;
+};
+
+enum {
+ PROP_0,
+ PROP_DOMAIN,
+ PROP_HOST,
+ PROP_METHOD,
+ PROP_PORT,
+ PROP_REMEMBER_PASSWORD,
+ PROP_USER
+};
+
+G_DEFINE_TYPE (
+ ESourceAuthentication,
+ e_source_authentication,
+ E_TYPE_SOURCE_EXTENSION)
+
+static void
+source_authentication_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_DOMAIN:
+ e_source_authentication_set_domain (
+ E_SOURCE_AUTHENTICATION (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_HOST:
+ e_source_authentication_set_host (
+ E_SOURCE_AUTHENTICATION (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_METHOD:
+ e_source_authentication_set_method (
+ E_SOURCE_AUTHENTICATION (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_PORT:
+ e_source_authentication_set_port (
+ E_SOURCE_AUTHENTICATION (object),
+ g_value_get_uint (value));
+ return;
+
+ case PROP_REMEMBER_PASSWORD:
+ e_source_authentication_set_remember_password (
+ E_SOURCE_AUTHENTICATION (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_USER:
+ e_source_authentication_set_user (
+ E_SOURCE_AUTHENTICATION (object),
+ g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_authentication_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_DOMAIN:
+ g_value_set_string (
+ value,
+ e_source_authentication_get_domain (
+ E_SOURCE_AUTHENTICATION (object)));
+ return;
+
+ case PROP_HOST:
+ g_value_set_string (
+ value,
+ e_source_authentication_get_host (
+ E_SOURCE_AUTHENTICATION (object)));
+ return;
+
+ case PROP_METHOD:
+ g_value_set_string (
+ value,
+ e_source_authentication_get_method (
+ E_SOURCE_AUTHENTICATION (object)));
+ return;
+
+ case PROP_PORT:
+ g_value_set_uint (
+ value,
+ e_source_authentication_get_port (
+ E_SOURCE_AUTHENTICATION (object)));
+ return;
+
+ case PROP_REMEMBER_PASSWORD:
+ g_value_set_boolean (
+ value,
+ e_source_authentication_get_remember_password (
+ E_SOURCE_AUTHENTICATION (object)));
+ return;
+
+ case PROP_USER:
+ g_value_set_string (
+ value,
+ e_source_authentication_get_user (
+ E_SOURCE_AUTHENTICATION (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_authentication_finalize (GObject *object)
+{
+ ESourceAuthenticationPrivate *priv;
+
+ priv = E_SOURCE_AUTHENTICATION_GET_PRIVATE (object);
+
+ g_free (priv->domain);
+ g_free (priv->host);
+ g_free (priv->method);
+ g_free (priv->user);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_source_authentication_parent_class)->finalize (object);
+}
+
+static void
+e_source_authentication_class_init (ESourceAuthenticationClass *class)
+{
+ GObjectClass *object_class;
+ ESourceExtensionClass *extension_class;
+
+ g_type_class_add_private (class, sizeof (ESourceAuthenticationPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = source_authentication_set_property;
+ object_class->get_property = source_authentication_get_property;
+ object_class->finalize = source_authentication_finalize;
+
+ extension_class = E_SOURCE_EXTENSION_CLASS (class);
+ extension_class->name = E_SOURCE_EXTENSION_AUTHENTICATION;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_DOMAIN,
+ g_param_spec_string (
+ "domain",
+ "Domain",
+ "Authentication domain",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_HOST,
+ g_param_spec_string (
+ "host",
+ "Host",
+ "Host name for the remote account",
+ "",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_METHOD,
+ g_param_spec_string (
+ "method",
+ "Method",
+ "Authentication method",
+ "none",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_PORT,
+ g_param_spec_uint (
+ "port",
+ "Port",
+ "Port number for the remote account",
+ 0, G_MAXUINT16, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_REMEMBER_PASSWORD,
+ g_param_spec_boolean (
+ "remember-password",
+ "RememberPassword",
+ "Remember the user's password",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_USER,
+ g_param_spec_string (
+ "user",
+ "User",
+ "User name for the remote account",
+ g_get_user_name (),
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+}
+
+static void
+e_source_authentication_init (ESourceAuthentication *extension)
+{
+ extension->priv = E_SOURCE_AUTHENTICATION_GET_PRIVATE (extension);
+}
+
+gboolean
+e_source_authentication_required (ESourceAuthentication *extension)
+{
+ const gchar *method;
+
+ /* This is a convenience function for when we just want to
+ * know if a remote data source requires us to authenticate.
+ * Our convention is to set the method name to "none" when
+ * authentication is not required. */
+
+ g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), FALSE);
+
+ method = e_source_authentication_get_method (extension);
+ g_return_val_if_fail (method != NULL && *method != '\0', FALSE);
+
+ return (g_strcmp0 (method, "none") != 0);
+}
+
+const gchar *
+e_source_authentication_get_domain (ESourceAuthentication *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), NULL);
+
+ return extension->priv->domain;
+}
+
+void
+e_source_authentication_set_domain (ESourceAuthentication *extension,
+ const gchar *domain)
+{
+ g_return_if_fail (E_IS_SOURCE_AUTHENTICATION (extension));
+
+ g_free (extension->priv->domain);
+ extension->priv->domain = g_strdup (domain);
+
+ g_object_notify (G_OBJECT (extension), "domain");
+}
+
+const gchar *
+e_source_authentication_get_host (ESourceAuthentication *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), NULL);
+
+ return extension->priv->host;
+}
+
+void
+e_source_authentication_set_host (ESourceAuthentication *extension,
+ const gchar *host)
+{
+ g_return_if_fail (E_IS_SOURCE_AUTHENTICATION (extension));
+
+ g_free (extension->priv->host);
+ extension->priv->host = g_strdup (host);
+
+ g_object_notify (G_OBJECT (extension), "host");
+}
+
+const gchar *
+e_source_authentication_get_method (ESourceAuthentication *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), NULL);
+
+ return extension->priv->method;
+}
+
+void
+e_source_authentication_set_method (ESourceAuthentication *extension,
+ const gchar *method)
+{
+ g_return_if_fail (E_IS_SOURCE_AUTHENTICATION (extension));
+
+ /* Convert empty strings to "none". */
+ if (method == NULL || *method == '\0')
+ method = "none";
+
+ g_free (extension->priv->method);
+ extension->priv->method = g_strdup (method);
+
+ g_object_notify (G_OBJECT (extension), "method");
+}
+
+guint16
+e_source_authentication_get_port (ESourceAuthentication *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), 0);
+
+ return extension->priv->port;
+}
+
+void
+e_source_authentication_set_port (ESourceAuthentication *extension,
+ guint16 port)
+{
+ g_return_if_fail (E_SOURCE_AUTHENTICATION (extension));
+
+ extension->priv->port = port;
+
+ g_object_notify (G_OBJECT (extension), "port");
+}
+
+gboolean
+e_source_authentication_get_remember_password (ESourceAuthentication *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), FALSE);
+
+ return extension->priv->remember_password;
+}
+
+void
+e_source_authentication_set_remember_password (ESourceAuthentication *extension,
+ gboolean remember_password)
+{
+ g_return_if_fail (E_IS_SOURCE_AUTHENTICATION (extension));
+
+ extension->priv->remember_password = remember_password;
+
+ g_object_notify (G_OBJECT (extension), "remember-password");
+}
+
+const gchar *
+e_source_authentication_get_user (ESourceAuthentication *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), NULL);
+
+ return extension->priv->user;
+}
+
+void
+e_source_authentication_set_user (ESourceAuthentication *extension,
+ const gchar *user)
+{
+ g_return_if_fail (E_IS_SOURCE_AUTHENTICATION (extension));
+
+ g_free (extension->priv->user);
+ extension->priv->user = g_strdup (user);
+
+ /* Strip leading and trailing whitespace. */
+ if (extension->priv->user != NULL)
+ g_strstrip (extension->priv->user);
+
+ g_object_notify (G_OBJECT (extension), "user");
+}
diff --git a/libedataserver/e-source-authentication.h b/libedataserver/e-source-authentication.h
new file mode 100644
index 0000000..86b3c9e
--- /dev/null
+++ b/libedataserver/e-source-authentication.h
@@ -0,0 +1,96 @@
+/*
+ * e-source-authentication.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_AUTHENTICATION_H
+#define E_SOURCE_AUTHENTICATION_H
+
+#include <libedataserver/e-source-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_AUTHENTICATION \
+ (e_source_authentication_get_type ())
+#define E_SOURCE_AUTHENTICATION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_AUTHENTICATION, ESourceAuthentication))
+#define E_SOURCE_AUTHENTICATION_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_AUTHENTICATION, ESourceAuthenticationClass))
+#define E_IS_SOURCE_AUTHENTICATION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_AUTHENTICATION))
+#define E_IS_SOURCE_AUTHENTICATION_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_AUTHENTICATION))
+#define E_SOURCE_AUTHENTICATION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_AUTHENTICATION, ESourceAuthenticationClass))
+
+#define E_SOURCE_EXTENSION_AUTHENTICATION "Authentication"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceAuthentication ESourceAuthentication;
+typedef struct _ESourceAuthenticationClass ESourceAuthenticationClass;
+typedef struct _ESourceAuthenticationPrivate ESourceAuthenticationPrivate;
+
+struct _ESourceAuthentication {
+ ESourceExtension parent;
+ ESourceAuthenticationPrivate *priv;
+};
+
+struct _ESourceAuthenticationClass {
+ ESourceExtensionClass parent_class;
+};
+
+GType e_source_authentication_get_type (void);
+gboolean e_source_authentication_required
+ (ESourceAuthentication *extension);
+const gchar * e_source_authentication_get_domain
+ (ESourceAuthentication *extension);
+void e_source_authentication_set_domain
+ (ESourceAuthentication *extension,
+ const gchar *domain);
+const gchar * e_source_authentication_get_host
+ (ESourceAuthentication *extension);
+void e_source_authentication_set_host
+ (ESourceAuthentication *extension,
+ const gchar *host);
+const gchar * e_source_authentication_get_method
+ (ESourceAuthentication *extension);
+void e_source_authentication_set_method
+ (ESourceAuthentication *extension,
+ const gchar *method);
+guint16 e_source_authentication_get_port
+ (ESourceAuthentication *extension);
+void e_source_authentication_set_port
+ (ESourceAuthentication *extension,
+ guint16 port);
+gboolean e_source_authentication_get_remember_password
+ (ESourceAuthentication *extension);
+void e_source_authentication_set_remember_password
+ (ESourceAuthentication *extension,
+ gboolean remember_password);
+const gchar * e_source_authentication_get_user
+ (ESourceAuthentication *extension);
+void e_source_authentication_set_user
+ (ESourceAuthentication *extension,
+ const gchar *user);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_AUTHENTICATION_H */
diff --git a/libedataserver/e-source-autocomplete.c b/libedataserver/e-source-autocomplete.c
new file mode 100644
index 0000000..958e631
--- /dev/null
+++ b/libedataserver/e-source-autocomplete.c
@@ -0,0 +1,126 @@
+/*
+ * e-source-autocomplete.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-autocomplete.h"
+
+#define E_SOURCE_AUTOCOMPLETE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SOURCE_AUTOCOMPLETE, ESourceAutocompletePrivate))
+
+struct _ESourceAutocompletePrivate {
+ gboolean include_me;
+};
+
+enum {
+ PROP_0,
+ PROP_INCLUDE_ME
+};
+
+G_DEFINE_TYPE (
+ ESourceAutocomplete,
+ e_source_autocomplete,
+ E_TYPE_SOURCE_EXTENSION)
+
+static void
+source_autocomplete_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_INCLUDE_ME:
+ e_source_autocomplete_set_include_me (
+ E_SOURCE_AUTOCOMPLETE (object),
+ g_value_get_boolean (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_autocomplete_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_INCLUDE_ME:
+ g_value_set_boolean (
+ value,
+ e_source_autocomplete_get_include_me (
+ E_SOURCE_AUTOCOMPLETE (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_source_autocomplete_class_init (ESourceAutocompleteClass *class)
+{
+ GObjectClass *object_class;
+ ESourceExtensionClass *extension_class;
+
+ g_type_class_add_private (class, sizeof (ESourceAutocompletePrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = source_autocomplete_set_property;
+ object_class->get_property = source_autocomplete_get_property;
+
+ extension_class = E_SOURCE_EXTENSION_CLASS (class);
+ extension_class->name = E_SOURCE_EXTENSION_AUTOCOMPLETE;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_INCLUDE_ME,
+ g_param_spec_boolean (
+ "include-me",
+ "IncludeMe",
+ "Include this source when autocompleting",
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+}
+
+static void
+e_source_autocomplete_init (ESourceAutocomplete *extension)
+{
+ extension->priv = E_SOURCE_AUTOCOMPLETE_GET_PRIVATE (extension);
+}
+
+gboolean
+e_source_autocomplete_get_include_me (ESourceAutocomplete *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_AUTOCOMPLETE (extension), FALSE);
+
+ return extension->priv->include_me;
+}
+
+void
+e_source_autocomplete_set_include_me (ESourceAutocomplete *extension,
+ gboolean include_me)
+{
+ g_return_if_fail (E_IS_SOURCE_AUTOCOMPLETE (extension));
+
+ extension->priv->include_me = include_me;
+
+ g_object_notify (G_OBJECT (extension), "include-me");
+}
diff --git a/libedataserver/e-source-autocomplete.h b/libedataserver/e-source-autocomplete.h
new file mode 100644
index 0000000..b91725b
--- /dev/null
+++ b/libedataserver/e-source-autocomplete.h
@@ -0,0 +1,69 @@
+/*
+ * e-source-autocomplete.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_AUTOCOMPLETE_H
+#define E_SOURCE_AUTOCOMPLETE_H
+
+#include <libedataserver/e-source-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_AUTOCOMPLETE \
+ (e_source_autocomplete_get_type ())
+#define E_SOURCE_AUTOCOMPLETE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_AUTOCOMPLETE, ESourceAutocomplete))
+#define E_SOURCE_AUTOCOMPLETE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_AUTOCOMPLETE, ESourceAutocompleteClass))
+#define E_IS_SOURCE_AUTOCOMPLETE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_AUTOCOMPLETE))
+#define E_IS_SOURCE_AUTOCOMPLETE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_AUTOCOMPLETE))
+#define E_SOURCE_AUTOCOMPLETE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_AUTOCOMPLETE, ESourceAutocompleteClass))
+
+#define E_SOURCE_EXTENSION_AUTOCOMPLETE "Autocomplete"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceAutocomplete ESourceAutocomplete;
+typedef struct _ESourceAutocompleteClass ESourceAutocompleteClass;
+typedef struct _ESourceAutocompletePrivate ESourceAutocompletePrivate;
+
+struct _ESourceAutocomplete {
+ ESourceExtension parent;
+ ESourceAutocompletePrivate *priv;
+};
+
+struct _ESourceAutocompleteClass {
+ ESourceExtensionClass parent_class;
+};
+
+GType e_source_autocomplete_get_type (void);
+gboolean e_source_autocomplete_get_include_me
+ (ESourceAutocomplete *extension);
+void e_source_autocomplete_set_include_me
+ (ESourceAutocomplete *extension,
+ gboolean include_me);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_AUTOCOMPLETE_H */
diff --git a/libedataserver/e-source-extension.c b/libedataserver/e-source-extension.c
new file mode 100644
index 0000000..bab3409
--- /dev/null
+++ b/libedataserver/e-source-extension.c
@@ -0,0 +1,167 @@
+/*
+ * e-source-extension.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-extension.h"
+
+#define E_SOURCE_EXTENSION_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SOURCE_EXTENSION, ESourceExtensionPrivate))
+
+struct _ESourceExtensionPrivate {
+ gpointer source; /* weak pointer */
+};
+
+enum {
+ PROP_0,
+ PROP_SOURCE
+};
+
+G_DEFINE_ABSTRACT_TYPE (
+ ESourceExtension,
+ e_source_extension,
+ G_TYPE_OBJECT)
+
+static void
+source_extension_set_source (ESourceExtension *extension,
+ ESource *source)
+{
+ g_return_if_fail (E_IS_SOURCE (source));
+ g_return_if_fail (extension->priv->source == NULL);
+
+ extension->priv->source = source;
+
+ g_object_add_weak_pointer (
+ G_OBJECT (source), &extension->priv->source);
+}
+
+static void
+source_extension_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SOURCE:
+ source_extension_set_source (
+ E_SOURCE_EXTENSION (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_extension_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SOURCE:
+ g_value_set_object (
+ value, e_source_extension_get_source (
+ E_SOURCE_EXTENSION (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_extension_dispose (GObject *object)
+{
+ ESourceExtensionPrivate *priv;
+
+ priv = E_SOURCE_EXTENSION_GET_PRIVATE (object);
+
+ if (priv->source != NULL) {
+ g_object_remove_weak_pointer (
+ G_OBJECT (priv->source), &priv->source);
+ priv->source = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_source_extension_parent_class)->dispose (object);
+}
+
+static void
+source_extension_notify (GObject *object,
+ GParamSpec *pspec)
+{
+ ESource *source;
+ ESourceExtension *extension;
+
+ extension = E_SOURCE_EXTENSION (object);
+ source = e_source_extension_get_source (extension);
+
+ if (source != NULL)
+ e_source_changed (source);
+}
+
+static void
+source_extension_constructed (GObject *object)
+{
+ /* This allows subclasses to chain up safely since GObject
+ * does not implement this method, and we might want to do
+ * something here in the future. */
+}
+
+static void
+e_source_extension_class_init (ESourceExtensionClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (ESourceExtensionPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = source_extension_set_property;
+ object_class->get_property = source_extension_get_property;
+ object_class->dispose = source_extension_dispose;
+ object_class->notify = source_extension_notify;
+ object_class->constructed = source_extension_constructed;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SOURCE,
+ g_param_spec_object (
+ "source",
+ "Source",
+ "The ESource being extended",
+ E_TYPE_SOURCE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_source_extension_init (ESourceExtension *extension)
+{
+ extension->priv = E_SOURCE_EXTENSION_GET_PRIVATE (extension);
+}
+
+ESource *
+e_source_extension_get_source (ESourceExtension *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_EXTENSION (extension), NULL);
+
+ /* If the ESource was finalized and our weak pointer set this
+ * to NULL, then the type cast macro will fail and we'll get a
+ * runtime warning about it, which is what we want. */
+ return E_SOURCE (extension->priv->source);
+}
diff --git a/libedataserver/e-source-extension.h b/libedataserver/e-source-extension.h
new file mode 100644
index 0000000..d4db376
--- /dev/null
+++ b/libedataserver/e-source-extension.h
@@ -0,0 +1,65 @@
+/*
+ * e-source-extension.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_EXTENSION_H
+#define E_SOURCE_EXTENSION_H
+
+#include <libedataserver/e-source.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_EXTENSION \
+ (e_source_extension_get_type ())
+#define E_SOURCE_EXTENSION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_EXTENSION, ESourceExtension))
+#define E_SOURCE_EXTENSION_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_EXTENSION, ESourceExtensionClass))
+#define E_IS_SOURCE_EXTENSION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_EXTENSION))
+#define E_IS_SOURCE_EXTENSION_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_EXTENSION))
+#define E_SOURCE_EXTENSION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_EXTENSION, ESourceExtensionClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceExtension ESourceExtension;
+typedef struct _ESourceExtensionClass ESourceExtensionClass;
+typedef struct _ESourceExtensionPrivate ESourceExtensionPrivate;
+
+struct _ESourceExtension {
+ GObject parent;
+ ESourceExtensionPrivate *priv;
+};
+
+struct _ESourceExtensionClass {
+ GObjectClass parent_class;
+
+ const gchar *name;
+};
+
+GType e_source_extension_get_type (void) G_GNUC_CONST;
+ESource * e_source_extension_get_source (ESourceExtension *extension);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_EXTENSION_H */
diff --git a/libedataserver/e-source-offline.c b/libedataserver/e-source-offline.c
new file mode 100644
index 0000000..2319d17
--- /dev/null
+++ b/libedataserver/e-source-offline.c
@@ -0,0 +1,126 @@
+/*
+ * e-source-offline.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-offline.h"
+
+#define E_SOURCE_OFFLINE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SOURCE_OFFLINE, ESourceOfflinePrivate))
+
+struct _ESourceOfflinePrivate {
+ gboolean stay_synchronized;
+};
+
+enum {
+ PROP_0,
+ PROP_STAY_SYNCHRONIZED
+};
+
+G_DEFINE_TYPE (
+ ESourceOffline,
+ e_source_offline,
+ E_TYPE_SOURCE_EXTENSION)
+
+static void
+source_offline_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_STAY_SYNCHRONIZED:
+ e_source_offline_set_stay_synchronized (
+ E_SOURCE_OFFLINE (object),
+ g_value_get_boolean (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_offline_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_STAY_SYNCHRONIZED:
+ g_value_set_boolean (
+ value,
+ e_source_offline_get_stay_synchronized (
+ E_SOURCE_OFFLINE (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_source_offline_class_init (ESourceOfflineClass *class)
+{
+ GObjectClass *object_class;
+ ESourceExtensionClass *extension_class;
+
+ g_type_class_add_private (class, sizeof (ESourceOfflinePrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = source_offline_set_property;
+ object_class->get_property = source_offline_get_property;
+
+ extension_class = E_SOURCE_EXTENSION_CLASS (class);
+ extension_class->name = E_SOURCE_EXTENSION_OFFLINE;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_STAY_SYNCHRONIZED,
+ g_param_spec_boolean (
+ "stay-synchronized",
+ "StaySynchronized",
+ "Keep remote content synchronized locally",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+}
+
+static void
+e_source_offline_init (ESourceOffline *extension)
+{
+ extension->priv = E_SOURCE_OFFLINE_GET_PRIVATE (extension);
+}
+
+gboolean
+e_source_offline_get_stay_synchronized (ESourceOffline *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_OFFLINE (extension), FALSE);
+
+ return extension->priv->stay_synchronized;
+}
+
+void
+e_source_offline_set_stay_synchronized (ESourceOffline *extension,
+ gboolean stay_synchronized)
+{
+ g_return_if_fail (E_IS_SOURCE_OFFLINE (extension));
+
+ extension->priv->stay_synchronized = stay_synchronized;
+
+ g_object_notify (G_OBJECT (extension), "stay-synchronized");
+}
diff --git a/libedataserver/e-source-offline.h b/libedataserver/e-source-offline.h
new file mode 100644
index 0000000..d31092e
--- /dev/null
+++ b/libedataserver/e-source-offline.h
@@ -0,0 +1,69 @@
+/*
+ * e-source-offline.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_OFFLINE_H
+#define E_SOURCE_OFFLINE_H
+
+#include <libedataserver/e-source-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_OFFLINE \
+ (e_source_offline_get_type ())
+#define E_SOURCE_OFFLINE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_OFFLINE, ESourceOffline))
+#define E_SOURCE_OFFLINE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_OFFLINE, ESourceOfflineClass))
+#define E_IS_SOURCE_OFFLINE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_OFFLINE))
+#define E_IS_SOURCE_OFFLINE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_OFFLINE))
+#define E_SOURCE_OFFLINE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_OFFLINE, ESourceOfflineClass))
+
+#define E_SOURCE_EXTENSION_OFFLINE "Offline"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceOffline ESourceOffline;
+typedef struct _ESourceOfflineClass ESourceOfflineClass;
+typedef struct _ESourceOfflinePrivate ESourceOfflinePrivate;
+
+struct _ESourceOffline {
+ ESourceExtension parent;
+ ESourceOfflinePrivate *priv;
+};
+
+struct _ESourceOfflineClass {
+ ESourceExtensionClass parent_class;
+};
+
+GType e_source_offline_get_type (void);
+gboolean e_source_offline_get_stay_synchronized
+ (ESourceOffline *extension);
+void e_source_offline_set_stay_synchronized
+ (ESourceOffline *extension,
+ gboolean stay_synchronized);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_OFFLINE_H */
diff --git a/libedataserver/e-source-password.c b/libedataserver/e-source-password.c
new file mode 100644
index 0000000..6d9c0ce
--- /dev/null
+++ b/libedataserver/e-source-password.c
@@ -0,0 +1,412 @@
+/*
+ * e-source-password.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-password.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+#include <gnome-keyring.h>
+
+#define KEYRING_ITEM_ATTRIBUTE_NAME "e-source-uid"
+#define KEYRING_ITEM_DISPLAY_FORMAT "Evolution Data Source %s"
+
+typedef struct _Context Context;
+
+struct _Context {
+ gchar *password;
+ gboolean permanently;
+};
+
+static GnomeKeyringPasswordSchema schema = {
+ GNOME_KEYRING_ITEM_GENERIC_SECRET,
+ {
+ { KEYRING_ITEM_ATTRIBUTE_NAME,
+ GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
+ { NULL, 0 }
+ }
+};
+
+static void
+context_free (Context *context)
+{
+ g_free (context->password);
+ g_slice_free (Context, context);
+}
+
+GQuark
+e_source_password_error_quark (void)
+{
+ static GQuark quark = 0;
+
+ if (G_UNLIKELY (quark == 0)) {
+ const gchar *string = "e-source-password-error-quark";
+ quark = g_quark_from_static_string (string);
+ }
+
+ return quark;
+}
+
+static void
+source_password_store_thread (GSimpleAsyncResult *simple,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ Context *context;
+ GError *error = NULL;
+
+ context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ e_source_password_store_sync (
+ E_SOURCE (object), context->password,
+ context->permanently, cancellable, &error);
+
+ if (error != NULL) {
+ g_simple_async_result_set_from_error (simple, error);
+ g_error_free (error);
+ }
+}
+
+void
+e_source_password_store (ESource *source,
+ const gchar *password,
+ gboolean permanently,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ Context *context;
+
+ g_return_if_fail (E_IS_SOURCE (source));
+ g_return_if_fail (password != NULL);
+
+ context = g_slice_new0 (Context);
+ context->password = g_strdup (password);
+ context->permanently = permanently;
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (source), callback,
+ user_data, e_source_password_store);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, context, (GDestroyNotify) context_free);
+
+ g_simple_async_result_run_in_thread (
+ simple, source_password_store_thread,
+ io_priority, cancellable);
+
+ g_object_unref (simple);
+}
+
+gboolean
+e_source_password_store_finish (ESource *source,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (source), e_source_password_store), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ /* Assume success unless a GError is set. */
+ return !g_simple_async_result_propagate_error (simple, error);
+}
+
+gboolean
+e_source_password_store_sync (ESource *source,
+ const gchar *password,
+ gboolean permanently,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GnomeKeyringResult result;
+ const gchar *keyring;
+ const gchar *uid;
+ gchar *display_name;
+
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+ g_return_val_if_fail (password != NULL, FALSE);
+
+ /* XXX Syncrhonous gnome-keyring functions are not cancellable.
+ * Maybe they will be someday, but in the meantime check for
+ * cancellation ourselves before doing this. */
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return FALSE;
+
+ if (permanently)
+ keyring = GNOME_KEYRING_DEFAULT;
+ else
+ keyring = GNOME_KEYRING_SESSION;
+
+ uid = e_source_get_uid (source);
+ display_name = g_strdup_printf (KEYRING_ITEM_DISPLAY_FORMAT, uid);
+
+ result = gnome_keyring_store_password_sync (
+ &schema, keyring, display_name, password,
+ KEYRING_ITEM_ATTRIBUTE_NAME, uid, NULL);
+
+ if (result == GNOME_KEYRING_RESULT_CANCELLED) {
+ g_cancellable_cancel (cancellable);
+ g_set_error_literal (
+ error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ _("Keyring operation was cancelled"));
+
+ } else if (result != GNOME_KEYRING_RESULT_OK) {
+ g_set_error_literal (
+ error, E_SOURCE_PASSWORD_ERROR, result,
+ gnome_keyring_result_to_message (result));
+ }
+
+ g_free (display_name);
+
+ return (result == GNOME_KEYRING_RESULT_OK);
+}
+
+static void
+source_password_lookup_thread (GSimpleAsyncResult *simple,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ Context *context;
+ GError *error = NULL;
+
+ context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ e_source_password_lookup_sync (
+ E_SOURCE (object), cancellable,
+ &context->password, &error);
+
+ if (error != NULL) {
+ g_simple_async_result_set_from_error (simple, error);
+ g_error_free (error);
+ }
+}
+
+void
+e_source_password_lookup (ESource *source,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ Context *context;
+
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ context = g_slice_new0 (Context);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (source), callback,
+ user_data, e_source_password_lookup);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, context, (GDestroyNotify) context_free);
+
+ g_simple_async_result_run_in_thread (
+ simple, source_password_lookup_thread,
+ io_priority, cancellable);
+
+ g_object_unref (simple);
+}
+
+gboolean
+e_source_password_lookup_finish (ESource *source,
+ GAsyncResult *result,
+ gchar **password,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ Context *context;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (source), e_source_password_lookup), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ if (password != NULL)
+ *password = context->password;
+ else
+ e_source_password_free (context->password);
+
+ context->password = NULL;
+
+ return TRUE;
+}
+
+gboolean
+e_source_password_lookup_sync (ESource *source,
+ GCancellable *cancellable,
+ gchar **password,
+ GError **error)
+{
+ GnomeKeyringResult result;
+ const gchar *uid;
+ gchar *temp = NULL;
+
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+ /* XXX Synchronous gnome-keyring functions are not cancellable.
+ * Maybe they will be someday, but in the meantime check for
+ * cancellation ourselves before doing this. */
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return FALSE;
+
+ uid = e_source_get_uid (source);
+
+ result = gnome_keyring_find_password_sync (
+ &schema, &temp, KEYRING_ITEM_ATTRIBUTE_NAME, uid, NULL);
+
+ /* Not finding an ESource password is not an error. */
+ if (result == GNOME_KEYRING_RESULT_NO_MATCH) {
+ result = GNOME_KEYRING_RESULT_OK;
+ e_source_password_free (temp);
+ temp = NULL;
+
+ } else if (result == GNOME_KEYRING_RESULT_CANCELLED) {
+ g_cancellable_cancel (cancellable);
+ g_set_error_literal (
+ error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ _("Keyring operation was cancelled"));
+ g_warn_if_fail (temp == NULL);
+
+ } else if (result != GNOME_KEYRING_RESULT_OK) {
+ g_set_error_literal (
+ error, E_SOURCE_PASSWORD_ERROR, result,
+ gnome_keyring_result_to_message (result));
+ g_warn_if_fail (temp == NULL);
+ }
+
+ if (password != NULL)
+ *password = temp;
+ else
+ e_source_password_free (temp);
+
+ return (result == GNOME_KEYRING_RESULT_OK);
+}
+
+static void
+source_password_delete_thread (GSimpleAsyncResult *simple,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ GError *error = NULL;
+
+ e_source_password_delete_sync (
+ E_SOURCE (object), cancellable, &error);
+
+ if (error != NULL) {
+ g_simple_async_result_set_from_error (simple, error);
+ g_error_free (error);
+ }
+}
+
+void
+e_source_password_delete (ESource *source,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (source), callback,
+ user_data, e_source_password_delete);
+
+ g_simple_async_result_run_in_thread (
+ simple, source_password_delete_thread,
+ io_priority, cancellable);
+
+ g_object_unref (simple);
+}
+
+gboolean
+e_source_password_delete_finish (ESource *source,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (source), e_source_password_delete), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ /* Assume success unless a GError is set. */
+ return !g_simple_async_result_propagate_error (simple, error);
+}
+
+gboolean
+e_source_password_delete_sync (ESource *source,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GnomeKeyringResult result;
+ const gchar *uid;
+
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+ /* XXX Synchronous gnome-keyring functions are not cancellable.
+ * Maybe they will be someday, but in the meantime check for
+ * cancellation ourselves before doing this. */
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return FALSE;
+
+ uid = e_source_get_uid (source);
+
+ result = gnome_keyring_delete_password_sync (
+ &schema, KEYRING_ITEM_ATTRIBUTE_NAME, uid, NULL);
+
+ /* Not finding an ESource password is not an error. */
+ if (result == GNOME_KEYRING_RESULT_NO_MATCH) {
+ result = GNOME_KEYRING_RESULT_OK;
+
+ } else if (result == GNOME_KEYRING_RESULT_CANCELLED) {
+ g_cancellable_cancel (cancellable);
+ g_set_error_literal (
+ error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ _("Keyring operation was cancelled"));
+
+ } else if (result != GNOME_KEYRING_RESULT_OK) {
+ g_set_error_literal (
+ error, E_SOURCE_PASSWORD_ERROR, result,
+ gnome_keyring_result_to_message (result));
+ }
+
+ return (result == GNOME_KEYRING_RESULT_OK);
+}
+
+void
+e_source_password_free (gchar *password)
+{
+ if (password != NULL)
+ gnome_keyring_free_password (password);
+}
diff --git a/libedataserver/e-source-password.h b/libedataserver/e-source-password.h
new file mode 100644
index 0000000..e1f8473
--- /dev/null
+++ b/libedataserver/e-source-password.h
@@ -0,0 +1,72 @@
+/*
+ * e-source-password.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_PASSWORD_H
+#define E_SOURCE_PASSWORD_H
+
+#include <libedataserver/e-source.h>
+
+#define E_SOURCE_PASSWORD_ERROR (e_source_password_error_quark ())
+
+G_BEGIN_DECLS
+
+GQuark e_source_password_error_quark (void) G_GNUC_CONST;
+void e_source_password_store (ESource *source,
+ const gchar *password,
+ gboolean permanently,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_source_password_store_finish (ESource *source,
+ GAsyncResult *result,
+ GError **error);
+gboolean e_source_password_store_sync (ESource *source,
+ const gchar *password,
+ gboolean permanently,
+ GCancellable *cancellable,
+ GError **error);
+void e_source_password_lookup (ESource *source,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_source_password_lookup_finish (ESource *source,
+ GAsyncResult *result,
+ gchar **password,
+ GError **error);
+gboolean e_source_password_lookup_sync (ESource *source,
+ GCancellable *cancellable,
+ gchar **password,
+ GError **error);
+void e_source_password_delete (ESource *source,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_source_password_delete_finish (ESource *source,
+ GAsyncResult *result,
+ GError **error);
+gboolean e_source_password_delete_sync (ESource *source,
+ GCancellable *cancellable,
+ GError **error);
+void e_source_password_free (gchar *password);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_PASSWORD_H */
diff --git a/libedataserver/e-source-refresh.c b/libedataserver/e-source-refresh.c
new file mode 100644
index 0000000..705c079
--- /dev/null
+++ b/libedataserver/e-source-refresh.c
@@ -0,0 +1,126 @@
+/*
+ * e-source-refresh.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-refresh.h"
+
+#define E_SOURCE_REFRESH_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SOURCE_REFRESH, ESourceRefreshPrivate))
+
+struct _ESourceRefreshPrivate {
+ guint interval_minutes;
+};
+
+enum {
+ PROP_0,
+ PROP_INTERVAL_MINUTES
+};
+
+G_DEFINE_TYPE (
+ ESourceRefresh,
+ e_source_refresh,
+ E_TYPE_SOURCE_EXTENSION)
+
+static void
+source_refresh_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_INTERVAL_MINUTES:
+ e_source_refresh_set_interval_minutes (
+ E_SOURCE_REFRESH (object),
+ g_value_get_uint (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_refresh_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_INTERVAL_MINUTES:
+ g_value_set_uint (
+ value,
+ e_source_refresh_get_interval_minutes (
+ E_SOURCE_REFRESH (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_source_refresh_class_init (ESourceRefreshClass *class)
+{
+ GObjectClass *object_class;
+ ESourceExtensionClass *extension_class;
+
+ g_type_class_add_private (class, sizeof (ESourceRefreshPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = source_refresh_set_property;
+ object_class->get_property = source_refresh_get_property;
+
+ extension_class = E_SOURCE_EXTENSION_CLASS (class);
+ extension_class->name = E_SOURCE_EXTENSION_REFRESH;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_INTERVAL_MINUTES,
+ g_param_spec_uint (
+ "interval-minutes",
+ "Interval in Minutes",
+ "Refresh interval in minutes",
+ 0, G_MAXUINT, 60,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+}
+
+static void
+e_source_refresh_init (ESourceRefresh *extension)
+{
+ extension->priv = E_SOURCE_REFRESH_GET_PRIVATE (extension);
+}
+
+guint
+e_source_refresh_get_interval_minutes (ESourceRefresh *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_REFRESH (extension), FALSE);
+
+ return extension->priv->interval_minutes;
+}
+
+void
+e_source_refresh_set_interval_minutes (ESourceRefresh *extension,
+ guint interval_minutes)
+{
+ g_return_if_fail (E_IS_SOURCE_REFRESH (extension));
+
+ extension->priv->interval_minutes = interval_minutes;
+
+ g_object_notify (G_OBJECT (extension), "interval-minutes");
+}
diff --git a/libedataserver/e-source-refresh.h b/libedataserver/e-source-refresh.h
new file mode 100644
index 0000000..36fbe8f
--- /dev/null
+++ b/libedataserver/e-source-refresh.h
@@ -0,0 +1,69 @@
+/*
+ * e-source-refresh.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_REFRESH_H
+#define E_SOURCE_REFRESH_H
+
+#include <libedataserver/e-source-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_REFRESH \
+ (e_source_refresh_get_type ())
+#define E_SOURCE_REFRESH(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_REFRESH, ESourceRefresh))
+#define E_SOURCE_REFRESH_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_REFRESH, ESourceRefreshClass))
+#define E_IS_SOURCE_REFRESH(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_REFRESH))
+#define E_IS_SOURCE_REFRESH_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_REFRESH))
+#define E_SOURCE_REFRESH_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_REFRESH, ESourceRefreshClass))
+
+#define E_SOURCE_EXTENSION_REFRESH "Refresh"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceRefresh ESourceRefresh;
+typedef struct _ESourceRefreshClass ESourceRefreshClass;
+typedef struct _ESourceRefreshPrivate ESourceRefreshPrivate;
+
+struct _ESourceRefresh {
+ ESourceExtension parent;
+ ESourceRefreshPrivate *priv;
+};
+
+struct _ESourceRefreshClass {
+ ESourceExtensionClass parent_class;
+};
+
+GType e_source_refresh_get_type (void);
+guint e_source_refresh_get_interval_minutes
+ (ESourceRefresh *extension);
+void e_source_refresh_set_interval_minutes
+ (ESourceRefresh *extension,
+ guint interval_in_minutes);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_REFRESH_H */
diff --git a/libedataserver/e-source-registry.c b/libedataserver/e-source-registry.c
new file mode 100644
index 0000000..557149b
--- /dev/null
+++ b/libedataserver/e-source-registry.c
@@ -0,0 +1,1319 @@
+/*
+ * e-source-registry.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-registry.h"
+
+#include <config.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n-lib.h>
+
+#include "e-data-server-util.h"
+#include "e-marshal.h"
+
+/* built-in extension types */
+#include "e-source-alarms.h"
+#include "e-source-authentication.h"
+#include "e-source-autocomplete.h"
+#include "e-source-offline.h"
+#include "e-source-refresh.h"
+#include "e-source-security.h"
+#include "e-source-selectable.h"
+#include "e-source-webdav.h"
+
+#define E_SOURCE_REGISTRY_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SOURCE_REGISTRY, ESourceRegistryPrivate))
+
+#define SETTINGS_SCHEMA "org.gnome.Evolution.DefaultSources"
+
+struct _ESourceRegistryPrivate {
+ GHashTable *sources;
+ GHashTable *orphans;
+ GHashTable *monitors;
+ GSettings *settings;
+};
+
+enum {
+ PROP_0,
+ PROP_DEFAULT_ADDRESS_BOOK,
+ PROP_DEFAULT_CALENDAR,
+ PROP_DEFAULT_MEMO_LIST,
+ PROP_DEFAULT_TASK_LIST
+};
+
+enum {
+ LOAD_ERROR,
+ SOURCE_ADDED,
+ SOURCE_CHANGED,
+ SOURCE_REMOVED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+static ESourceRegistry *source_registry_singleton = NULL;
+
+G_DEFINE_TYPE (
+ ESourceRegistry,
+ e_source_registry,
+ G_TYPE_OBJECT)
+
+static void
+source_registry_settings_changed_cb (GSettings *settings,
+ const gchar *key,
+ ESourceRegistry *registry)
+{
+ /* We define a property name that matches every key in
+ * the "org.gnome.Evolution.DefaultSources" schema. */
+ g_object_notify (G_OBJECT (registry), key);
+}
+
+static void
+source_registry_source_changed_cb (ESource *source,
+ ESourceRegistry *registry)
+{
+ g_signal_emit (registry, signals[SOURCE_CHANGED], 0, source);
+}
+
+static void
+source_registry_unref_source (ESource *source)
+{
+ g_signal_handlers_disconnect_matched (
+ source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
+ source_registry_source_changed_cb, NULL);
+
+ g_object_unref (source);
+}
+
+static gboolean
+source_registry_find_parent (ESourceRegistry *registry,
+ ESource *source)
+{
+ GHashTable *orphans;
+ GPtrArray *array;
+ ESource *parent;
+ const gchar *uid;
+
+ /* If an ESource references a parent ESource and the parent
+ * ESource is not present in the registry, the child ESource
+ * is added to an orphan list until the referenced parent is
+ * added to the registry. */
+
+ uid = e_source_get_parent (source);
+
+ if (uid == NULL || *uid == '\0')
+ return TRUE;
+
+ parent = e_source_registry_lookup_by_uid (registry, uid);
+
+ if (parent != NULL) {
+ GNode *parent_node;
+ GNode *source_node;
+
+ parent_node = e_source_get_node (parent);
+ source_node = e_source_get_node (source);
+ g_node_append (parent_node, source_node);
+
+ return TRUE;
+ }
+
+ orphans = registry->priv->orphans;
+ array = g_hash_table_lookup (orphans, uid);
+
+ if (array == NULL) {
+ array = g_ptr_array_new_with_free_func (
+ (GDestroyNotify) g_object_unref);
+ g_hash_table_insert (orphans, g_strdup (uid), array);
+ }
+
+ g_ptr_array_add (array, g_object_ref (source));
+
+ return FALSE;
+}
+
+static void
+source_registry_adopt_orphans (ESourceRegistry *registry,
+ ESource *source)
+{
+ GHashTable *orphans;
+ GPtrArray *array;
+ const gchar *uid;
+ guint ii;
+
+ /* Check if a newly-added ESource has any orphan ESources
+ * that are waiting for it. The orphans can now be added
+ * to the registry as children of the newly-added ESource. */
+
+ uid = e_source_get_uid (source);
+
+ orphans = registry->priv->orphans;
+ array = g_hash_table_lookup (orphans, uid);
+
+ if (array == NULL)
+ return;
+
+ for (ii = 0; ii < array->len; ii++) {
+ ESource *orphan = g_ptr_array_index (array, ii);
+ e_source_registry_add_source (registry, orphan);
+ }
+
+ g_ptr_array_set_size (array, 0);
+}
+
+static void
+source_registry_monitor_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ ESourceRegistry *registry)
+{
+ gchar *basename;
+ gboolean hidden;
+
+ basename = g_file_get_basename (file);
+ hidden = g_str_has_prefix (basename, ".");
+ g_free (basename);
+
+ /* XXX Ignore hidden files so we don't try
+ * to load .goutputstream-XXXXXX files. */
+ if (hidden)
+ return;
+
+ if (event_type == G_FILE_MONITOR_EVENT_CREATED) {
+ GError *error = NULL;
+
+ e_source_registry_load_file (registry, file, &error);
+ if (error != NULL) {
+ e_source_registry_load_error (registry, file, error);
+ g_error_free (error);
+ }
+ }
+
+ if (event_type == G_FILE_MONITOR_EVENT_DELETED) {
+ ESource *source;
+
+ source = e_source_registry_lookup_by_file (registry, file);
+ if (source != NULL)
+ e_source_registry_remove_source (registry, source);
+ }
+}
+
+static gboolean
+source_registry_remove_cb (GNode *node,
+ ESourceRegistry *registry)
+{
+ ESource *source = E_SOURCE (node->data);
+ const gchar *uid;
+
+ source = E_SOURCE (node->data);
+ uid = e_source_get_uid (source);
+
+ g_object_ref (source);
+
+ if (g_hash_table_remove (registry->priv->sources, uid)) {
+ g_node_unlink (e_source_get_node (source));
+ g_signal_emit (registry, signals[SOURCE_REMOVED], 0, source);
+ }
+
+ g_object_unref (source);
+
+ return FALSE;
+}
+
+static void
+source_registry_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_DEFAULT_ADDRESS_BOOK:
+ e_source_registry_set_default_address_book (
+ E_SOURCE_REGISTRY (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_DEFAULT_CALENDAR:
+ e_source_registry_set_default_calendar (
+ E_SOURCE_REGISTRY (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_DEFAULT_MEMO_LIST:
+ e_source_registry_set_default_memo_list (
+ E_SOURCE_REGISTRY (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_DEFAULT_TASK_LIST:
+ e_source_registry_set_default_task_list (
+ E_SOURCE_REGISTRY (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_registry_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_DEFAULT_ADDRESS_BOOK:
+ g_value_set_object (
+ value,
+ e_source_registry_get_default_address_book (
+ E_SOURCE_REGISTRY (object)));
+ return;
+
+ case PROP_DEFAULT_CALENDAR:
+ g_value_set_object (
+ value,
+ e_source_registry_get_default_calendar (
+ E_SOURCE_REGISTRY (object)));
+ return;
+
+ case PROP_DEFAULT_MEMO_LIST:
+ g_value_set_object (
+ value,
+ e_source_registry_get_default_memo_list (
+ E_SOURCE_REGISTRY (object)));
+ return;
+
+ case PROP_DEFAULT_TASK_LIST:
+ g_value_set_object (
+ value,
+ e_source_registry_get_default_task_list (
+ E_SOURCE_REGISTRY (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_registry_dispose (GObject *object)
+{
+ ESourceRegistryPrivate *priv;
+
+ priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
+
+ g_hash_table_remove_all (priv->sources);
+ g_hash_table_remove_all (priv->orphans);
+ g_hash_table_remove_all (priv->monitors);
+
+ if (priv->settings != NULL) {
+ g_object_unref (priv->settings);
+ priv->settings = NULL;
+ }
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_source_registry_parent_class)->dispose (object);
+}
+
+static void
+source_registry_finalize (GObject *object)
+{
+ ESourceRegistryPrivate *priv;
+
+ priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
+
+ g_hash_table_destroy (priv->sources);
+ g_hash_table_destroy (priv->orphans);
+ g_hash_table_destroy (priv->monitors);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_source_registry_parent_class)->finalize (object);
+}
+
+static void
+e_source_registry_class_init (ESourceRegistryClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (ESourceRegistryPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = source_registry_set_property;
+ object_class->get_property = source_registry_get_property;
+ object_class->dispose = source_registry_dispose;
+ object_class->finalize = source_registry_finalize;
+
+ /* The property names correspond to the key names in the
+ * "org.gnome.Evolution.DefaultSources" GSettings schema. */
+
+ /**
+ * ESourceRegistry:default-address-book
+ *
+ * The default address book #ESource.
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_DEFAULT_ADDRESS_BOOK,
+ g_param_spec_object (
+ "default-address-book",
+ "Default Address Book",
+ "The default address book ESource",
+ E_TYPE_SOURCE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * ESourceRegistry:default-calendar
+ *
+ * The default calendar #ESource.
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_DEFAULT_CALENDAR,
+ g_param_spec_object (
+ "default-calendar",
+ "Default Calendar",
+ "The default calendar ESource",
+ E_TYPE_SOURCE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * ESourceRegistry:default-memo-list
+ *
+ * The default memo list #ESource.
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_DEFAULT_MEMO_LIST,
+ g_param_spec_object (
+ "default-memo-list",
+ "Default Memo List",
+ "The default memo list ESource",
+ E_TYPE_SOURCE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * ESourceRegistry:default-task-list
+ *
+ * The default task list #ESource.
+ **/
+ g_object_class_install_property (
+ object_class,
+ PROP_DEFAULT_TASK_LIST,
+ g_param_spec_object (
+ "default-task-list",
+ "Default Task List",
+ "The default task list ESource",
+ E_TYPE_SOURCE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * ESourceRegistry::load-error:
+ * @registry: the #DataSourceRegistry which emitted the signal
+ * @file: the #GFile being loaded
+ * @error: a #GError describing the error
+ *
+ * Emitted when an error occurs while loading or parsing a
+ * data source key file.
+ **/
+ signals[LOAD_ERROR] = g_signal_new (
+ "load-error",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESourceRegistryClass, load_error),
+ NULL, NULL,
+ e_marshal_VOID__OBJECT_BOXED,
+ G_TYPE_NONE, 2,
+ G_TYPE_FILE,
+ G_TYPE_ERROR | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+ /**
+ * ESourceRegistry::source-added:
+ * @registry: the #ESourceRegistry which emitted the signal
+ * @source: the newly-added #ESource
+ *
+ * Emitted when an #ESource is added to @registry.
+ **/
+ signals[SOURCE_ADDED] = g_signal_new (
+ "source-added",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESourceRegistryClass, source_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ E_TYPE_SOURCE);
+
+ /**
+ * ESourceRegistry::source-changed
+ * @registry: the #ESourceRegistry which emitted the signal
+ * @source: the #ESource that changed
+ *
+ * Emitted when an #ESource registered with @registry emits
+ * its #ESource::changed signal.
+ **/
+ signals[SOURCE_CHANGED] = g_signal_new (
+ "source-changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESourceRegistryClass, source_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ E_TYPE_SOURCE);
+
+ /**
+ * ESourceRegistry::source-removed:
+ * @registry: the #ESourceRegistry which emitted the signal
+ * @source: the #ESource that got removed
+ *
+ * Emitted when an #ESource is removed from @registry.
+ **/
+ signals[SOURCE_REMOVED] = g_signal_new (
+ "source-removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESourceRegistryClass, source_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ E_TYPE_SOURCE);
+
+ /* Register built-in ESourceExtension types. */
+ E_TYPE_SOURCE_ALARMS;
+ E_TYPE_SOURCE_AUTHENTICATION;
+ E_TYPE_SOURCE_AUTOCOMPLETE;
+ E_TYPE_SOURCE_OFFLINE;
+ E_TYPE_SOURCE_REFRESH;
+ E_TYPE_SOURCE_SECURITY;
+ E_TYPE_SOURCE_SELECTABLE;
+ E_TYPE_SOURCE_WEBDAV;
+}
+
+static void
+e_source_registry_init (ESourceRegistry *registry)
+{
+ registry->priv = E_SOURCE_REGISTRY_GET_PRIVATE (registry);
+
+ /* UID string -> ESource */
+ registry->priv->sources = g_hash_table_new_full (
+ (GHashFunc) g_str_hash,
+ (GEqualFunc) g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) source_registry_unref_source);
+
+ /* Parent UID string -> GQueue of ESources */
+ registry->priv->orphans = g_hash_table_new_full (
+ (GHashFunc) g_str_hash,
+ (GEqualFunc) g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_ptr_array_unref);
+
+ /* GFile -> GFileMonitor */
+ registry->priv->monitors = g_hash_table_new_full (
+ (GHashFunc) g_file_hash,
+ (GEqualFunc) g_file_equal,
+ (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) g_object_unref);
+
+ registry->priv->settings = g_settings_new (SETTINGS_SCHEMA);
+
+ g_signal_connect (
+ registry->priv->settings, "changed",
+ G_CALLBACK (source_registry_settings_changed_cb), registry);
+}
+
+/**
+ * e_source_registry_get_default:
+ *
+ * Gets a unique instance of #ESourceRegistry that you can share in your
+ * application without caring about memory management.
+ *
+ * Applications must call e_source_registry_load_sources() on the unique
+ * #ESourceRegistry instance before it can be used.
+ *
+ * Returns: a unique #ESourceRegistry
+ *
+ * Since: 2.92
+ **/
+ESourceRegistry *
+e_source_registry_get_default (void)
+{
+ if (G_UNLIKELY (source_registry_singleton == NULL))
+ source_registry_singleton =
+ g_object_new (E_TYPE_SOURCE_REGISTRY, NULL);
+
+ return source_registry_singleton;
+}
+
+/**
+ * e_source_registry_add_source:
+ * @registry: an #ESourceRegistry
+ * @source: an #ESource
+ *
+ * Adds @source to @registry.
+ *
+ * Since: 2.92
+ **/
+void
+e_source_registry_add_source (ESourceRegistry *registry,
+ ESource *source)
+{
+ const gchar *uid;
+
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ uid = e_source_get_uid (source);
+
+ /* Check if we already have this source in the registry. */
+ if (e_source_registry_lookup_by_uid (registry, uid) != NULL)
+ return;
+
+ /* Make sure the parent source (if any) is in the registry. */
+ if (!source_registry_find_parent (registry, source))
+ return;
+
+ g_signal_connect (
+ source, "changed",
+ G_CALLBACK (source_registry_source_changed_cb), registry);
+
+ g_hash_table_insert (
+ registry->priv->sources,
+ g_strdup (uid), g_object_ref (source));
+
+ g_signal_emit (registry, signals[SOURCE_ADDED], 0, source);
+
+ /* Adopt any orphans that have been waiting for this source. */
+ source_registry_adopt_orphans (registry, source);
+}
+
+/**
+ * e_source_registry_remove_source:
+ * @registry: an #ESourceRegistry
+ * @source: an #ESource
+ *
+ * Removes @source and its children from @registry.
+ *
+ * Since: 2.92
+ **/
+void
+e_source_registry_remove_source (ESourceRegistry *registry,
+ ESource *source)
+{
+ GNode *node;
+ const gchar *uid;
+
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ /* The system source cannot be removed. */
+ uid = e_source_get_uid (source);
+ if (g_strcmp0 (uid, "system") == 0)
+ return;
+
+ node = e_source_get_node (source);
+
+ /* Removing an ESource also removes its children. We remove
+ * children first so they are never without a parent source. */
+ g_node_traverse (
+ node, G_POST_ORDER, G_TRAVERSE_ALL, -1,
+ (GNodeTraverseFunc) source_registry_remove_cb, registry);
+}
+
+/**
+ * e_source_registry_load_sources:
+ * @registry: an #ESourceRegistry
+ * @error: return location for a #GError, or %NULL
+ *
+ * Loads data source key files from standard system-wide and user-specific
+ * locations. Because multiple errors can occur when loading multiple files,
+ * @error is only set if a directory can not be opened. If a key file fails
+ * to load, the error is broadcast through the #ESourceRegistry::load-error
+ * signal.
+ *
+ * Returns: %TRUE if the standard directories were successfully opened,
+ * but this does not imply the key files were successfully loaded.
+ *
+ * Since: 2.92
+ **/
+gboolean
+e_source_registry_load_sources (ESourceRegistry *registry,
+ GError **error)
+{
+ const gchar *data_dir;
+ gboolean success;
+ gchar *path;
+
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
+
+ /* Load the user's sources directory first so that user-specific
+ * data sources overshadow predefined data sources with identical
+ * UIDs. The "system" data source is one such example. */
+
+ data_dir = e_get_user_data_dir ();
+ path = g_build_filename (data_dir, "sources", NULL);
+ success = e_source_registry_load_directory (
+ registry, path, TRUE, error);
+ g_prefix_error (error, "%s: ", path);
+ g_free (path);
+
+ if (!success)
+ return FALSE;
+
+ data_dir = E_DATA_SERVER_PRIVDATADIR;
+ path = g_build_filename (data_dir, "sources", NULL);
+ success = e_source_registry_load_directory (
+ registry, path, FALSE, error);
+ g_prefix_error (error, "%s: ", path);
+ g_free (path);
+
+ return success;
+}
+
+/**
+ * e_source_registry_load_directory:
+ * @registry: an #ESourceRegistry
+ * @path: the path to the directory to load
+ * @monitor_for_changes: monitor the directory for changes
+ * @error: return location for a #GError, or %NULL
+ *
+ * Loads data source key files in @path. Because multiple errors can
+ * occur when loading multiple files, @error is only set if @path can
+ * not be opened. If a key file fails to load, the error is broadcast
+ * through the #ESourceRegistry::load-error signal.
+ *
+ * If @monitor_for_changes is %TRUE, then the @registry will emit
+ * ESourceRegistry::source-added and ESourceRegistry::source-removed
+ * signals when key files are created and deleted in @path.
+ *
+ * Returns: %TRUE if @path was successfully opened, but this
+ * does not imply the key files were successfully loaded
+ *
+ * Since: 2.92
+ **/
+gboolean
+e_source_registry_load_directory (ESourceRegistry *registry,
+ const gchar *path,
+ gboolean monitor_for_changes,
+ GError **error)
+{
+ GDir *dir;
+ GFile *file;
+ const gchar *name;
+
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
+ g_return_val_if_fail (path != NULL, FALSE);
+
+ /* If the directory doesn't exist then there's nothing to load.
+ * Note we do not use G_FILE_TEST_DIR here. If the given path
+ * exists but is not a directory then we let g_dir_open() fail. */
+ if (!g_file_test (path, G_FILE_TEST_EXISTS))
+ return TRUE;
+
+ dir = g_dir_open (path, 0, error);
+ if (dir == NULL)
+ return FALSE;
+
+ file = g_file_new_for_path (path);
+
+ while ((name = g_dir_read_name (dir)) != NULL) {
+ GFile *child;
+ GError *local_error = NULL;
+
+ /* XXX Ignore hidden files so we don't try
+ * to load .goutputstream-XXXXXX files. */
+ if (g_str_has_prefix (name, "."))
+ continue;
+
+ child = g_file_get_child (file, name);
+
+ e_source_registry_load_file (
+ registry, child, &local_error);
+
+ if (local_error != NULL) {
+ e_source_registry_load_error (
+ registry, child, local_error);
+ g_error_free (local_error);
+ }
+
+ g_object_unref (child);
+ }
+
+ g_dir_close (dir);
+
+ if (monitor_for_changes) {
+ GFileMonitor *monitor;
+
+ monitor = g_file_monitor_directory (
+ file, G_FILE_MONITOR_NONE, NULL, error);
+ if (monitor == NULL)
+ return FALSE;
+
+ g_signal_connect (
+ monitor, "changed",
+ G_CALLBACK (source_registry_monitor_changed),
+ registry);
+
+ g_hash_table_insert (
+ registry->priv->monitors,
+ g_object_ref (file), monitor);
+ }
+
+ return TRUE;
+}
+
+/**
+ * e_source_registry_load_file:
+ * @registry: an #ESourceRegistry
+ * @file: the data source key file to load
+ * @error: return location for a #GError, or %NULL
+ *
+ * Creates an #ESource for a native key file and adds it to @registry.
+ * If an error occurs, the function returns %NULL and sets @error.
+ *
+ * Returns: the newly-added #ESource, or %NULL on error
+ *
+ * Since: 2.92
+ **/
+ESource *
+e_source_registry_load_file (ESourceRegistry *registry,
+ GFile *file,
+ GError **error)
+{
+ ESource *source;
+
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+
+ /* Check if we already have this file loaded. */
+ source = e_source_registry_lookup_by_file (registry, file);
+ if (source != NULL)
+ return source;
+
+ /* Create a new ESource and add it to the registry. */
+ source = e_source_new (file, error);
+ if (source != NULL) {
+ e_source_registry_add_source (registry, source);
+ g_object_unref (source);
+ }
+
+ return source;
+}
+
+/**
+ * e_source_registry_load_error:
+ * @registry: an #ESourceRegistry
+ * @file: the #GFile that failed to load
+ * @error: a #GError describing the load error
+ *
+ * Emits the #ESourceRegistry::load-error signal.
+ *
+ * Since: 2.92
+ **/
+void
+e_source_registry_load_error (ESourceRegistry *registry,
+ GFile *file,
+ const GError *error)
+{
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+ g_return_if_fail (G_IS_FILE (file));
+ g_return_if_fail (error != NULL);
+
+ g_signal_emit (registry, signals[LOAD_ERROR], 0, file, error);
+}
+
+/**
+ * e_source_registry_lookup_by_file:
+ * @registry: an #ESourceRegistry
+ * @file: a #GFile
+ *
+ * Looks up an #ESource in @registry by its #GFile.
+ *
+ * Returns: an #ESource, or %NULL if no match was found
+ *
+ * Since: 2.92
+ **/
+ESource *
+e_source_registry_lookup_by_file (ESourceRegistry *registry,
+ GFile *file)
+{
+ ESource *source;
+ gchar *uid;
+
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+
+ uid = g_file_get_basename (file);
+ source = e_source_registry_lookup_by_uid (registry, uid);
+ g_free (uid);
+
+ return source;
+}
+
+/**
+ * e_source_registry_lookup_by_uid:
+ * @registry: an #ESourceRegistry
+ * @uid: a unique identifier string
+ *
+ * Looks up an #ESource in @registry by its unique identifier string.
+ *
+ * Returns: an #ESource, or %NULL if no match was found
+ *
+ * Since: 2.92
+ **/
+ESource *
+e_source_registry_lookup_by_uid (ESourceRegistry *registry,
+ const gchar *uid)
+{
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+ g_return_val_if_fail (uid != NULL, NULL);
+
+ return g_hash_table_lookup (registry->priv->sources, uid);
+}
+
+/**
+ * e_source_registry_list_sources:
+ * @registry: an #ESourceRegistry
+ * @extension_name: an extension name, or %NULL
+ *
+ * Returns a list of registered sources. If @extension_name is given,
+ * restrict the list to sources having that extension name. Free the
+ * returned list with g_list_free().
+ *
+ * Returns: a list of sources
+ *
+ * Since: 2.92
+ **/
+GList *
+e_source_registry_list_sources (ESourceRegistry *registry,
+ const gchar *extension_name)
+{
+ GList *list, *iter;
+ GList *trash = NULL;
+
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ list = g_hash_table_get_values (registry->priv->sources);
+ if (extension_name == NULL)
+ return list;
+
+ for (iter = list; iter != NULL; iter = g_list_next (iter)) {
+ ESource *source = E_SOURCE (iter->data);
+
+ if (!e_source_has_extension (source, extension_name))
+ trash = g_list_prepend (trash, iter);
+ }
+
+ for (iter = trash; iter != NULL; iter = g_list_next (iter))
+ list = g_list_delete_link (list, iter->data);
+
+ g_list_free (trash);
+
+ return list;
+}
+
+/* Helper for e_source_registry_list_sources_for_display() */
+static gint
+source_registry_compare_nodes (GNode *node_a,
+ GNode *node_b)
+{
+ ESource *source_a = E_SOURCE (node_a->data);
+ ESource *source_b = E_SOURCE (node_b->data);
+
+ /* The built-in "local" source comes first at depth 1. */
+
+ if (g_strcmp0 (e_source_get_uid (source_a), "local") == 0)
+ return -1;
+
+ if (g_strcmp0 (e_source_get_uid (source_b), "local") == 0)
+ return 1;
+
+ /* The built-in "system" source comes first at depth 2. */
+
+ if (g_strcmp0 (e_source_get_uid (source_a), "system") == 0)
+ return -1;
+
+ if (g_strcmp0 (e_source_get_uid (source_b), "system") == 0)
+ return 1;
+
+ return e_source_compare_by_display_name (source_a, source_b);
+}
+
+/* Helper for e_source_registry_list_sources_for_display() */
+static gboolean
+source_registry_prune_nodes (GNode *node,
+ const gchar *extension_name)
+{
+ GQueue queue = G_QUEUE_INIT;
+ GNode *child;
+
+ /* Unlink all the child nodes and place them in a queue. */
+ while ((child = g_node_first_child (node)) != NULL) {
+ g_node_unlink (child);
+ g_queue_push_tail (&queue, child);
+ }
+
+ /* Sort the queue by source name. */
+ g_queue_sort (
+ &queue, (GCompareDataFunc)
+ source_registry_compare_nodes, NULL);
+
+ /* Pop nodes off the head of the queue until the queue is empty.
+ * If the node has either its own children or the given extension
+ * name, put it back under the parent node (preserving the sorted
+ * order). Otherwise delete the node. */
+ while ((child = g_queue_pop_head (&queue)) != NULL) {
+ ESource *source = E_SOURCE (child->data);
+
+ if (extension_name == NULL)
+ g_node_append (node, child);
+
+ else if (e_source_has_extension (source, extension_name))
+ g_node_append (node, child);
+
+ else if (g_node_first_child (child) != NULL)
+ g_node_append (node, child);
+
+ else
+ g_node_destroy (child);
+ }
+
+ return FALSE;
+}
+
+/**
+ * e_source_registry_build_display_tree:
+ * @registry: an #ESourceRegistry
+ * @extension_name: an extension name, or %NULL
+ *
+ * Returns a single #GNode tree of registered sources that can be used to
+ * populate a #GtkTreeModel. (The root #GNode is just an empty placeholder.)
+ *
+ * Similar to e_source_registry_list_sources(), an @extension_name can be
+ * given to restrict the tree to sources having that extension name. Parents
+ * of matched sources are included in the tree regardless of whether they have
+ * an extension named @extension_name.
+ *
+ * Free the returned #GNode tree with g_node_destroy().
+ *
+ * Returns: a tree of sources, arranged for display
+ *
+ * Since: 2.92
+ **/
+GNode *
+e_source_registry_build_display_tree (ESourceRegistry *registry,
+ const gchar *extension_name)
+{
+ GNode *root;
+ GHashTableIter iter;
+ gpointer value;
+
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ root = g_node_new (NULL);
+
+ /* Copy each source tree and append it to the root node. */
+ g_hash_table_iter_init (&iter, registry->priv->sources);
+ while (g_hash_table_iter_next (&iter, NULL, &value)) {
+ ESource *source = E_SOURCE (value);
+ GNode *node = e_source_get_node (source);
+
+ if (node != NULL && G_NODE_IS_ROOT (node))
+ g_node_append (root, g_node_copy (node));
+ }
+
+ /* Prune unwanted nodes from the copied source trees.
+ * This must be done in "post" order (children first)
+ * since it reorders and deletes child nodes. */
+ g_node_traverse (
+ root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
+ (GNodeTraverseFunc) source_registry_prune_nodes,
+ (gpointer) extension_name);
+
+ return root;
+}
+
+/**
+ * e_source_registry_get_default_address_book:
+ * @registry: an #ESourceRegistry
+ *
+ * Returns the #ESource most recently passed to
+ * e_source_registry_set_default_address_book() either in this session
+ * or a previous session, or else falls back to the "system" #ESource.
+ * Therefore as long as data sources have been loaded into @registry,
+ * it should be safe to assume the return value is a valid #ESource.
+ *
+ * Returns: the default address book #ESource
+ *
+ * Since: 2.92
+ **/
+ESource *
+e_source_registry_get_default_address_book (ESourceRegistry *registry)
+{
+ const gchar *key = "default-address-book";
+ ESource *source;
+ gchar *uid;
+
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ uid = g_settings_get_string (registry->priv->settings, key);
+ source = e_source_registry_lookup_by_uid (registry, uid);
+ g_free (uid);
+
+ /* The "system" source should always be present. */
+ if (source == NULL)
+ source = e_source_registry_lookup_by_uid (registry, "system");
+
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ return source;
+}
+
+/**
+ * e_source_registry_set_default_address_book:
+ * @registry: an #ESourceRegistry
+ * @default_source: an address book #ESource, or %NULL
+ *
+ * Sets @default_source as the default address book. If @default_source
+ * is %NULL, the default address book is reset to the "system" #ESource.
+ * This setting will persist across sessions until changed.
+ *
+ * Since: 2.92
+ **/
+void
+e_source_registry_set_default_address_book (ESourceRegistry *registry,
+ ESource *default_source)
+{
+ const gchar *key = "default-address-book";
+ const gchar *uid = "system";
+
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+
+ if (default_source != NULL) {
+ g_return_if_fail (E_IS_SOURCE (default_source));
+ uid = e_source_get_uid (default_source);
+ }
+
+ g_settings_set_string (registry->priv->settings, key, uid);
+
+ /* The GSettings::changed signal will trigger a "notify" signal
+ * from the registry, so no need to call g_object_notify() here. */
+}
+
+/**
+ * e_source_registry_get_default_calendar:
+ * @registry: an #ESourceRegistry
+ *
+ * Returns the #ESource most recently passed to
+ * e_source_registry_set_default_calendar() either in this session
+ * or a previous session, or else falls back to the "system" #ESource.
+ * Therefore as long as data sources have been loaded into @registry,
+ * it should be safe to assume the return value is a valid #ESource.
+ *
+ * Returns: the default calendar #ESource
+ *
+ * Since: 2.92
+ **/
+ESource *
+e_source_registry_get_default_calendar (ESourceRegistry *registry)
+{
+ const gchar *key = "default-calendar";
+ ESource *source;
+ gchar *uid;
+
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ uid = g_settings_get_string (registry->priv->settings, key);
+ source = e_source_registry_lookup_by_uid (registry, uid);
+ g_free (uid);
+
+ /* The "system" source should always be present. */
+ if (source == NULL)
+ source = e_source_registry_lookup_by_uid (registry, "system");
+
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ return source;
+}
+
+/**
+ * e_source_registry_set_default_calendar:
+ * @registry: an #ESourceRegistry
+ * @default_source: a calendar #ESource, or %NULL
+ *
+ * Sets @default_source as the default calendar. If @default_source
+ * is %NULL, the default calendar is reset to the "system" #ESource.
+ * This setting will persist across sessions until changed.
+ *
+ * Since: 2.92
+ **/
+void
+e_source_registry_set_default_calendar (ESourceRegistry *registry,
+ ESource *default_source)
+{
+ const gchar *key = "default-calendar";
+ const gchar *uid = "system";
+
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+
+ if (default_source != NULL) {
+ g_return_if_fail (E_IS_SOURCE (default_source));
+ uid = e_source_get_uid (default_source);
+ }
+
+ g_settings_set_string (registry->priv->settings, key, uid);
+
+ /* The GSettings::changed signal will trigger a "notify" signal
+ * from the registry, so no need to call g_object_notify() here. */
+}
+
+/**
+ * e_source_registry_get_default_memo_list:
+ * @registry: an #ESourceRegistry
+ *
+ * Returns the #ESource most recently passed to
+ * e_source_registry_set_default_memo_list() either in this session
+ * or a previous session, or else falls back to the "system" #ESource.
+ * Therefore as long as data sources have been loaded into @registry,
+ * it should be safe to assume the return valud is a valid #Esource.
+ *
+ * Returns: the default memo list #ESource
+ *
+ * Since: 2.92
+ **/
+ESource *
+e_source_registry_get_default_memo_list (ESourceRegistry *registry)
+{
+ const gchar *key = "default-memo-list";
+ ESource *source;
+ gchar *uid;
+
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ uid = g_settings_get_string (registry->priv->settings, key);
+ source = e_source_registry_lookup_by_uid (registry, uid);
+ g_free (uid);
+
+ /* The "system" source should always be present. */
+ if (source == NULL)
+ source = e_source_registry_lookup_by_uid (registry, "system");
+
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ return source;
+}
+
+/**
+ * e_source_registry_set_default_memo_list:
+ * @registry: an #ESourceRegistry
+ * @default_source: a memo list #ESource, or %NULL
+ *
+ * Sets @default_source as the default memo list. If @default_source
+ * is %NULL, the default memo list is reset to the "system" #ESource.
+ * This setting will persist across sessions until changed.
+ *
+ * Since: 2.92
+ **/
+void
+e_source_registry_set_default_memo_list (ESourceRegistry *registry,
+ ESource *default_source)
+{
+ const gchar *key = "default-memo-list";
+ const gchar *uid = "system";
+
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+
+ if (default_source != NULL) {
+ g_return_if_fail (E_IS_SOURCE (default_source));
+ uid = e_source_get_uid (default_source);
+ }
+
+ g_settings_set_string (registry->priv->settings, key, uid);
+
+ /* The GSettings::changed signal will trigger a "notify" signal
+ * from the registry, so no need to call g_object_notify() here. */
+}
+
+/**
+ * e_source_registry_get_default_task_list:
+ * @registry: an #ESourceRegistry
+ *
+ * Returns the #ESource most recently passed to
+ * e_source_registry_set_default_task_list() either in this session
+ * or a previous session, or else falls back to the "system" #ESource.
+ * Therefore as long as data sources have been loaded into @registry,
+ * it should be safe to assume the return value is a valid #ESource.
+ *
+ * Returns: the default task list #ESource
+ *
+ * Since: 2.92
+ **/
+ESource *
+e_source_registry_get_default_task_list (ESourceRegistry *registry)
+{
+ const gchar *key = "default-task-list";
+ ESource *source;
+ gchar *uid;
+
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ uid = g_settings_get_string (registry->priv->settings, key);
+ source = e_source_registry_lookup_by_uid (registry, uid);
+ g_free (uid);
+
+ /* The "system" source should always be present. */
+ if (source == NULL)
+ source = e_source_registry_lookup_by_uid (registry, "system");
+
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ return source;
+}
+
+/**
+ * e_source_registry_set_default_task_list:
+ * @registry: an #ESourceRegistry
+ * @default_source: a task list #ESource, or %NULL
+ *
+ * Sets @default_source as the default task list. If @default_source
+ * is %NULL, the default task list is reset to the "system" #ESource.
+ * This setting will persist across sessions until changed.
+ *
+ * Since: 2.92
+ **/
+void
+e_source_registry_set_default_task_list (ESourceRegistry *registry,
+ ESource *default_source)
+{
+ const gchar *key = "default-task-list";
+ const gchar *uid = "system";
+
+ g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+
+ if (default_source != NULL) {
+ g_return_if_fail (E_IS_SOURCE (default_source));
+ uid = e_source_get_uid (default_source);
+ }
+
+ g_settings_set_string (registry->priv->settings, key, uid);
+
+ /* The GSettings::changed signal will trigger a "notify" signal
+ * from the registry, so no need to call g_object_notify() here. */
+}
diff --git a/libedataserver/e-source-registry.h b/libedataserver/e-source-registry.h
new file mode 100644
index 0000000..9d43b2b
--- /dev/null
+++ b/libedataserver/e-source-registry.h
@@ -0,0 +1,127 @@
+/*
+ * e-source-registry.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_REGISTRY_H
+#define E_SOURCE_REGISTRY_H
+
+#include <libedataserver/e-source.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_REGISTRY \
+ (e_source_registry_get_type ())
+#define E_SOURCE_REGISTRY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_REGISTRY, ESourceRegistry))
+#define E_SOURCE_REGISTRY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_REGISTRY, ESourceRegistryClass))
+#define E_IS_SOURCE_REGISTRY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_REGISTRY))
+#define E_IS_SOURCE_REGISTRY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_REGISTRY))
+#define E_SOURCE_REGISTRY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_REGISTRY, ESourceRegistryClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceRegistry ESourceRegistry;
+typedef struct _ESourceRegistryClass ESourceRegistryClass;
+typedef struct _ESourceRegistryPrivate ESourceRegistryPrivate;
+
+struct _ESourceRegistry {
+ GObject parent;
+ ESourceRegistryPrivate *priv;
+};
+
+struct _ESourceRegistryClass {
+ GObjectClass parent_class;
+
+ /* Signals */
+ void (*load_error) (ESourceRegistry *registry,
+ GFile *file,
+ const GError *error);
+ void (*source_added) (ESourceRegistry *registry,
+ ESource *source);
+ void (*source_changed) (ESourceRegistry *registry,
+ ESource *source);
+ void (*source_removed) (ESourceRegistry *registry,
+ ESource *source);
+};
+
+GType e_source_registry_get_type (void) G_GNUC_CONST;
+ESourceRegistry *
+ e_source_registry_get_default (void);
+void e_source_registry_add_source (ESourceRegistry *registry,
+ ESource *source);
+void e_source_registry_remove_source (ESourceRegistry *registry,
+ ESource *source);
+gboolean e_source_registry_load_sources (ESourceRegistry *registry,
+ GError **error);
+gboolean e_source_registry_load_directory
+ (ESourceRegistry *registry,
+ const gchar *path,
+ gboolean monitor_for_changes,
+ GError **error);
+ESource * e_source_registry_load_file (ESourceRegistry *registry,
+ GFile *file,
+ GError **error);
+void e_source_registry_load_error (ESourceRegistry *registry,
+ GFile *file,
+ const GError *error);
+ESource * e_source_registry_lookup_by_file
+ (ESourceRegistry *registry,
+ GFile *file);
+ESource * e_source_registry_lookup_by_uid (ESourceRegistry *registry,
+ const gchar *uid);
+GList * e_source_registry_list_sources (ESourceRegistry *registry,
+ const gchar *extension_name);
+GNode * e_source_registry_build_display_tree
+ (ESourceRegistry *registry,
+ const gchar *extension_name);
+
+/* The following is a front-end for the "org.gnome.Evolution.DefaultSources"
+ * GSettings schema, except that it gets and sets ESource objects instead of
+ * ESource UID strings. */
+
+ESource * e_source_registry_get_default_address_book
+ (ESourceRegistry *registry);
+void e_source_registry_set_default_address_book
+ (ESourceRegistry *registry,
+ ESource *default_source);
+ESource * e_source_registry_get_default_calendar
+ (ESourceRegistry *registry);
+void e_source_registry_set_default_calendar
+ (ESourceRegistry *registry,
+ ESource *default_source);
+ESource * e_source_registry_get_default_memo_list
+ (ESourceRegistry *registry);
+void e_source_registry_set_default_memo_list
+ (ESourceRegistry *registry,
+ ESource *default_source);
+ESource * e_source_registry_get_default_task_list
+ (ESourceRegistry *registry);
+void e_source_registry_set_default_task_list
+ (ESourceRegistry *registry,
+ ESource *default_source);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_REGISTRY_H */
diff --git a/libedataserver/e-source-security.c b/libedataserver/e-source-security.c
new file mode 100644
index 0000000..b930ffd
--- /dev/null
+++ b/libedataserver/e-source-security.c
@@ -0,0 +1,203 @@
+/*
+ * e-source-security.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-security.h"
+
+#define E_SOURCE_SECURITY_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SOURCE_SECURITY, ESourceSecurityPrivate))
+
+#define SECURE_METHOD "tls"
+
+struct _ESourceSecurityPrivate {
+ gchar *method;
+};
+
+enum {
+ PROP_0,
+ PROP_METHOD,
+ PROP_SECURE
+};
+
+G_DEFINE_TYPE (
+ ESourceSecurity,
+ e_source_security,
+ E_TYPE_SOURCE_EXTENSION)
+
+static void
+source_security_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_METHOD:
+ e_source_security_set_method (
+ E_SOURCE_SECURITY (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_SECURE:
+ e_source_security_set_secure (
+ E_SOURCE_SECURITY (object),
+ g_value_get_boolean (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_security_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_METHOD:
+ g_value_set_string (
+ value,
+ e_source_security_get_method (
+ E_SOURCE_SECURITY (object)));
+ return;
+
+ case PROP_SECURE:
+ g_value_set_boolean (
+ value,
+ e_source_security_get_secure (
+ E_SOURCE_SECURITY (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_security_finalize (GObject *object)
+{
+ ESourceSecurityPrivate *priv;
+
+ priv = E_SOURCE_SECURITY_GET_PRIVATE (object);
+
+ g_free (priv->method);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_source_security_parent_class)->finalize (object);
+}
+
+static void
+e_source_security_class_init (ESourceSecurityClass *class)
+{
+ GObjectClass *object_class;
+ ESourceExtensionClass *extension_class;
+
+ g_type_class_add_private (class, sizeof (ESourceSecurityPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = source_security_set_property;
+ object_class->get_property = source_security_get_property;
+ object_class->finalize = source_security_finalize;
+
+ extension_class = E_SOURCE_EXTENSION_CLASS (class);
+ extension_class->name = E_SOURCE_EXTENSION_SECURITY;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_METHOD,
+ g_param_spec_string (
+ "method",
+ "Method",
+ "Security method",
+ "none",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SECURE,
+ g_param_spec_boolean (
+ "secure",
+ "Secure",
+ "Secure the network connection",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_source_security_init (ESourceSecurity *extension)
+{
+ extension->priv = E_SOURCE_SECURITY_GET_PRIVATE (extension);
+}
+
+const gchar *
+e_source_security_get_method (ESourceSecurity *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_SECURITY (extension), FALSE);
+
+ return extension->priv->method;
+}
+
+void
+e_source_security_set_method (ESourceSecurity *extension,
+ const gchar *method)
+{
+ GObject *object;
+
+ g_return_if_fail (E_IS_SOURCE_SECURITY (extension));
+
+ /* Convert empty strings to "none". */
+ if (method == NULL || *method == '\0')
+ method = "none";
+
+ g_free (extension->priv->method);
+ extension->priv->method = g_strdup (method);
+
+ object = G_OBJECT (extension);
+ g_object_freeze_notify (object);
+ g_object_notify (object, "method");
+ g_object_notify (object, "secure");
+ g_object_thaw_notify (object);
+}
+
+gboolean
+e_source_security_get_secure (ESourceSecurity *extension)
+{
+ const gchar *method;
+
+ g_return_val_if_fail (E_IS_SOURCE_SECURITY (extension), FALSE);
+
+ method = e_source_security_get_method (extension);
+ g_return_val_if_fail (method != NULL, FALSE);
+
+ return (g_strcmp0 (method, "none") != 0);
+}
+
+void
+e_source_security_set_secure (ESourceSecurity *extension,
+ gboolean secure)
+{
+ const gchar *method;
+
+ g_return_if_fail (E_IS_SOURCE_SECURITY (extension));
+
+ method = secure ? SECURE_METHOD : "none";
+ e_source_security_set_method (extension, method);
+}
diff --git a/libedataserver/e-source-security.h b/libedataserver/e-source-security.h
new file mode 100644
index 0000000..16a6fe6
--- /dev/null
+++ b/libedataserver/e-source-security.h
@@ -0,0 +1,70 @@
+/*
+ * e-source-security.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_SECURITY_H
+#define E_SOURCE_SECURITY_H
+
+#include <libedataserver/e-source-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_SECURITY \
+ (e_source_security_get_type ())
+#define E_SOURCE_SECURITY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_SECURITY, ESourceSecurity))
+#define E_SOURCE_SECURITY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_SECURITY, ESourceSecurityClass))
+#define E_IS_SOURCE_SECURITY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_SECURITY))
+#define E_IS_SOURCE_SECURITY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_SECURITY))
+#define E_SOURCE_SECURITY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_SECURITY, ESourceSecurityClass))
+
+#define E_SOURCE_EXTENSION_SECURITY "Security"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceSecurity ESourceSecurity;
+typedef struct _ESourceSecurityClass ESourceSecurityClass;
+typedef struct _ESourceSecurityPrivate ESourceSecurityPrivate;
+
+struct _ESourceSecurity {
+ ESourceExtension parent;
+ ESourceSecurityPrivate *priv;
+};
+
+struct _ESourceSecurityClass {
+ ESourceExtensionClass parent_class;
+};
+
+GType e_source_security_get_type (void);
+const gchar * e_source_security_get_method (ESourceSecurity *extension);
+void e_source_security_set_method (ESourceSecurity *extension,
+ const gchar *method);
+gboolean e_source_security_get_secure (ESourceSecurity *extension);
+void e_source_security_set_secure (ESourceSecurity *extension,
+ gboolean secure);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_SECURITY_H */
diff --git a/libedataserver/e-source-selectable.c b/libedataserver/e-source-selectable.c
new file mode 100644
index 0000000..5a28805
--- /dev/null
+++ b/libedataserver/e-source-selectable.c
@@ -0,0 +1,235 @@
+/*
+ * e-source-selectable.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-selectable.h"
+
+#define E_SOURCE_SELECTABLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SOURCE_SELECTABLE, ESourceSelectablePrivate))
+
+struct _ESourceSelectablePrivate {
+ gchar *color;
+ gboolean enabled;
+ gboolean writable_hint;
+};
+
+enum {
+ PROP_0,
+ PROP_COLOR,
+ PROP_ENABLED,
+ PROP_WRITABLE_HINT
+};
+
+G_DEFINE_ABSTRACT_TYPE (
+ ESourceSelectable,
+ e_source_selectable,
+ E_TYPE_SOURCE_EXTENSION)
+
+static void
+source_selectable_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_COLOR:
+ e_source_selectable_set_color (
+ E_SOURCE_SELECTABLE (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_ENABLED:
+ e_source_selectable_set_enabled (
+ E_SOURCE_SELECTABLE (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_WRITABLE_HINT:
+ e_source_selectable_set_writable_hint (
+ E_SOURCE_SELECTABLE (object),
+ g_value_get_boolean (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_selectable_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_COLOR:
+ g_value_set_string (
+ value,
+ e_source_selectable_get_color (
+ E_SOURCE_SELECTABLE (object)));
+ return;
+
+ case PROP_ENABLED:
+ g_value_set_boolean (
+ value,
+ e_source_selectable_get_enabled (
+ E_SOURCE_SELECTABLE (object)));
+ return;
+
+ case PROP_WRITABLE_HINT:
+ g_value_set_boolean (
+ value,
+ e_source_selectable_get_writable_hint (
+ E_SOURCE_SELECTABLE (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_selectable_finalize (GObject *object)
+{
+ ESourceSelectablePrivate *priv;
+
+ priv = E_SOURCE_SELECTABLE_GET_PRIVATE (object);
+
+ g_free (priv->color);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_source_selectable_parent_class)->finalize (object);
+}
+
+static void
+e_source_selectable_class_init (ESourceSelectableClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (ESourceSelectablePrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = source_selectable_set_property;
+ object_class->get_property = source_selectable_get_property;
+ object_class->finalize = source_selectable_finalize;
+
+ /* We do not provide an extension name,
+ * which is why the class is abstract. */
+
+ g_object_class_install_property (
+ object_class,
+ PROP_COLOR,
+ g_param_spec_string (
+ "color",
+ "Color",
+ "Textual specification of a color",
+ "#becedd",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ENABLED,
+ g_param_spec_boolean (
+ "enabled",
+ "Enabled",
+ "Whether the data source is enabled",
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_WRITABLE_HINT,
+ g_param_spec_boolean (
+ "writable-hint",
+ "Writable Hint",
+ "Hints at whether the data source is writable",
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+}
+
+static void
+e_source_selectable_init (ESourceSelectable *extension)
+{
+ extension->priv = E_SOURCE_SELECTABLE_GET_PRIVATE (extension);
+}
+
+const gchar *
+e_source_selectable_get_color (ESourceSelectable *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_SELECTABLE (extension), NULL);
+
+ return extension->priv->color;
+}
+
+void
+e_source_selectable_set_color (ESourceSelectable *extension,
+ const gchar *color)
+{
+ g_return_if_fail (E_IS_SOURCE_SELECTABLE (extension));
+ g_return_if_fail (color != NULL);
+
+ g_free (extension->priv->color);
+ extension->priv->color = g_strdup (color);
+
+ g_object_notify (G_OBJECT (extension), "color");
+}
+
+gboolean
+e_source_selectable_get_enabled (ESourceSelectable *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_SELECTABLE (extension), FALSE);
+
+ return extension->priv->enabled;
+}
+
+void
+e_source_selectable_set_enabled (ESourceSelectable *extension,
+ gboolean enabled)
+{
+ g_return_if_fail (E_IS_SOURCE_SELECTABLE (extension));
+
+ extension->priv->enabled = enabled;
+
+ g_object_notify (G_OBJECT (extension), "enabled");
+}
+
+gboolean
+e_source_selectable_get_writable_hint (ESourceSelectable *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_SELECTABLE (extension), FALSE);
+
+ return extension->priv->writable_hint;
+}
+
+void
+e_source_selectable_set_writable_hint (ESourceSelectable *extension,
+ gboolean writable_hint)
+{
+ g_return_if_fail (E_IS_SOURCE_SELECTABLE (extension));
+
+ extension->priv->writable_hint = writable_hint;
+
+ g_object_notify (G_OBJECT (extension), "writable-hint");
+}
diff --git a/libedataserver/e-source-selectable.h b/libedataserver/e-source-selectable.h
new file mode 100644
index 0000000..2fdf52c
--- /dev/null
+++ b/libedataserver/e-source-selectable.h
@@ -0,0 +1,73 @@
+/*
+ * e-source-selectable.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_SELECTABLE_H
+#define E_SOURCE_SELECTABLE_H
+
+#include <libedataserver/e-source-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_SELECTABLE \
+ (e_source_selectable_get_type ())
+#define E_SOURCE_SELECTABLE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_SELECTABLE, ESourceSelectable))
+#define E_SOURCE_SELECTABLE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_SELECTABLE, ESourceSelectableClass))
+#define E_IS_SOURCE_SELECTABLE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_SELECTABLE))
+#define E_IS_SOURCE_SELECTABLE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_SELECTABLE))
+#define E_SOURCE_SELECTABLE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_SELECTABLE, ESourceSelectableClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceSelectable ESourceSelectable;
+typedef struct _ESourceSelectableClass ESourceSelectableClass;
+typedef struct _ESourceSelectablePrivate ESourceSelectablePrivate;
+
+struct _ESourceSelectable {
+ ESourceExtension parent;
+ ESourceSelectablePrivate *priv;
+};
+
+struct _ESourceSelectableClass {
+ ESourceExtensionClass parent_class;
+};
+
+GType e_source_selectable_get_type (void);
+const gchar * e_source_selectable_get_color (ESourceSelectable *extension);
+void e_source_selectable_set_color (ESourceSelectable *extension,
+ const gchar *color);
+gboolean e_source_selectable_get_enabled (ESourceSelectable *extension);
+void e_source_selectable_set_enabled (ESourceSelectable *extension,
+ gboolean enabled);
+gboolean e_source_selectable_get_writable_hint
+ (ESourceSelectable *extension);
+void e_source_selectable_set_writable_hint
+ (ESourceSelectable *extension,
+ gboolean writable_hint);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_SELECTABLE_H */
diff --git a/libedataserver/e-source-webdav.c b/libedataserver/e-source-webdav.c
new file mode 100644
index 0000000..2114f5f
--- /dev/null
+++ b/libedataserver/e-source-webdav.c
@@ -0,0 +1,552 @@
+/*
+ * e-source-webdav.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-webdav.h"
+
+#include <libedataserver/e-source-authentication.h>
+#include <libedataserver/e-source-security.h>
+
+#define E_SOURCE_WEBDAV_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SOURCE_WEBDAV, ESourceWebdavPrivate))
+
+struct _ESourceWebdavPrivate {
+ gchar *display_name;
+ gboolean avoid_ifmatch;
+ SoupURI *uri;
+};
+
+enum {
+ PROP_0,
+ PROP_AVOID_IFMATCH,
+ PROP_DISPLAY_NAME,
+ PROP_HOST,
+ PROP_PATH,
+ PROP_PORT,
+ PROP_SECURE,
+ PROP_SOUP_URI,
+ PROP_USER
+};
+
+G_DEFINE_TYPE (
+ ESourceWebdav,
+ e_source_webdav,
+ E_TYPE_SOURCE_EXTENSION)
+
+static gboolean
+source_webdav_user_to_method (GBinding *binding,
+ const GValue *source_value,
+ GValue *target_value,
+ gpointer user_data)
+{
+ const gchar *user;
+
+ user = g_value_get_string (source_value);
+ if (user == NULL || *user == '\0')
+ g_value_set_string (target_value, "none");
+ else
+ g_value_set_string (target_value, "plain/password");
+
+ return TRUE;
+}
+
+static const gchar *
+source_webdav_get_host (ESourceWebdav *extension)
+{
+ return extension->priv->uri->host;
+}
+
+static void
+source_webdav_set_host (ESourceWebdav *extension,
+ const gchar *host)
+{
+ GObject *object = G_OBJECT (extension);
+
+ soup_uri_set_host (extension->priv->uri, host);
+
+ g_object_freeze_notify (object);
+ g_object_notify (object, "host");
+ g_object_notify (object, "soup-uri");
+ g_object_thaw_notify (object);
+}
+
+static const gchar *
+source_webdav_get_path (ESourceWebdav *extension)
+{
+ return extension->priv->uri->path;
+}
+
+static void
+source_webdav_set_path (ESourceWebdav *extension,
+ const gchar *path)
+{
+ GObject *object = G_OBJECT (extension);
+
+ if (path == NULL || *path == '\0')
+ path = "/";
+
+ soup_uri_set_path (extension->priv->uri, path);
+
+ g_object_freeze_notify (object);
+ g_object_notify (object, "path");
+ g_object_notify (object, "soup-uri");
+ g_object_thaw_notify (object);
+}
+
+static guint16
+source_webdav_get_port (ESourceWebdav *extension)
+{
+ return (guint16) extension->priv->uri->port;
+}
+
+static void
+source_webdav_set_port (ESourceWebdav *extension,
+ guint16 port)
+{
+ GObject *object = G_OBJECT (extension);
+
+ soup_uri_set_port (extension->priv->uri, port);
+
+ g_object_freeze_notify (object);
+ g_object_notify (object, "port");
+ g_object_notify (object, "soup-uri");
+ g_object_thaw_notify (object);
+}
+
+static gboolean
+source_webdav_get_secure (ESourceWebdav *extension)
+{
+ return (extension->priv->uri->scheme == SOUP_URI_SCHEME_HTTPS);
+}
+
+static void
+source_webdav_set_secure (ESourceWebdav *extension,
+ gboolean secure)
+{
+ GObject *object = G_OBJECT (extension);
+ const gchar *scheme;
+
+ scheme = secure ? SOUP_URI_SCHEME_HTTPS : SOUP_URI_SCHEME_HTTP;
+ soup_uri_set_scheme (extension->priv->uri, scheme);
+
+ g_object_freeze_notify (object);
+ g_object_notify (object, "port");
+ g_object_notify (object, "secure");
+ g_object_notify (object, "soup-uri");
+ g_object_thaw_notify (object);
+}
+
+static const gchar *
+source_webdav_get_user (ESourceWebdav *extension)
+{
+ return extension->priv->uri->user;
+}
+
+static void
+source_webdav_set_user (ESourceWebdav *extension,
+ const gchar *user)
+{
+ GObject *object = G_OBJECT (extension);
+
+ soup_uri_set_user (extension->priv->uri, user);
+
+ g_object_freeze_notify (object);
+ g_object_notify (object, "user");
+ g_object_notify (object, "soup-uri");
+ g_object_thaw_notify (object);
+}
+
+static void
+source_webdav_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_AVOID_IFMATCH:
+ e_source_webdav_set_avoid_ifmatch (
+ E_SOURCE_WEBDAV (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_DISPLAY_NAME:
+ e_source_webdav_set_display_name (
+ E_SOURCE_WEBDAV (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_HOST:
+ source_webdav_set_host (
+ E_SOURCE_WEBDAV (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_PATH:
+ source_webdav_set_path (
+ E_SOURCE_WEBDAV (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_PORT:
+ source_webdav_set_port (
+ E_SOURCE_WEBDAV (object),
+ g_value_get_uint (value));
+ return;
+
+ case PROP_SECURE:
+ source_webdav_set_secure (
+ E_SOURCE_WEBDAV (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_SOUP_URI:
+ e_source_webdav_set_soup_uri (
+ E_SOURCE_WEBDAV (object),
+ g_value_get_boxed (value));
+ return;
+
+ case PROP_USER:
+ source_webdav_set_user (
+ E_SOURCE_WEBDAV (object),
+ g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_webdav_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_AVOID_IFMATCH:
+ g_value_set_boolean (
+ value,
+ e_source_webdav_get_avoid_ifmatch (
+ E_SOURCE_WEBDAV (object)));
+ return;
+
+ case PROP_DISPLAY_NAME:
+ g_value_set_string (
+ value,
+ e_source_webdav_get_display_name (
+ E_SOURCE_WEBDAV (object)));
+ return;
+
+ case PROP_HOST:
+ g_value_set_string (
+ value,
+ source_webdav_get_host (
+ E_SOURCE_WEBDAV (object)));
+ return;
+
+ case PROP_PATH:
+ g_value_set_string (
+ value,
+ source_webdav_get_path (
+ E_SOURCE_WEBDAV (object)));
+ return;
+
+ case PROP_PORT:
+ g_value_set_uint (
+ value,
+ source_webdav_get_port (
+ E_SOURCE_WEBDAV (object)));
+ return;
+
+ case PROP_SECURE:
+ g_value_set_boolean (
+ value,
+ source_webdav_get_secure (
+ E_SOURCE_WEBDAV (object)));
+ return;
+
+ case PROP_SOUP_URI:
+ g_value_take_boxed (
+ value,
+ e_source_webdav_get_soup_uri (
+ E_SOURCE_WEBDAV (object)));
+ return;
+
+ case PROP_USER:
+ g_value_set_string (
+ value,
+ source_webdav_get_user (
+ E_SOURCE_WEBDAV (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_webdav_finalize (GObject *object)
+{
+ ESourceWebdavPrivate *priv;
+
+ priv = E_SOURCE_WEBDAV_GET_PRIVATE (object);
+
+ soup_uri_free (priv->uri);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_source_webdav_parent_class)->finalize (object);
+}
+
+static void
+source_webdav_constructed (GObject *object)
+{
+ ESource *source;
+ ESourceExtension *this_extension;
+ ESourceExtension *other_extension;
+ const gchar *extension_name;
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_source_webdav_parent_class)->constructed (object);
+
+ this_extension = E_SOURCE_EXTENSION (object);
+ source = e_source_extension_get_source (this_extension);
+
+ /* Bind to properties of other extensions for convenience. */
+
+ extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+ other_extension = e_source_get_extension (source, extension_name);
+
+ g_object_bind_property (
+ other_extension, "host",
+ this_extension, "host",
+ G_BINDING_BIDIRECTIONAL |
+ G_BINDING_SYNC_CREATE);
+
+ g_object_bind_property (
+ other_extension, "port",
+ this_extension, "port",
+ G_BINDING_BIDIRECTIONAL |
+ G_BINDING_SYNC_CREATE);
+
+ g_object_bind_property (
+ other_extension, "user",
+ this_extension, "user",
+ G_BINDING_BIDIRECTIONAL |
+ G_BINDING_SYNC_CREATE);
+
+ /* XXX Avoid binding the "user" and "method" properties of
+ * other_extension until we require GLib 2.28, or else
+ * it causes a crash in GBinding. I reported this in:
+ * https://bugzilla.gnome.org/show_bug.cgi?id=639873. */
+ g_object_bind_property_full (
+ this_extension, "user",
+ other_extension, "method",
+ G_BINDING_SYNC_CREATE,
+ source_webdav_user_to_method,
+ NULL,
+ NULL, (GDestroyNotify) NULL);
+
+ extension_name = E_SOURCE_EXTENSION_SECURITY;
+ other_extension = e_source_get_extension (source, extension_name);
+
+ g_object_bind_property (
+ other_extension, "secure",
+ this_extension, "secure",
+ G_BINDING_BIDIRECTIONAL |
+ G_BINDING_SYNC_CREATE);
+}
+
+static void
+e_source_webdav_class_init (ESourceWebdavClass *class)
+{
+ GObjectClass *object_class;
+ ESourceExtensionClass *extension_class;
+
+ g_type_class_add_private (class, sizeof (ESourceWebdavPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = source_webdav_set_property;
+ object_class->get_property = source_webdav_get_property;
+ object_class->finalize = source_webdav_finalize;
+ object_class->constructed = source_webdav_constructed;
+
+ extension_class = E_SOURCE_EXTENSION_CLASS (class);
+ extension_class->name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_AVOID_IFMATCH,
+ g_param_spec_boolean (
+ "avoid-ifmatch",
+ "Avoid If-Match",
+ "Work around a bug in old Apache servers",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_DISPLAY_NAME,
+ g_param_spec_string (
+ "display-name",
+ "Display Name",
+ "Display name of the WebDAV resource",
+ "",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_HOST,
+ g_param_spec_string (
+ "host",
+ "Host",
+ "WebDAV service host name",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_PATH,
+ g_param_spec_string (
+ "path",
+ "Path",
+ "WebDAV service path",
+ "/",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_PORT,
+ g_param_spec_uint (
+ "port",
+ "Port",
+ "WebDAV service port number",
+ 0, G_MAXUINT16, 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SECURE,
+ g_param_spec_boolean (
+ "secure",
+ "Secure",
+ "Secure the network connection",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SOUP_URI,
+ g_param_spec_boxed (
+ "soup-uri",
+ "SoupURI",
+ "WebDAV service as a SoupURI",
+ SOUP_TYPE_URI,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_USER,
+ g_param_spec_string (
+ "user",
+ "User",
+ "WebDAV service user name",
+ NULL,
+ G_PARAM_READWRITE));
+}
+
+static void
+e_source_webdav_init (ESourceWebdav *extension)
+{
+ extension->priv = E_SOURCE_WEBDAV_GET_PRIVATE (extension);
+ extension->priv->uri = soup_uri_new (NULL);
+}
+
+gboolean
+e_source_webdav_get_avoid_ifmatch (ESourceWebdav *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), FALSE);
+
+ return extension->priv->avoid_ifmatch;
+}
+
+void
+e_source_webdav_set_avoid_ifmatch (ESourceWebdav *extension,
+ gboolean avoid_ifmatch)
+{
+ g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
+
+ extension->priv->avoid_ifmatch = avoid_ifmatch;
+
+ g_object_notify (G_OBJECT (extension), "avoid-ifmatch");
+}
+
+const gchar *
+e_source_webdav_get_display_name (ESourceWebdav *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
+
+ return extension->priv->display_name;
+}
+
+void
+e_source_webdav_set_display_name (ESourceWebdav *extension,
+ const gchar *display_name)
+{
+ g_return_if_fail (E_IS_SOURCE_WEBDAV (extension));
+
+ g_free (extension->priv->display_name);
+ extension->priv->display_name = g_strdup (display_name);
+
+ g_object_notify (G_OBJECT (extension), "display-name");
+}
+
+SoupURI *
+e_source_webdav_get_soup_uri (ESourceWebdav *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_WEBDAV (extension), NULL);
+
+ return soup_uri_copy (extension->priv->uri);
+}
+
+void
+e_source_webdav_set_soup_uri (ESourceWebdav *extension,
+ SoupURI *uri)
+{
+ GObject *object;
+
+ g_return_if_fail (extension != NULL);
+ g_return_if_fail (uri != NULL);
+
+ soup_uri_free (extension->priv->uri);
+ extension->priv->uri = soup_uri_copy (uri);
+
+ object = G_OBJECT (extension);
+ g_object_freeze_notify (object);
+ g_object_notify (object, "host");
+ g_object_notify (object, "path");
+ g_object_notify (object, "port");
+ g_object_notify (object, "secure");
+ g_object_notify (object, "soup-uri");
+ g_object_notify (object, "user");
+ g_object_thaw_notify (object);
+}
+
diff --git a/libedataserver/e-source-webdav.h b/libedataserver/e-source-webdav.h
new file mode 100644
index 0000000..457f90d
--- /dev/null
+++ b/libedataserver/e-source-webdav.h
@@ -0,0 +1,95 @@
+/*
+ * e-source-webdav.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_WEBDAV_H
+#define E_SOURCE_WEBDAV_H
+
+/* This class exists in libedataserver because we have several
+ * WebDAV-based backends. Each of these backends is free to use
+ * this class directly or subclass it with additional settings.
+ * Subclasses should override the extension name.
+ *
+ * The SoupURI is parsed into components and distributed across
+ * several other built-in extensions such as Authentication and
+ * Security. */
+
+#include <libsoup/soup.h>
+#include <libedataserver/e-source-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_WEBDAV \
+ (e_source_webdav_get_type ())
+#define E_SOURCE_WEBDAV(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_WEBDAV, ESourceWebdav))
+#define E_SOURCE_WEBDAV_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_WEBDAV, ESourceWebdavClass))
+#define E_IS_SOURCE_WEBDAV(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_WEBDAV))
+#define E_IS_SOURCE_WEBDAV_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_WEBDAV))
+#define E_SOURCE_WEBDAV_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_WEBDAV, ESourceWebdavClass))
+
+#define E_SOURCE_EXTENSION_WEBDAV_BACKEND "WebDAV Backend"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceWebdav ESourceWebdav;
+typedef struct _ESourceWebdavClass ESourceWebdavClass;
+typedef struct _ESourceWebdavPrivate ESourceWebdavPrivate;
+
+struct _ESourceWebdav {
+ ESourceExtension parent;
+ ESourceWebdavPrivate *priv;
+};
+
+struct _ESourceWebdavClass {
+ ESourceExtensionClass parent_class;
+};
+
+GType e_source_webdav_get_type (void);
+const gchar * e_source_webdav_get_display_name
+ (ESourceWebdav *extension);
+void e_source_webdav_set_display_name
+ (ESourceWebdav *extension,
+ const gchar *display_name);
+SoupURI * e_source_webdav_get_soup_uri (ESourceWebdav *extension);
+void e_source_webdav_set_soup_uri (ESourceWebdav *extension,
+ SoupURI *uri);
+
+/* XXX This setting works around a bug [1] in older Apache mod_dav
+ * versions. We may deprecate this once Apache 2.2.8 or newer
+ * becomes sufficiently ubiquitous, or we figure out a way to
+ * detect and work around the bug automatically.
+ *
+ * [1] https://issues.apache.org/bugzilla/show_bug.cgi?id=38034
+ */
+gboolean e_source_webdav_get_avoid_ifmatch
+ (ESourceWebdav *extension);
+void e_source_webdav_set_avoid_ifmatch
+ (ESourceWebdav *extension,
+ gboolean avoid_ifmatch);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_WEBDAV_H */
diff --git a/libedataserver/e-source.c b/libedataserver/e-source.c
index 49121db..ade9614 100644
--- a/libedataserver/e-source.c
+++ b/libedataserver/e-source.c
@@ -1,958 +1,1300 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-source.c
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+/*
+ * e-source.c
*
* This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
*
* 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.
+ * Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
*
- * Author: Ettore Perazzoli <ettore ximian com>
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "e-source.h"
+#include <config.h>
#include <string.h>
+
+#include <glib/gi18n-lib.h>
+
+#include "e-data-server-util.h"
+#include "e-source-extension.h"
#include "e-uid.h"
-#include "e-source.h"
-#define ES_CLASS(obj) E_SOURCE_CLASS (G_OBJECT_GET_CLASS (obj))
+#define E_SOURCE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SOURCE, ESourcePrivate))
-/* Private members. */
+#define E_SOURCE_GROUP_NAME "Data Source"
struct _ESourcePrivate {
- ESourceGroup *group;
+ GFile *file;
+ GNode node;
+ gchar *backend_name;
+ gchar *display_name;
+ gchar *parent;
gchar *uid;
- gchar *name;
- gchar *relative_uri;
- gchar *absolute_uri;
-
- gboolean readonly;
-
- gchar *color_spec;
- GHashTable *properties;
+ GKeyFile *key_file;
+ GHashTable *extensions;
+ GFileMonitor *file_monitor;
};
-/* Signals. */
+enum {
+ PROP_0,
+ PROP_BACKEND_NAME,
+ PROP_DISPLAY_NAME,
+ PROP_FILE,
+ PROP_PARENT,
+ PROP_UID
+};
enum {
CHANGED,
LAST_SIGNAL
};
-static guint signals[LAST_SIGNAL] = { 0 };
-/* Callbacks. */
+static guint signals[LAST_SIGNAL];
+
+static void e_source_initable_init (GInitableIface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+ ESource,
+ e_source,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (
+ G_TYPE_INITABLE,
+ e_source_initable_init))
static void
-group_weak_notify (ESource *source,
- GObject **where_the_object_was)
+source_find_extension_classes_rec (GType parent_type,
+ GHashTable *hash_table)
{
- source->priv->group = NULL;
+ GType *children;
+ guint n_children, ii;
- g_signal_emit (source, signals[CHANGED], 0);
-}
+ children = g_type_children (parent_type, &n_children);
-/* GObject methods. */
+ for (ii = 0; ii < n_children; ii++) {
+ GType type = children[ii];
+ ESourceExtensionClass *class;
+ gpointer key;
-G_DEFINE_TYPE (ESource, e_source, G_TYPE_OBJECT)
+ /* Recurse over the child's children. */
+ source_find_extension_classes_rec (type, hash_table);
-static void
-impl_finalize (GObject *object)
-{
- ESourcePrivate *priv = E_SOURCE (object)->priv;
+ /* Skip abstract types. */
+ if (G_TYPE_IS_ABSTRACT (type))
+ continue;
- g_free (priv->uid);
- g_free (priv->name);
- g_free (priv->relative_uri);
- g_free (priv->absolute_uri);
- g_free (priv->color_spec);
+ class = g_type_class_ref (type);
+ key = (gpointer) class->name;
- g_hash_table_destroy (priv->properties);
+ if (key != NULL)
+ g_hash_table_insert (hash_table, key, class);
+ else
+ g_type_class_unref (class);
+ }
- g_free (priv);
+ g_free (children);
+}
- (* G_OBJECT_CLASS (e_source_parent_class)->finalize) (object);
+static GHashTable *
+source_find_extension_classes (void)
+{
+ GHashTable *hash_table;
+
+ hash_table = g_hash_table_new_full (
+ (GHashFunc) g_str_hash,
+ (GEqualFunc) g_str_equal,
+ (GDestroyNotify) NULL,
+ (GDestroyNotify) g_type_class_unref);
+
+ source_find_extension_classes_rec (
+ E_TYPE_SOURCE_EXTENSION, hash_table);
+
+ return hash_table;
}
-static void
-impl_dispose (GObject *object)
+static gchar *
+source_name_to_key (const gchar *name)
{
- ESourcePrivate *priv = E_SOURCE (object)->priv;
+ gboolean uppercase = TRUE;
+ gchar *key, *cp;
+ gint ii;
+
+ /* Convert the property name to CamelCase. */
+
+ key = cp = g_malloc0 (strlen (name) + 1);
- if (priv->group != NULL) {
- g_object_weak_unref (G_OBJECT (priv->group), (GWeakNotify) group_weak_notify, object);
- priv->group = NULL;
+ for (ii = 0; name[ii] != '\0'; ii++) {
+ if (g_ascii_isalnum (name[ii]) && uppercase) {
+ *cp++ = g_ascii_toupper (name[ii]);
+ uppercase = FALSE;
+ } else if (name[ii] == '-' || name[ii] == '_')
+ uppercase = TRUE;
+ else
+ *cp++ = name[ii];
}
- (* G_OBJECT_CLASS (e_source_parent_class)->dispose) (object);
+ return key;
}
-/* Initialization. */
-
static void
-e_source_class_init (ESourceClass *class)
+source_set_key_file_from_property (GObject *object,
+ GParamSpec *pspec,
+ GKeyFile *key_file,
+ const gchar *group_name)
{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GValue *pvalue;
+ GValue *svalue;
+ gchar *key;
+
+ pvalue = g_slice_new0 (GValue);
+ g_value_init (pvalue, pspec->value_type);
+ g_object_get_property (object, pspec->name, pvalue);
+
+ svalue = g_slice_new0 (GValue);
+ g_value_init (svalue, G_TYPE_STRING);
+
+ key = source_name_to_key (pspec->name);
+
+ /* For the most part we can just transform any supported
+ * property type to a string, with a couple exceptions. */
+
+ /* Transforming a boolean GValue to a string results in
+ * "TRUE" or "FALSE" (all uppercase), but GKeyFile only
+ * recognizes "true" or "false" (all lowercase). So we
+ * have to use g_key_file_set_boolean(). */
+ if (G_VALUE_HOLDS_BOOLEAN (pvalue)) {
+ gboolean v_boolean = g_value_get_boolean (pvalue);
+ g_key_file_set_boolean (key_file, group_name, key, v_boolean);
+
+ /* String GValues may contain characters that need escaping. */
+ } else if (G_VALUE_HOLDS_STRING (pvalue)) {
+ const gchar *v_string = g_value_get_string (pvalue);
+ g_key_file_set_string (
+ key_file, group_name, key,
+ (v_string != NULL) ? v_string : "");
+
+ /* Transforming an enum GValue to a string results in
+ * the GEnumValue name. We want the shorter nickname. */
+ } else if (G_VALUE_HOLDS_ENUM (pvalue)) {
+ GParamSpecEnum *enum_pspec;
+ GEnumClass *enum_class;
+ GEnumValue *enum_value;
+ gint value;
+
+ enum_pspec = G_PARAM_SPEC_ENUM (pspec);
+ enum_class = enum_pspec->enum_class;
+
+ value = g_value_get_enum (pvalue);
+ enum_value = g_enum_get_value (enum_class, value);
+
+ if (enum_value == NULL) {
+ value = enum_pspec->default_value;
+ enum_value = g_enum_get_value (enum_class, value);
+ }
- object_class->dispose = impl_dispose;
- object_class->finalize = impl_finalize;
+ if (enum_value != NULL)
+ g_key_file_set_string (
+ key_file, group_name, key,
+ enum_value->value_nick);
+
+ /* For GValues holding a GFile object we save the URI. */
+ } else if (G_VALUE_HOLDS (pvalue, G_TYPE_FILE)) {
+ GFile *file = g_value_get_object (pvalue);
+ gchar *uri = NULL;
+
+ if (file != NULL)
+ uri = g_file_get_uri (file);
+ g_key_file_set_string (
+ key_file, group_name, key,
+ (uri != NULL) ? uri : "");
+ g_free (uri);
+
+ } else if (g_value_transform (pvalue, svalue)) {
+ const gchar *value = g_value_get_string (svalue);
+ g_key_file_set_value (key_file, group_name, key, value);
+ }
- signals[CHANGED] =
- g_signal_new ("changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ESourceClass, changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ g_free (key);
+ g_value_unset (pvalue);
+ g_value_unset (svalue);
+ g_slice_free (GValue, pvalue);
+ g_slice_free (GValue, svalue);
}
static void
-e_source_init (ESource *source)
+source_set_property_from_key_file (GObject *object,
+ GParamSpec *pspec,
+ GKeyFile *key_file,
+ const gchar *group_name)
{
- ESourcePrivate *priv;
+ gchar *key;
+ GValue *value;
+ GError *error = NULL;
+
+ value = g_slice_new0 (GValue);
+ key = source_name_to_key (pspec->name);
+
+ if (G_IS_PARAM_SPEC_CHAR (pspec) ||
+ G_IS_PARAM_SPEC_UCHAR (pspec) ||
+ G_IS_PARAM_SPEC_INT (pspec) ||
+ G_IS_PARAM_SPEC_UINT (pspec) ||
+ G_IS_PARAM_SPEC_LONG (pspec) ||
+ G_IS_PARAM_SPEC_ULONG (pspec)) {
+ gint v_int;
+
+ v_int = g_key_file_get_integer (
+ key_file, group_name, key, &error);
+ if (error == NULL) {
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, v_int);
+ }
- priv = g_new0 (ESourcePrivate, 1);
- source->priv = priv;
+ } else if (G_IS_PARAM_SPEC_BOOLEAN (pspec)) {
+ gboolean v_boolean;
- priv->properties = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_free);
-}
+ v_boolean = g_key_file_get_boolean (
+ key_file, group_name, key, &error);
+ if (error == NULL) {
+ g_value_init (value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (value, v_boolean);
+ }
-/* Private methods. */
+ } else if (G_IS_PARAM_SPEC_ENUM (pspec)) {
+ gchar *nick;
+
+ nick = g_key_file_get_string (
+ key_file, group_name, key, &error);
+ if (error == NULL) {
+ GParamSpecEnum *enum_pspec;
+ GEnumValue *enum_value;
+
+ enum_pspec = G_PARAM_SPEC_ENUM (pspec);
+ enum_value = g_enum_get_value_by_nick (
+ enum_pspec->enum_class, nick);
+ if (enum_value != NULL) {
+ g_value_init (value, pspec->value_type);
+ g_value_set_enum (value, enum_value->value);
+ }
+ g_free (nick);
+ }
-static gboolean
-set_color_spec (ESource *source,
- const gchar *color_spec)
-{
- ESourcePrivate *priv = source->priv;
- gboolean do_cmp;
+ } else if (G_IS_PARAM_SPEC_FLOAT (pspec) ||
+ G_IS_PARAM_SPEC_DOUBLE (pspec)) {
+ gdouble v_double;
- if (color_spec == priv->color_spec)
- return FALSE;
+ v_double = g_key_file_get_double (
+ key_file, group_name, key, &error);
+ if (error == NULL) {
+ g_value_init (value, G_TYPE_DOUBLE);
+ g_value_set_double (value, v_double);
+ }
- do_cmp = (color_spec != NULL && priv->color_spec != NULL);
- if (do_cmp && g_ascii_strcasecmp (color_spec, priv->color_spec) == 0)
- return FALSE;
+ } else if (G_IS_PARAM_SPEC_STRING (pspec)) {
+ gchar *v_string;
- g_free (priv->color_spec);
- priv->color_spec = g_strdup (color_spec);
+ /* Get the localized string if present. */
+ v_string = g_key_file_get_locale_string (
+ key_file, group_name, key, NULL, &error);
+ if (error == NULL) {
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, v_string);
+ g_free (v_string);
+ }
- return TRUE;
-}
+ } else if (g_type_is_a (pspec->value_type, G_TYPE_FILE)) {
+ gchar *uri;
+
+ /* Create the GFile from the URI string. */
+ uri = g_key_file_get_locale_string (
+ key_file, group_name, key, NULL, &error);
+ if (error == NULL) {
+ GFile *file = NULL;
+ if (uri != NULL && *uri != '\0')
+ file = g_file_new_for_uri (uri);
+ g_value_init (value, pspec->value_type);
+ g_value_take_object (value, file);
+ g_free (uri);
+ }
-/* Public methods. */
+ } else {
+ g_warning (
+ "No GKeyFile-to-GValue converter defined "
+ "for type '%s'", G_VALUE_TYPE_NAME (value));
+ }
-ESource *
-e_source_new (const gchar *name,
- const gchar *relative_uri)
+ /* If a value could not be retrieved from the key
+ * file, restore the property to its default value. */
+ if (error != NULL) {
+ g_value_init (value, pspec->value_type);
+ g_param_value_set_default (pspec, value);
+ g_error_free (error);
+ }
+
+ if (G_IS_VALUE (value)) {
+ g_object_set_property (object, pspec->name, value);
+ g_value_unset (value);
+ }
+
+ g_slice_free (GValue, value);
+ g_free (key);
+}
+
+static void
+source_load_from_key_file (GObject *object,
+ GKeyFile *key_file,
+ const gchar *group_name)
{
- ESource *source;
+ GObjectClass *class;
+ GParamSpec **properties;
+ guint n_properties, ii;
- g_return_val_if_fail (name != NULL, NULL);
- g_return_val_if_fail (relative_uri != NULL, NULL);
+ class = G_OBJECT_GET_CLASS (object);
+ properties = g_object_class_list_properties (class, &n_properties);
- source = g_object_new (e_source_get_type (), NULL);
- source->priv->uid = e_uid_new ();
+ g_object_freeze_notify (object);
+
+ for (ii = 0; ii < n_properties; ii++) {
+ if (properties[ii]->flags & E_SOURCE_PARAM_SETTING) {
+ source_set_property_from_key_file (
+ object, properties[ii], key_file, group_name);
+ }
+ }
- e_source_set_name (source, name);
- e_source_set_relative_uri (source, relative_uri);
- return source;
+ g_object_thaw_notify (object);
+
+ g_free (properties);
}
-ESource *
-e_source_new_with_absolute_uri (const gchar *name,
- const gchar *absolute_uri)
+static void
+source_save_to_key_file (GObject *object,
+ GKeyFile *key_file,
+ const gchar *group_name)
{
- ESource *source;
+ GObjectClass *class;
+ GParamSpec **properties;
+ guint n_properties, ii;
- g_return_val_if_fail (name != NULL, NULL);
- g_return_val_if_fail (absolute_uri != NULL, NULL);
+ class = G_OBJECT_GET_CLASS (object);
+ properties = g_object_class_list_properties (class, &n_properties);
- source = g_object_new (e_source_get_type (), NULL);
- source->priv->uid = e_uid_new ();
+ for (ii = 0; ii < n_properties; ii++) {
+ if (properties[ii]->flags & E_SOURCE_PARAM_SETTING) {
+ source_set_key_file_from_property (
+ object, properties[ii], key_file, group_name);
+ }
+ }
- e_source_set_name (source, name);
- e_source_set_absolute_uri (source, absolute_uri);
- return source;
+ g_free (properties);
}
-ESource *
-e_source_new_from_xml_node (xmlNodePtr node)
+static void
+source_file_monitor_changed (GFileMonitor *file_monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ ESource *source)
{
- ESource *source;
- xmlChar *uid;
+ GError *error = NULL;
- uid = xmlGetProp (node, (xmlChar*)"uid");
- if (uid == NULL)
- return NULL;
+ /* Ignore file deletion events. */
+ if (event_type != G_FILE_MONITOR_EVENT_DELETED)
+ e_source_reload (source, &error);
- source = g_object_new (e_source_get_type (), NULL);
+ /* FIXME Need better error handling. */
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+}
- source->priv->uid = g_strdup ((gchar *)uid);
- xmlFree (uid);
+static void
+source_setup_file_monitor (ESource *source)
+{
+ GFile *file;
- if (e_source_update_from_xml_node (source, node, NULL))
- return source;
+ file = e_source_get_file (source);
- g_object_unref (source);
- return NULL;
+ if (source->priv->file_monitor != NULL)
+ g_object_unref (source->priv->file_monitor);
+
+ source->priv->file_monitor = g_file_monitor (
+ file, G_FILE_MONITOR_NONE, NULL, NULL);
+
+ if (source->priv->file_monitor != NULL)
+ g_signal_connect (
+ source->priv->file_monitor, "changed",
+ G_CALLBACK (source_file_monitor_changed), source);
}
static void
-import_properties (ESource *source,
- xmlNodePtr prop_root)
+source_set_file (ESource *source,
+ GFile *file)
{
- ESourcePrivate *priv = source->priv;
- xmlNodePtr prop_node;
+ g_return_if_fail (source->priv->file == NULL);
- for (prop_node = prop_root->children; prop_node; prop_node = prop_node->next) {
- xmlChar *name, *value;
+ if (G_IS_FILE (file))
+ g_object_ref (file);
+ else {
+ const gchar *data_dir;
+ gchar *uid = e_uid_new ();
+ gchar *path;
- if (!prop_node->name || strcmp ((gchar *)prop_node->name, "property"))
- continue;
+ e_filename_make_safe (uid);
- name = xmlGetProp (prop_node, (xmlChar*)"name");
- value = xmlGetProp (prop_node, (xmlChar*)"value");
+ data_dir = e_get_user_data_dir ();
+ path = g_build_filename (data_dir, "sources", uid, NULL);
- if (name && value)
- g_hash_table_insert (priv->properties, g_strdup ((gchar *)name), g_strdup ((gchar *)value));
+ file = g_file_new_for_path (path);
- if (name)
- xmlFree (name);
- if (value)
- xmlFree (value);
+ g_free (path);
+ g_free (uid);
}
+
+ source->priv->file = file;
+ source->priv->uid = g_file_get_basename (file);
+
+ source_setup_file_monitor (source);
}
-typedef struct
+static void
+source_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
- gboolean equal;
- GHashTable *table2;
-} hash_compare_data;
+ switch (property_id) {
+ case PROP_BACKEND_NAME:
+ e_source_set_backend_name (
+ E_SOURCE (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_DISPLAY_NAME:
+ e_source_set_display_name (
+ E_SOURCE (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_FILE:
+ source_set_file (
+ E_SOURCE (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_PARENT:
+ e_source_set_parent (
+ E_SOURCE (object),
+ g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
static void
-compare_str_hash (gpointer key, gpointer value, hash_compare_data *cd)
+source_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- gpointer value2 = g_hash_table_lookup (cd->table2, key);
- if (value2 == NULL || g_str_equal (value, value2) == FALSE)
- cd->equal = FALSE;
+ switch (property_id) {
+ case PROP_BACKEND_NAME:
+ g_value_set_string (
+ value, e_source_get_backend_name (
+ E_SOURCE (object)));
+ return;
+
+ case PROP_DISPLAY_NAME:
+ g_value_set_string (
+ value, e_source_get_display_name (
+ E_SOURCE (object)));
+ return;
+
+ case PROP_FILE:
+ g_value_set_object (
+ value, e_source_get_file (
+ E_SOURCE (object)));
+ return;
+
+ case PROP_PARENT:
+ g_value_set_string (
+ value, e_source_get_parent (
+ E_SOURCE (object)));
+ return;
+
+ case PROP_UID:
+ g_value_set_string (
+ value, e_source_get_uid (
+ E_SOURCE (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
-static gboolean
-compare_str_hashes (GHashTable *table1, GHashTable *table2)
+static void
+source_dispose (GObject *object)
{
- hash_compare_data cd;
+ ESourcePrivate *priv;
- if (g_hash_table_size (table1) != g_hash_table_size (table2))
- return FALSE;
+ priv = E_SOURCE_GET_PRIVATE (object);
+
+ if (priv->file != NULL) {
+ g_object_unref (priv->file);
+ priv->file = NULL;
+ }
+
+ if (priv->file_monitor != NULL) {
+ g_object_unref (priv->file_monitor);
+ priv->file_monitor = NULL;
+ }
- cd.equal = TRUE;
- cd.table2 = table2;
- g_hash_table_foreach (table1, (GHFunc) compare_str_hash, &cd);
- return cd.equal;
+ g_hash_table_remove_all (priv->extensions);
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_source_parent_class)->dispose (object);
}
-/**
- * e_source_update_from_xml_node:
- * @source: An ESource.
- * @node: A pointer to the node to parse.
- *
- * Update the ESource properties from @node.
- *
- * Returns: %TRUE if the data in @node was recognized and parsed into
- * acceptable values for @source, %FALSE otherwise.
- **/
-gboolean
-e_source_update_from_xml_node (ESource *source,
- xmlNodePtr node,
- gboolean *changed_return)
-{
- xmlChar *name;
- xmlChar *relative_uri;
- xmlChar *absolute_uri;
- xmlChar *color_spec;
- xmlChar *color;
- gboolean retval = FALSE;
- gboolean changed = FALSE;
-
- name = xmlGetProp (node, (xmlChar*)"name");
- relative_uri = xmlGetProp (node, (xmlChar*)"relative_uri");
- absolute_uri = xmlGetProp (node, (xmlChar*)"uri");
- color_spec = xmlGetProp (node, (xmlChar*)"color_spec");
- color = xmlGetProp (node, (xmlChar*)"color"); /* obsolete */
-
- if (name == NULL || (relative_uri == NULL && absolute_uri == NULL))
- goto done;
-
- if (color_spec != NULL && color != NULL)
- goto done;
-
- if (source->priv->name == NULL
- || strcmp ((gchar *)name, source->priv->name) != 0
- || (source->priv->relative_uri == NULL && relative_uri != NULL)
- || (source->priv->relative_uri != NULL && relative_uri == NULL)
- || (relative_uri && source->priv->relative_uri && strcmp ((gchar *)relative_uri, source->priv->relative_uri) != 0)) {
- gchar *abs_uri = NULL;
-
- g_free (source->priv->name);
- source->priv->name = g_strdup ((gchar *)name);
-
- if (source->priv->group) {
- abs_uri = e_source_build_absolute_uri (source);
- }
+static void
+source_finalize (GObject *object)
+{
+ ESourcePrivate *priv;
- if (abs_uri && source->priv->absolute_uri && g_str_equal (abs_uri, source->priv->absolute_uri)) {
- /* reset the absolute uri to NULL to be regenerated when asked for,
- but only when it was generated also before */
- g_free (source->priv->absolute_uri);
- source->priv->absolute_uri = NULL;
- } else if (source->priv->absolute_uri &&
- source->priv->relative_uri &&
- g_str_has_suffix (source->priv->absolute_uri, source->priv->relative_uri)) {
- gchar *tmp = source->priv->absolute_uri;
+ priv = E_SOURCE_GET_PRIVATE (object);
- tmp[strlen (tmp) - strlen (source->priv->relative_uri)] = 0;
- source->priv->absolute_uri = g_strconcat (tmp, (gchar *)relative_uri, NULL);
+ g_node_unlink (&priv->node);
- g_free (tmp);
- }
+ g_free (priv->backend_name);
+ g_free (priv->display_name);
+ g_free (priv->parent);
+ g_free (priv->uid);
- g_free (abs_uri);
+ g_key_file_free (priv->key_file);
+ g_hash_table_destroy (priv->extensions);
- g_free (source->priv->relative_uri);
- source->priv->relative_uri = g_strdup ((gchar *)relative_uri);
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_source_parent_class)->finalize (object);
+}
- changed = TRUE;
- }
+static void
+source_notify (GObject *object,
+ GParamSpec *pspec)
+{
+ e_source_changed (E_SOURCE (object));
+}
- if (absolute_uri != NULL) {
- g_free (source->priv->absolute_uri);
+static gboolean
+source_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean success;
+ GError *local_error = NULL;
- if (relative_uri && g_str_equal ((const gchar *) relative_uri, "system") &&
- (g_str_has_prefix ((const gchar *) absolute_uri, "file:") || g_str_equal ((const gchar *) absolute_uri, "local:/system")))
- source->priv->absolute_uri = NULL;
- else
- source->priv->absolute_uri = g_strdup ((gchar *)absolute_uri);
- changed = TRUE;
- }
+ success = e_source_reload (E_SOURCE (initable), &local_error);
- if (color == NULL) {
- /* It is okay for color_spec to be NULL. */
- changed |= set_color_spec (source, (gchar *)color_spec);
- } else {
- gchar buffer[8];
- g_snprintf (buffer, sizeof (buffer), "#%s", color);
- changed |= set_color_spec (source, buffer);
- }
+ /* The key file will not exist yet if this is a new data source. */
+ if (g_error_matches (local_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
+ g_clear_error (&local_error);
+ success = TRUE;
- if (g_hash_table_size (source->priv->properties) && !node->children) {
- g_hash_table_destroy (source->priv->properties);
- source->priv->properties = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_free);
- changed = TRUE;
- }
+ } else if (local_error != NULL)
+ g_propagate_error (error, local_error);
- for (node = node->children; node; node = node->next) {
- if (!node->name)
- continue;
+ return success;
+}
- if (!strcmp ((gchar *)node->name, "properties")) {
- GHashTable *temp = source->priv->properties;
- source->priv->properties = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_free);
- import_properties (source, node);
- if (!compare_str_hashes (temp, source->priv->properties))
- changed = TRUE;
- g_hash_table_destroy (temp);
- break;
- }
- }
+static void
+e_source_class_init (ESourceClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (ESourcePrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = source_set_property;
+ object_class->get_property = source_get_property;
+ object_class->dispose = source_dispose;
+ object_class->finalize = source_finalize;
+ object_class->notify = source_notify;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_BACKEND_NAME,
+ g_param_spec_string (
+ "backend-name",
+ "Backend Name",
+ "The name of the backend handling the data source",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_DISPLAY_NAME,
+ g_param_spec_string (
+ "display-name",
+ "Display Name",
+ "The human-readable name of the data source",
+ _("New Source"),
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_FILE,
+ g_param_spec_object (
+ "file",
+ "File",
+ "The key file for the data source",
+ G_TYPE_FILE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_PARENT,
+ g_param_spec_string (
+ "parent",
+ "Parent",
+ "The unique identity of the parent data source",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_UID,
+ g_param_spec_string (
+ "uid",
+ "UID",
+ "The unique identity of the data source",
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ signals[CHANGED] = g_signal_new (
+ "changed",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
+ G_STRUCT_OFFSET (ESourceClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
- retval = TRUE;
+static void
+e_source_initable_init (GInitableIface *interface)
+{
+ interface->init = source_initable_init;
+}
- done:
- if (changed)
- g_signal_emit (source, signals[CHANGED], 0);
+static void
+e_source_init (ESource *source)
+{
+ GHashTable *extensions;
- if (changed_return != NULL)
- *changed_return = changed;
+ extensions = g_hash_table_new_full (
+ (GHashFunc) g_str_hash,
+ (GEqualFunc) g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
- if (name != NULL)
- xmlFree (name);
- if (relative_uri != NULL)
- xmlFree (relative_uri);
- if (absolute_uri != NULL)
- xmlFree (absolute_uri);
- if (color_spec != NULL)
- xmlFree (color_spec);
- if (color != NULL)
- xmlFree (color);
+ source->priv = E_SOURCE_GET_PRIVATE (source);
+ source->priv->key_file = g_key_file_new ();
+ source->priv->extensions = extensions;
- return retval;
+ memset (&source->priv->node, 0, sizeof (GNode));
+ source->priv->node.data = source;
}
/**
- * e_source_name_from_xml_node:
- * @node: A pointer to an XML node.
+ * e_source_new:
+ * @file: a #GFile, or %NULL
+ * @error: return location for a #GError, or %NULL
*
- * Assuming that @node is a valid ESource specification, retrieve the name of
- * the source from it.
+ * Creates a new #ESource for the key file described by @file. If the
+ * key file does not exist, cannot be opened, has syntax errors or fails
+ * to pass some basic integrity checks, the function returns %NULL and
+ * sets @error.
*
- * Returns: Name of the source in the specified @node. The caller must
- * free the string.
+ * If @file is %NULL, the #ESource will generate a new unique identifier
+ * string and construct a #GFile from it. This is useful when creating a
+ * new data source. The key file will be written to the user's "sources"
+ * directory after changes are applied to the returned #ESource.
+ *
+ * Returns: a newly-created #ESource, or %NULL on error
+ *
+ * Since: 2.92
**/
-gchar *
-e_source_uid_from_xml_node (xmlNodePtr node)
+ESource *
+e_source_new (GFile *file,
+ GError **error)
{
- xmlChar *uid = xmlGetProp (node, (xmlChar*)"uid");
- gchar *retval;
+ g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
- if (uid == NULL)
- return NULL;
-
- retval = g_strdup ((gchar *)uid);
- xmlFree (uid);
- return retval;
+ return g_initable_new (
+ E_TYPE_SOURCE, NULL, error, "file", file, NULL);
}
-gchar *
-e_source_build_absolute_uri (ESource *source)
+/**
+ * e_source_hash:
+ * @source: an #ESource
+ *
+ * Generates a hash value for @source. This function is intended for
+ * easily hashing an #ESource to add to a #GHashTable or similar data
+ * structure.
+ *
+ * Returns: a hash value for @source.
+ *
+ * Since: 2.92
+ **/
+guint
+e_source_hash (ESource *source)
{
- const gchar *base_uri_str;
- gchar *uri_str;
+ const gchar *uid;
- g_return_val_if_fail (source->priv->group != NULL, NULL);
+ g_return_val_if_fail (E_IS_SOURCE (source), 0);
- base_uri_str = e_source_group_peek_base_uri (source->priv->group);
-
- /* If last character in base URI is a slash, just concat the
- * strings. We don't want to compress e.g. the trailing ://
- * in a protocol specification Note: Do not use
- * G_DIR_SEPARATOR or g_build_filename() when manipulating
- * URIs. URIs use normal ("forward") slashes also on Windows.
- */
- if (*base_uri_str && *(base_uri_str + strlen (base_uri_str) - 1) == '/')
- uri_str = g_strconcat (base_uri_str, source->priv->relative_uri, NULL);
- else {
- if (source->priv->relative_uri != NULL)
- uri_str = g_strconcat (base_uri_str, g_str_equal (base_uri_str, "local:") ? "" : "/", source->priv->relative_uri,
- NULL);
- else
- uri_str = g_strdup (base_uri_str);
- }
+ uid = e_source_get_uid (source);
- return uri_str;
+ return g_str_hash (uid);
}
-void
-e_source_set_group (ESource *source,
- ESourceGroup *group)
+/**
+ * e_source_equal:
+ * @source1: the first #ESource
+ * @source2: the second #ESource
+ *
+ * Checks two #ESource instances for equality. #ESource instances are
+ * equal if their unique identifier strings are equal.
+ *
+ * Returns: %TRUE if @source1 and @source2 are equal
+ *
+ * Since: 2.92
+ **/
+gboolean
+e_source_equal (ESource *source1,
+ ESource *source2)
{
- g_return_if_fail (E_IS_SOURCE (source));
- g_return_if_fail (group == NULL || E_IS_SOURCE_GROUP (group));
+ const gchar *uid1, *uid2;
- if (source->priv->readonly)
- return;
-
- if (source->priv->group == group)
- return;
+ g_return_val_if_fail (E_IS_SOURCE (source1), FALSE);
+ g_return_val_if_fail (E_IS_SOURCE (source2), FALSE);
- if (source->priv->group != NULL)
- g_object_weak_unref (G_OBJECT (source->priv->group), (GWeakNotify) group_weak_notify, source);
+ if (source1 == source2)
+ return TRUE;
- source->priv->group = group;
- if (group != NULL) {
- g_object_weak_ref (G_OBJECT (group), (GWeakNotify) group_weak_notify, source);
- }
+ uid1 = e_source_get_uid (source1);
+ uid2 = e_source_get_uid (source2);
- g_signal_emit (source, signals[CHANGED], 0);
+ return g_str_equal (uid1, uid2);
}
-void
-e_source_set_name (ESource *source,
- const gchar *name)
+/**
+ * e_source_sync:
+ * @source: an #ESource
+ * @error: return location for a #GError, or %NULL
+ *
+ * Creates or replaces a key file at the location pointed to by the
+ * ESource:file property.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ **/
+gboolean
+e_source_sync (ESource *source,
+ GError **error)
{
- g_return_if_fail (E_IS_SOURCE (source));
- g_return_if_fail (name != NULL);
+ GKeyFile *key_file;
+ GHashTableIter iter;
+ gpointer extension;
+ gpointer group_name;
+ gboolean success;
+ gchar *contents;
+ gsize length;
+ GFile *file;
- if (source->priv->readonly)
- return;
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
- if (source->priv->name != NULL &&
- strcmp (source->priv->name, name) == 0)
- return;
+ file = e_source_get_file (source);
+ key_file = source->priv->key_file;
- g_free (source->priv->name);
- source->priv->name = g_strdup (name);
+ source_save_to_key_file (
+ G_OBJECT (source), key_file, E_SOURCE_GROUP_NAME);
- g_signal_emit (source, signals[CHANGED], 0);
-}
+ g_hash_table_iter_init (&iter, source->priv->extensions);
+ while (g_hash_table_iter_next (&iter, &group_name, &extension))
+ source_save_to_key_file (extension, key_file, group_name);
-void
-e_source_set_relative_uri (ESource *source,
- const gchar *relative_uri)
-{
- gchar *absolute_uri, *old_abs_uri = NULL;
+ contents = g_key_file_to_data (key_file, &length, NULL);
- g_return_if_fail (E_IS_SOURCE (source));
+ success = g_file_replace_contents (
+ file, contents, length, NULL, FALSE,
+ G_FILE_CREATE_NONE, NULL, NULL, error);
- if (source->priv->readonly)
- return;
+ g_free (contents);
- if (source->priv->relative_uri == relative_uri ||
- (source->priv->relative_uri && relative_uri && g_str_equal (source->priv->relative_uri, relative_uri)))
- return;
+ return success;
+}
+
+/**
+ * e_source_reload:
+ * @source: an #ESource
+ * @error: return location for a #GError, or %NULL
+ *
+ * Reloads the key file for @source and updates all the extensions.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ **/
+gboolean
+e_source_reload (ESource *source,
+ GError **error)
+{
+ GKeyFile *key_file;
+ GFile *file;
+ gchar *path;
+ gchar **groups;
+ gsize length, ii;
+ gboolean success;
- if (source->priv->group)
- old_abs_uri = e_source_build_absolute_uri (source);
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
- g_free (source->priv->relative_uri);
- source->priv->relative_uri = g_strdup (relative_uri);
+ file = e_source_get_file (source);
+ key_file = source->priv->key_file;
- /* reset the absolute uri, if it's a generated one */
- if (source->priv->absolute_uri &&
- (!old_abs_uri || g_str_equal (source->priv->absolute_uri, old_abs_uri)) &&
- (absolute_uri = e_source_build_absolute_uri (source))) {
- g_free (source->priv->absolute_uri);
- source->priv->absolute_uri = absolute_uri;
+ path = g_file_get_path (file);
+ if (path == NULL) {
+ g_set_error (
+ error, G_IO_ERROR,
+ G_IO_ERROR_INVALID_FILENAME,
+ _("Sources can only be loaded from native files"));
+ return FALSE;
}
- g_free (old_abs_uri);
+ success = g_key_file_load_from_file (
+ key_file, path, G_KEY_FILE_KEEP_COMMENTS |
+ G_KEY_FILE_KEEP_TRANSLATIONS, error);
+
+ if (!success)
+ goto exit;
+
+ /* Make sure the key file has the main group. */
+ if (!g_key_file_has_group (key_file, E_SOURCE_GROUP_NAME)) {
+ g_set_error (
+ error, G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
+ _("Source file is missing a [%s] group"),
+ E_SOURCE_GROUP_NAME);
+ success = FALSE;
+ goto exit;
+ }
- g_signal_emit (source, signals[CHANGED], 0);
-}
+ groups = g_key_file_get_groups (key_file, &length);
+ for (ii = 0; ii < length; ii++) {
+ GObject *object;
-void
-e_source_set_absolute_uri (ESource *source,
- const gchar *absolute_uri)
-{
- g_return_if_fail (E_IS_SOURCE (source));
+ if (g_str_equal (groups[ii], E_SOURCE_GROUP_NAME))
+ object = G_OBJECT (source);
+ else
+ object = e_source_get_extension (source, groups[ii]);
- if ((absolute_uri == source->priv->absolute_uri && absolute_uri == NULL)
- || (absolute_uri && source->priv->absolute_uri && !strcmp (source->priv->absolute_uri, absolute_uri)))
- return;
+ /* Skip unrecognized groups. */
+ if (object == NULL)
+ continue;
- g_free (source->priv->absolute_uri);
- source->priv->absolute_uri = g_strdup (absolute_uri);
+ source_load_from_key_file (object, key_file, groups[ii]);
+ }
+ g_strfreev (groups);
- g_signal_emit (source, signals[CHANGED], 0);
+exit:
+ g_free (path);
+
+ return success;
}
+/**
+ * e_source_redirect:
+ * @source: an #ESource
+ * @directory: a native directory
+ *
+ * Redirects all future sync operations to @directory instead of the
+ * directory from which @source was originally loaded. This is useful
+ * if @source was created from a read-only template key file but you
+ * want to allow for modifications.
+ **/
void
-e_source_set_readonly (ESource *source,
- gboolean readonly)
+e_source_redirect (ESource *source,
+ GFile *directory)
{
+ GFile *file;
+ const gchar *uid;
+
g_return_if_fail (E_IS_SOURCE (source));
+ g_return_if_fail (G_IS_FILE (directory));
- if (source->priv->readonly == readonly)
+ uid = e_source_get_uid (source);
+ file = g_file_get_child (directory, uid);
+
+ if (g_file_equal (file, source->priv->file)) {
+ g_object_unref (file);
return;
+ }
- source->priv->readonly = readonly;
+ g_object_unref (source->priv->file);
+ source->priv->file = file;
- g_signal_emit (source, signals[CHANGED], 0);
+ source_setup_file_monitor (source);
+ g_object_notify (G_OBJECT (source), "file");
}
/**
- * e_source_set_color_spec:
- * @source: an ESource
- * @color_spec: a string specifying the color
+ * e_source_changed:
+ * @source: an #ESource
*
- * Store a textual representation of a color in @source. The @color_spec
- * string should be parsable by #gdk_color_parse(), or %NULL to unset the
- * color in @source.
+ * Emits the #ESource::changed signal.
*
- * Since: 1.10
+ * This function is primarily intended for use by #ESourceExtension
+ * when emitting a #GObject::notify signal on one of its properties.
+ *
+ * Since: 2.92
**/
void
-e_source_set_color_spec (ESource *source,
- const gchar *color_spec)
+e_source_changed (ESource *source)
{
g_return_if_fail (E_IS_SOURCE (source));
- if (!source->priv->readonly && set_color_spec (source, color_spec))
- g_signal_emit (source, signals[CHANGED], 0);
-}
-
-ESourceGroup *
-e_source_peek_group (ESource *source)
-{
- g_return_val_if_fail (E_IS_SOURCE (source), NULL);
-
- return source->priv->group;
+ g_signal_emit (source, signals[CHANGED], 0);
}
+/**
+ * e_source_get_uid:
+ * @source: an #ESource
+ *
+ * Returns the unique identifier string for @source.
+ *
+ * Returns: the UID for @source
+ *
+ * Since: 2.92
+ **/
const gchar *
-e_source_peek_uid (ESource *source)
+e_source_get_uid (ESource *source)
{
g_return_val_if_fail (E_IS_SOURCE (source), NULL);
return source->priv->uid;
}
-const gchar *
-e_source_peek_name (ESource *source)
-{
- g_return_val_if_fail (E_IS_SOURCE (source), NULL);
-
- return source->priv->name;
-}
-
-const gchar *
-e_source_peek_relative_uri (ESource *source)
+/**
+ * e_source_get_file:
+ * @source: an #ESource
+ *
+ * Returns a #GFile referring to the on-disk key file for @source.
+ *
+ * Returns: the #GFile for @source
+ *
+ * Since: 2.92
+ **/
+GFile *
+e_source_get_file (ESource *source)
{
g_return_val_if_fail (E_IS_SOURCE (source), NULL);
- return source->priv->relative_uri;
+ return source->priv->file;
}
-const gchar *
-e_source_peek_absolute_uri (ESource *source)
+/**
+ * e_source_get_node:
+ * @source: an #ESource
+ *
+ * Returns a #GNode representing the source's position within a hierarchy
+ * of sources. The #GNode<!-- -->'s data value points back to @source.
+ *
+ * Often data such as the backend name must be fetched from a parent
+ * #ESource. This is the mechanism for accessing a parent #ESource.
+ *
+ * Returns: the #GNode for @source
+ *
+ * Since: 2.92
+ **/
+GNode *
+e_source_get_node (ESource *source)
{
g_return_val_if_fail (E_IS_SOURCE (source), NULL);
- return source->priv->absolute_uri;
+ return &source->priv->node;
}
/**
- * e_source_peek_color_spec:
- * @source: an ESource
+ * e_source_get_parent:
+ * @source: an #ESource
*
- * Return the textual representation of the color for @source, or %NULL if it
- * has none. The returned string should be parsable by #gdk_color_parse().
+ * Returns the unique identifier string of the parent #ESource.
*
- * Returns: a string specifying the color
+ * Returns: the UID of the parent #ESource
*
- * Since: 1.10
+ * Since: 2.92
**/
const gchar *
-e_source_peek_color_spec (ESource *source)
+e_source_get_parent (ESource *source)
{
g_return_val_if_fail (E_IS_SOURCE (source), NULL);
- return source->priv->color_spec;
+ return source->priv->parent;
}
-gboolean
-e_source_get_readonly (ESource *source)
-{
- g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
-
- return source->priv->readonly;
-}
-
-gchar *
-e_source_get_uri (ESource *source)
+/**
+ * e_source_set_parent:
+ * @source: an #ESource
+ * @parent: the UID of the parent #ESource
+ *
+ * Identifies the parent of @source by its unique identifier string.
+ * This can only be set prior to adding @source to an #ESourceRegistry.
+ *
+ * Since: 2.92
+ **/
+void
+e_source_set_parent (ESource *source,
+ const gchar *parent)
{
- g_return_val_if_fail (E_IS_SOURCE (source), NULL);
-
- if (source->priv->group == NULL) {
- if (source->priv->absolute_uri != NULL)
- return g_strdup (source->priv->absolute_uri);
+ GNode *node;
- g_warning ("e_source_get_uri () called on source with no absolute URI!");
- return NULL;
- }
- else if (source->priv->absolute_uri != NULL) /* source->priv->group != NULL */
- return g_strdup (source->priv->absolute_uri);
- else
- return e_source_build_absolute_uri (source);
-}
-
-static void
-property_dump_cb (const xmlChar *key, const xmlChar *value, xmlNodePtr root)
-{
- xmlNodePtr node;
+ g_return_if_fail (E_IS_SOURCE (source));
- node = xmlNewChild (root, NULL, (xmlChar*)"property", NULL);
- xmlSetProp (node, (xmlChar*)"name", key);
- xmlSetProp (node, (xmlChar*)"value", value);
-}
+ node = e_source_get_node (source);
+ if (node->parent != NULL)
+ return;
-static xmlNodePtr
-dump_common_to_xml_node (ESource *source,
- xmlNodePtr parent_node)
-{
- ESourcePrivate *priv;
- xmlNodePtr node;
- const gchar *abs_uri = NULL, *relative_uri = NULL;
-
- priv = source->priv;
-
- if (parent_node)
- node = xmlNewChild (parent_node, NULL, (xmlChar*)"source", NULL);
- else
- node = xmlNewNode (NULL, (xmlChar*)"source");
-
- xmlSetProp (node, (xmlChar*)"uid", (xmlChar*)e_source_peek_uid (source));
- xmlSetProp (node, (xmlChar*)"name", (xmlChar*)e_source_peek_name (source));
- abs_uri = e_source_peek_absolute_uri (source);
- /* do not store absolute uris for local:system sources */
- relative_uri = e_source_peek_relative_uri (source);
- if (abs_uri && !(relative_uri && g_str_equal (relative_uri, "system") &&
- (g_str_has_prefix (abs_uri, "file:") || g_str_has_prefix (abs_uri, "local:"))))
- xmlSetProp (node, (xmlChar*)"uri", (xmlChar*)abs_uri);
- if (relative_uri)
- xmlSetProp (node, (xmlChar*)"relative_uri", (xmlChar*)relative_uri);
-
- if (priv->color_spec != NULL)
- xmlSetProp (node, (xmlChar*)"color_spec", (xmlChar*)priv->color_spec);
-
- if (g_hash_table_size (priv->properties) != 0) {
- xmlNodePtr properties_node;
-
- properties_node = xmlNewChild (node, NULL, (xmlChar*)"properties", NULL);
- g_hash_table_foreach (priv->properties, (GHFunc) property_dump_cb, properties_node);
- }
+ g_free (source->priv->parent);
+ source->priv->parent = g_strdup (parent);
- return node;
+ g_object_notify (G_OBJECT (source), "parent");
}
-void
-e_source_dump_to_xml_node (ESource *source,
- xmlNodePtr parent_node)
-{
- g_return_if_fail (E_IS_SOURCE (source));
-
- dump_common_to_xml_node (source, parent_node);
-}
-
-gchar *
-e_source_to_standalone_xml (ESource *source)
+/**
+ * e_source_get_extension:
+ * @source: an #ESource
+ * @name: an extension name
+ *
+ * Returns an instance of some #ESourceExtension subclass which registered
+ * itself under @name. If no such instance exists within @source, one will
+ * be created. It is the caller's responsibility to know which subclass is
+ * being returned.
+ *
+ * If you just want to test for the existence of an extension within @source
+ * without creating it, use e_source_has_extension().
+ *
+ * Extension instances are owned by their #ESource and should not be
+ * referenced directly. Instead, reference the #ESource instance and
+ * use this function to fetch the extension instance as needed.
+ *
+ * Returns: an instance of some #ESourceExtension subclass
+ *
+ * Since: 2.92
+ **/
+gpointer
+e_source_get_extension (ESource *source,
+ const gchar *name)
{
- xmlDocPtr doc;
- xmlNodePtr node;
- xmlChar *xml_buffer;
- gchar *returned_buffer;
- gint xml_buffer_size;
- gchar *uri;
+ ESourceExtension *extension;
+ GHashTable *hash_table;
+ GTypeClass *class;
g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
- doc = xmlNewDoc ((xmlChar*)"1.0");
- node = dump_common_to_xml_node (source, NULL);
-
- xmlDocSetRootElement (doc, node);
-
- uri = e_source_get_uri (source);
- xmlSetProp (node, (xmlChar*)"uri", (xmlChar*)uri);
- g_free (uri);
-
- xmlDocDumpMemory (doc, &xml_buffer, &xml_buffer_size);
- xmlFreeDoc (doc);
+ /* Check if we already have the extension. */
+ extension = g_hash_table_lookup (source->priv->extensions, name);
+ if (extension != NULL)
+ return extension;
+
+ /* Find all subclasses of ESourceExtensionClass. */
+ hash_table = source_find_extension_classes ();
+ class = g_hash_table_lookup (hash_table, name);
+
+ /* Create a new instance of the appropriate GType. */
+ if (class != NULL) {
+ extension = g_object_new (
+ G_TYPE_FROM_CLASS (class),
+ "source", source, NULL);
+ g_hash_table_insert (
+ source->priv->extensions,
+ g_strdup (name), extension);
+ } else {
+ /* XXX Tie this into a debug setting for ESources. */
+ g_critical (
+ "No registered GType for ESource "
+ "extension '%s'", name);
+ }
- returned_buffer = g_malloc (xml_buffer_size + 1);
- memcpy (returned_buffer, xml_buffer, xml_buffer_size);
- returned_buffer[xml_buffer_size] = '\0';
- xmlFree (xml_buffer);
+ g_hash_table_destroy (hash_table);
- return returned_buffer;
+ return extension;
}
/**
- * e_source_equal:
- * @a: An ESource
- * @b: Another ESource
+ * e_source_has_extension:
+ * @source: an #ESource
+ * @name: an extension name
*
- * Compares if @a is equivalent to @b.
+ * Checks whether @source has an #ESourceExtension with the given name.
*
- * Returns: %TRUE if @a is equivalent to @b,
- * %FALSE otherwise.
+ * Returns: %TRUE if @source has such an extension, %FALSE if not
*
- * Since: 2.24
+ * Since: 2.92
**/
gboolean
-e_source_equal (ESource *a, ESource *b)
+e_source_has_extension (ESource *source,
+ const gchar *name)
{
- g_return_val_if_fail (E_IS_SOURCE (a), FALSE);
- g_return_val_if_fail (E_IS_SOURCE (b), FALSE);
-
- #define ONLY_ONE_NULL(aa, bb) (((aa) == NULL && (bb) != NULL) || ((aa) != NULL && (bb) == NULL))
-
- /* Compare source stuff */
- if (a->priv->uid
- && b->priv->uid
- && g_ascii_strcasecmp (a->priv->uid, b->priv->uid))
- return FALSE;
-
- if (a->priv->name
- && b->priv->name
- && g_ascii_strcasecmp (a->priv->name, b->priv->name))
- return FALSE;
-
- if (a->priv->relative_uri
- && b->priv->relative_uri
- && g_ascii_strcasecmp (a->priv->relative_uri, b->priv->relative_uri))
- return FALSE;
+ ESourceExtension *extension;
- if (a->priv->absolute_uri
- && b->priv->absolute_uri
- && g_ascii_strcasecmp (a->priv->absolute_uri, b->priv->absolute_uri))
- return FALSE;
-
- if ((a->priv->color_spec
- && b->priv->color_spec
- && g_ascii_strcasecmp (a->priv->color_spec, b->priv->color_spec)) ||
- (ONLY_ONE_NULL (a->priv->color_spec, b->priv->color_spec)))
- return FALSE;
-
- if (a->priv->readonly != b->priv->readonly)
- return FALSE;
-
- if (!compare_str_hashes (a->priv->properties, b->priv->properties))
- return FALSE;
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
- #undef ONLY_ONE_NULL
+ extension = g_hash_table_lookup (source->priv->extensions, name);
- return TRUE;
+ return (extension != NULL);
}
/**
- * e_source_xmlstr_equal:
- * @a: XML representation of an ESource
- * @b: XML representation of another ESource
+ * e_source_get_backend_name:
+ * @source: an #ESource
*
- * Compares if @a is equivalent to @b.
+ * Returns the backend name for @source.
*
- * Returns: %TRUE if @a is equivalent to @b,
- * %FALSE otherwise.
+ * Returns: the backend name for @source
*
- * Since: 2.24
+ * Since: 2.92
**/
-gboolean
-e_source_xmlstr_equal (const gchar *a, const gchar *b)
+const gchar *
+e_source_get_backend_name (ESource *source)
{
- ESource *srca, *srcb;
- gboolean retval;
-
- srca = e_source_new_from_standalone_xml (a);
- srcb = e_source_new_from_standalone_xml (b);
-
- retval = e_source_equal (srca, srcb);
-
- g_object_unref (srca);
- g_object_unref (srcb);
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
- return retval;
-}
+ /* Check the given ESource and its parents
+ * until we find a non-empty backend string. */
-ESource *
-e_source_new_from_standalone_xml (const gchar *xml)
-{
- xmlDocPtr doc;
- xmlNodePtr root;
- ESource *source;
+ while (E_IS_SOURCE (source)) {
+ GNode *node;
+ const gchar *backend_name;
- doc = xmlParseDoc ((xmlChar*)xml);
- if (doc == NULL)
- return NULL;
+ backend_name = source->priv->backend_name;
+ if (backend_name != NULL && *backend_name != '\0')
+ return backend_name;
- root = doc->children;
- if (strcmp ((gchar *)root->name, "source") != 0)
- return NULL;
-
- source = e_source_new_from_xml_node (root);
- xmlFreeDoc (doc);
+ node = e_source_get_node (source);
+ g_return_val_if_fail (node != NULL, NULL);
+ source = (node->parent != NULL) ? node->parent->data : NULL;
+ }
- return source;
+ return NULL;
}
-const gchar *
-e_source_get_property (ESource *source,
- const gchar *property)
+/**
+ * e_source_set_backend_name:
+ * @source: an #ESource
+ * @backend_name: a backend name
+ *
+ * Sets the backend name for @source.
+ *
+ * Since: 2.92
+ **/
+void
+e_source_set_backend_name (ESource *source,
+ const gchar *backend_name)
{
- ESourcePrivate *priv;
+ g_return_if_fail (E_IS_SOURCE (source));
- g_return_val_if_fail (E_IS_SOURCE (source), NULL);
- priv = source->priv;
+ g_free (source->priv->backend_name);
+ source->priv->backend_name = g_strdup (backend_name);
- return g_hash_table_lookup (priv->properties, property);
+ g_object_notify (G_OBJECT (source), "backend-name");
}
/**
- * e_source_get_duped_property:
+ * e_source_get_display_name:
+ * @source: an #ESource
+ *
+ * Returns the display name for @source. Use the display name to
+ * represent the #ESource in a user interface.
+ *
+ * Returns: the display name for @source
*
- * Since: 1.12
+ * Since: 2.92
**/
-gchar *
-e_source_get_duped_property (ESource *source, const gchar *property)
+const gchar *
+e_source_get_display_name (ESource *source)
{
- ESourcePrivate *priv;
-
g_return_val_if_fail (E_IS_SOURCE (source), NULL);
- priv = source->priv;
-
- return g_strdup (g_hash_table_lookup (priv->properties, property));
-}
-void
-e_source_set_property (ESource *source,
- const gchar *property,
- const gchar *value)
-{
- ESourcePrivate *priv;
-
- g_return_if_fail (E_IS_SOURCE (source));
- priv = source->priv;
-
- if (value)
- g_hash_table_replace (priv->properties, g_strdup (property), g_strdup (value));
- else
- g_hash_table_remove (priv->properties, property);
-
- g_signal_emit (source, signals[CHANGED], 0);
+ return source->priv->display_name;
}
+/**
+ * e_source_set_display_name:
+ * @source: an #ESource
+ * @display_name: a display name
+ *
+ * Sets the display name for @source to a valid UTF-8 string. Use the
+ * display name to represent the #ESource in a user interface.
+ *
+ * Since: 2.92
+ **/
void
-e_source_foreach_property (ESource *source, GHFunc func, gpointer data)
+e_source_set_display_name (ESource *source,
+ const gchar *display_name)
{
- ESourcePrivate *priv;
-
g_return_if_fail (E_IS_SOURCE (source));
- priv = source->priv;
+ g_return_if_fail (display_name != NULL);
+ g_return_if_fail (g_utf8_validate (display_name, -1, NULL));
- g_hash_table_foreach (priv->properties, func, data);
-}
+ g_free (source->priv->display_name);
+ source->priv->display_name = g_strdup (display_name);
-static void
-copy_property (const gchar *key, const gchar *value, ESource *new_source)
-{
- e_source_set_property (new_source, key, value);
+ g_object_notify (G_OBJECT (source), "display-name");
}
-ESource *
-e_source_copy (ESource *source)
+/**
+ * e_source_compare_by_display_name:
+ * @source1: the first #ESource
+ * @source2: the second #ESource
+ *
+ * Compares two #ESource instances by their display names. Useful for
+ * ordering sources in a user interface.
+ *
+ * Returns: a negative value if @source1 compares before @source2, zero if
+ * they compare equal, or a positive value if @source1 compares
+ * after @source2
+ *
+ * Since: 2.92
+ **/
+gint
+e_source_compare_by_display_name (ESource *source1,
+ ESource *source2)
{
- ESource *new_source;
-
- g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+ const gchar *display_name1;
+ const gchar *display_name2;
- new_source = g_object_new (e_source_get_type (), NULL);
- new_source->priv->uid = g_strdup (e_source_peek_uid (source));
+ display_name1 = e_source_get_display_name (source1);
+ display_name2 = e_source_get_display_name (source2);
- e_source_set_name (new_source, e_source_peek_name (source));
-
- new_source->priv->color_spec = g_strdup (source->priv->color_spec);
-
- new_source->priv->absolute_uri = g_strdup (e_source_peek_absolute_uri (source));
-
- e_source_foreach_property (source, (GHFunc) copy_property, new_source);
-
- return new_source;
+ return g_utf8_collate (display_name1, display_name2);
}
-
diff --git a/libedataserver/e-source.h b/libedataserver/e-source.h
index ad68133..6f02335 100644
--- a/libedataserver/e-source.h
+++ b/libedataserver/e-source.h
@@ -1,117 +1,105 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-source.h
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+/*
+ * e-source.h
*
* This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
*
* 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.
+ * Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
*
- * Author: Ettore Perazzoli <ettore ximian com>
*/
-#ifndef _E_SOURCE_H_
-#define _E_SOURCE_H_
-
-#include <glib-object.h>
-#include <libxml/tree.h>
+#ifndef E_SOURCE_H
+#define E_SOURCE_H
+
+#include <gio/gio.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE \
+ (e_source_get_type ())
+#define E_SOURCE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE, ESource))
+#define E_SOURCE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE, ESourceClass))
+#define E_IS_SOURCE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE))
+#define E_IS_SOURCE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE))
+#define E_SOURCE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE, ESourceClass))
+
+/**
+ * E_SOURCE_PARAM_SETTING:
+ *
+ * Extends #GParamFlags to indicate the #GObject property is associated
+ * with a key file value. Use this flag when installing #GObject properties
+ * in #ESourceExtension subclasses.
+ **/
+#define E_SOURCE_PARAM_SETTING (1 << G_PARAM_USER_SHIFT)
G_BEGIN_DECLS
-#define E_TYPE_SOURCE (e_source_get_type ())
-#define E_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_SOURCE, ESource))
-#define E_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_SOURCE, ESourceClass))
-#define E_IS_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_SOURCE))
-#define E_IS_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_SOURCE))
-
-typedef struct _ESource ESource;
+typedef struct _ESource ESource;
+typedef struct _ESourceClass ESourceClass;
typedef struct _ESourcePrivate ESourcePrivate;
-typedef struct _ESourceClass ESourceClass;
-
-#include "e-source-group.h"
struct _ESource {
GObject parent;
-
ESourcePrivate *priv;
};
struct _ESourceClass {
GObjectClass parent_class;
- /* Signals. */
- void (* changed) (ESource *source);
+ /* Signals */
+ void (*changed) (ESource *source);
};
-GType e_source_get_type (void);
-
-ESource *e_source_new (const gchar *name,
- const gchar *relative_uri);
-ESource *e_source_new_with_absolute_uri (const gchar *name,
- const gchar *absolute_uri);
-ESource *e_source_new_from_xml_node (xmlNodePtr node);
-ESource *e_source_new_from_standalone_xml (const gchar *xml);
-
-ESource *e_source_copy (ESource *source);
-
-gboolean e_source_update_from_xml_node (ESource *source,
- xmlNodePtr node,
- gboolean *changed_return);
-
-gchar *e_source_uid_from_xml_node (xmlNodePtr node);
-
-void e_source_set_group (ESource *source,
- ESourceGroup *group);
-void e_source_set_name (ESource *source,
- const gchar *name);
-void e_source_set_relative_uri (ESource *source,
- const gchar *relative_uri);
-void e_source_set_absolute_uri (ESource *source,
- const gchar *absolute_uri);
-void e_source_set_color_spec (ESource *source,
- const gchar *color_spec);
-void e_source_set_readonly (ESource *source,
- gboolean readonly);
-
-ESourceGroup *e_source_peek_group (ESource *source);
-const gchar *e_source_peek_uid (ESource *source);
-const gchar *e_source_peek_name (ESource *source);
-const gchar *e_source_peek_relative_uri (ESource *source);
-const gchar *e_source_peek_absolute_uri (ESource *source);
-const gchar *e_source_peek_color_spec (ESource *source);
-gboolean e_source_get_readonly (ESource *source);
-
-gchar *e_source_get_uri (ESource *source);
-
-void e_source_dump_to_xml_node (ESource *source,
- xmlNodePtr parent_node);
-gchar *e_source_to_standalone_xml (ESource *source);
-
-const gchar *e_source_get_property (ESource *source,
- const gchar *property);
-void e_source_set_property (ESource *source,
- const gchar *property,
- const gchar *value);
-void e_source_foreach_property (ESource *source,
- GHFunc func,
- gpointer data);
-
-gchar *e_source_get_duped_property (ESource *source, const gchar *property);
-gchar *e_source_build_absolute_uri (ESource *source);
-
-gboolean e_source_equal (ESource *a, ESource *b);
-gboolean e_source_xmlstr_equal (const gchar *a, const gchar *b);
+GType e_source_get_type (void) G_GNUC_CONST;
+ESource * e_source_new (GFile *file,
+ GError **error);
+guint e_source_hash (ESource *source);
+gboolean e_source_equal (ESource *source1,
+ ESource *source2);
+gboolean e_source_sync (ESource *source,
+ GError **error);
+gboolean e_source_reload (ESource *source,
+ GError **error);
+void e_source_changed (ESource *source);
+void e_source_redirect (ESource *source,
+ GFile *directory);
+const gchar * e_source_get_uid (ESource *source);
+GFile * e_source_get_file (ESource *source);
+GNode * e_source_get_node (ESource *source);
+const gchar * e_source_get_parent (ESource *source);
+void e_source_set_parent (ESource *source,
+ const gchar *parent);
+gpointer e_source_get_extension (ESource *source,
+ const gchar *extension_name);
+gboolean e_source_has_extension (ESource *source,
+ const gchar *extension_name);
+const gchar * e_source_get_backend_name (ESource *source);
+void e_source_set_backend_name (ESource *source,
+ const gchar *backend_name);
+const gchar * e_source_get_display_name (ESource *source);
+void e_source_set_display_name (ESource *source,
+ const gchar *display_name);
+gint e_source_compare_by_display_name
+ (ESource *source1,
+ ESource *source2);
G_END_DECLS
-#endif /* _E_SOURCE_H_ */
+#endif /* E_SOURCE_H */
diff --git a/libedataserver/e-system-source.c b/libedataserver/e-system-source.c
new file mode 100644
index 0000000..12a7d1a
--- /dev/null
+++ b/libedataserver/e-system-source.c
@@ -0,0 +1,117 @@
+/*
+ * e-system-source.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-system-source.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include "e-data-server-util.h"
+
+G_DEFINE_TYPE (
+ ESystemSource,
+ e_system_source,
+ E_TYPE_SOURCE)
+
+static void
+system_source_notify (GObject *object,
+ GParamSpec *pspec)
+{
+ ESource *source = E_SOURCE (object);
+
+ /* GObject does not allow subclasses to override property flags,
+ * so we'll keep the "backend-name" and "display-name" properties
+ * fixed by intercepting attempts to change them and setting them
+ * back to their proper values. Hokey but works. */
+
+ if (g_strcmp0 (pspec->name, "backend-name") == 0) {
+ if (e_source_get_backend_name (source) != NULL) {
+ e_source_set_backend_name (source, NULL);
+ return;
+ }
+ }
+
+ if (g_strcmp0 (pspec->name, "display-name") == 0) {
+ const gchar *display_name;
+ const gchar *proper_value;
+
+ display_name = e_source_get_display_name (source);
+ proper_value = _("Personal");
+
+ if (g_strcmp0 (display_name, proper_value) != 0) {
+ e_source_set_display_name (source, proper_value);
+ return;
+ }
+ }
+
+ /* Chain up to parent's notify() method. */
+ G_OBJECT_CLASS (e_system_source_parent_class)->notify (object, pspec);
+}
+
+static void
+e_system_source_class_init (ESystemSourceClass *class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->notify = system_source_notify;
+}
+
+static void
+e_system_source_init (ESystemSource *source)
+{
+}
+
+ESource *
+e_system_source_new (void)
+{
+ GSettings *settings;
+ ESource *source;
+ GFile *file;
+ const gchar *data_dir;
+ gchar *path;
+
+ data_dir = e_get_user_data_dir ();
+ path = g_build_filename (data_dir, "sources", "system", NULL);
+ file = g_file_new_for_path (path);
+ g_free (path);
+
+ /* This function must not fail, so if a "system" key file
+ * exists and fails to load, delete it and try again. */
+ source = g_initable_new (
+ E_TYPE_SYSTEM_SOURCE, NULL, NULL, "file", file, NULL);
+ if (source == NULL) {
+ g_file_delete (file, NULL, NULL);
+ source = g_initable_new (
+ E_TYPE_SYSTEM_SOURCE, NULL, NULL, "file", file, NULL);
+ }
+
+ g_object_unref (file);
+
+ g_return_val_if_fail (E_IS_SYSTEM_SOURCE (source), NULL);
+
+ /* Set the "parent" key directly through its GSettings.
+ *
+ * XXX To set this during object construction we would have
+ * to override the GInitable interface. Too much hassle
+ * for now. Maybe revisit this in the future. */
+ settings = e_source_get_settings (source);
+ g_settings_set_string (settings, "parent", "local");
+
+ return source;
+}
diff --git a/libedataserver/e-system-source.h b/libedataserver/e-system-source.h
new file mode 100644
index 0000000..959a8f2
--- /dev/null
+++ b/libedataserver/e-system-source.h
@@ -0,0 +1,63 @@
+/*
+ * e-system-source.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SYSTEM_SOURCE_H
+#define E_SYSTEM_SOURCE_H
+
+#include <libedataserver/e-source.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SYSTEM_SOURCE \
+ (e_system_source_get_type ())
+#define E_SYSTEM_SOURCE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SYSTEM_SOURCE, ESystemSource))
+#define E_SYSTEM_SOURCE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SYSTEM_SOURCE, ESystemSourceClass))
+#define E_IS_SYSTEM_SOURCE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SYSTEM_SOURCE))
+#define E_IS_SYSTEM_SOURCE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SYSTEM_SOURCE))
+#define E_SYSTEM_SOURCE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE, ESystemSourceClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESystemSource ESystemSource;
+typedef struct _ESystemSourceClass ESystemSourceClass;
+typedef struct _ESystemSourcePrivate ESystemSourcePrivate;
+
+struct _ESystemSource {
+ ESource parent;
+ ESystemSourcePrivate *priv;
+};
+
+struct _ESystemSourceClass {
+ ESourceClass parent_class;
+};
+
+GType e_system_source_get_type (void) G_GNUC_CONST;
+ESource * e_system_source_new (void);
+
+G_END_DECLS
+
+#endif /* E_SYSTEM_SOURCE_H */
diff --git a/libedataserver/libedataserver.pc.in b/libedataserver/libedataserver.pc.in
index 9ee5be4..e81eba1 100644
--- a/libedataserver/libedataserver.pc.in
+++ b/libedataserver/libedataserver.pc.in
@@ -10,6 +10,6 @@ privincludedir= privincludedir@
Name: libedataserver
Description: Utility library for Evolution Data Server
Version: @VERSION@
-Requires: gio-2.0 libxml-2.0 gconf-2.0 libsoup-2.4
+Requires: gio-2.0 gnome-keyring-1 libxml-2.0 gconf-2.0 libsoup-2.4
Libs: -L${libdir} -ledataserver- API_VERSION@
Cflags: -I${privincludedir}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]