[evolution-data-server] New EClient/EBookClient/ECalClient API deprecating EBook/ECal
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] New EClient/EBookClient/ECalClient API deprecating EBook/ECal
- Date: Mon, 23 May 2011 09:49:45 +0000 (UTC)
commit 06cf0baa73a9d19d03cbf84e751fecef987e0b3a
Author: Milan Crha <mcrha redhat com>
Date: Mon May 23 11:45:20 2011 +0200
New EClient/EBookClient/ECalClient API deprecating EBook/ECal
addressbook/backends/file/e-book-backend-file.c | 398 +-
.../backends/google/e-book-backend-google.c | 471 +-
addressbook/backends/ldap/e-book-backend-ldap.c | 1155 ++--
addressbook/backends/vcf/e-book-backend-vcf.c | 158 +-
.../backends/webdav/e-book-backend-webdav.c | 237 +-
addressbook/libebook/Makefile.am | 5 +
.../e-book-client-view-private.h} | 14 +-
addressbook/libebook/e-book-client-view.c | 384 ++
addressbook/libebook/e-book-client-view.h | 71 +
addressbook/libebook/e-book-client.c | 2093 ++++++
addressbook/libebook/e-book-client.h | 131 +
addressbook/libebook/e-book-view-private.h | 1 +
addressbook/libebook/e-book-view.c | 49 +-
addressbook/libebook/e-book-view.h | 12 +-
addressbook/libebook/e-book.c | 362 +-
addressbook/libebook/e-book.h | 5 +
addressbook/libedata-book/Makefile.am | 1 -
addressbook/libedata-book/e-book-backend-sync.c | 511 +-
addressbook/libedata-book/e-book-backend-sync.h | 81 +-
addressbook/libedata-book/e-book-backend.c | 950 ++--
addressbook/libedata-book/e-book-backend.h | 221 +-
addressbook/libedata-book/e-data-book-factory.c | 53 +-
addressbook/libedata-book/e-data-book-factory.h | 2 +-
addressbook/libedata-book/e-data-book-types.h | 18 +-
addressbook/libedata-book/e-data-book-view.c | 169 +-
addressbook/libedata-book/e-data-book-view.h | 45 +-
addressbook/libedata-book/e-data-book.c | 894 ++-
addressbook/libedata-book/e-data-book.h | 118 +-
addressbook/libedata-book/opid.c | 75 -
addressbook/libegdbus/Makefile.am | 28 +-
addressbook/libegdbus/e-gdbus-book-factory.c | 551 ++
addressbook/libegdbus/e-gdbus-book-factory.h | 120 +
addressbook/libegdbus/e-gdbus-book-view.c | 690 ++
addressbook/libegdbus/e-gdbus-book-view.h | 155 +
addressbook/libegdbus/e-gdbus-book.c | 1126 +++
addressbook/libegdbus/e-gdbus-book.h | 265 +
addressbook/libegdbus/e-gdbus-egdbusbook.c | 4483 ------------
addressbook/libegdbus/e-gdbus-egdbusbook.h | 640 --
addressbook/libegdbus/e-gdbus-egdbusbookfactory.c | 1112 ---
addressbook/libegdbus/e-gdbus-egdbusbookfactory.h | 202 -
addressbook/libegdbus/e-gdbus-egdbusbookview.c | 2025 ------
addressbook/libegdbus/e-gdbus-egdbusbookview.h | 285 -
addressbook/libegdbus/e-gdbus-marshallers.c | 343 -
addressbook/libegdbus/e-gdbus-marshallers.h | 77 -
addressbook/libegdbus/e-gdbus-typemappers.h | 11 -
calendar/backends/caldav/e-cal-backend-caldav.c | 566 +-
.../backends/contacts/e-cal-backend-contacts.c | 249 +-
calendar/backends/file/e-cal-backend-file.c | 727 +--
calendar/backends/http/e-cal-backend-http.c | 437 +-
calendar/backends/weather/e-cal-backend-weather.c | 301 +-
calendar/libecal/Makefile.am | 7 +-
calendar/libecal/e-cal-client-view-private.h | 35 +
calendar/libecal/e-cal-client-view.c | 527 ++
calendar/libecal/e-cal-client-view.h | 68 +
calendar/libecal/e-cal-client.c | 4106 +++++++++++
calendar/libecal/e-cal-client.h | 193 +
calendar/libecal/e-cal-types.h | 3 +-
calendar/libecal/e-cal-view.c | 40 +-
calendar/libecal/e-cal-view.h | 6 +
calendar/libecal/e-cal.c | 857 ++-
calendar/libecal/e-cal.h | 12 +
calendar/libedata-cal/e-cal-backend-sexp.c | 8 +-
calendar/libedata-cal/e-cal-backend-sync.c | 742 +--
calendar/libedata-cal/e-cal-backend-sync.h | 213 +-
calendar/libedata-cal/e-cal-backend.c | 1610 +++---
calendar/libedata-cal/e-cal-backend.h | 235 +-
calendar/libedata-cal/e-data-cal-common.h | 3 -
calendar/libedata-cal/e-data-cal-factory.c | 65 +-
calendar/libedata-cal/e-data-cal-factory.h | 15 +-
calendar/libedata-cal/e-data-cal-types.h | 13 +-
calendar/libedata-cal/e-data-cal-view.c | 354 +-
calendar/libedata-cal/e-data-cal-view.h | 53 +-
calendar/libedata-cal/e-data-cal.c | 1442 +++--
calendar/libedata-cal/e-data-cal.h | 116 +-
calendar/libegdbus/Makefile.am | 27 +-
calendar/libegdbus/e-gdbus-cal-factory.c | 604 ++
calendar/libegdbus/e-gdbus-cal-factory.h | 116 +
calendar/libegdbus/e-gdbus-cal-view.c | 690 ++
calendar/libegdbus/e-gdbus-cal-view.h | 147 +
calendar/libegdbus/e-gdbus-cal.c | 1584 +++++
calendar/libegdbus/e-gdbus-cal.h | 333 +
calendar/libegdbus/e-gdbus-egdbuscal.c | 7222 --------------------
calendar/libegdbus/e-gdbus-egdbuscal.h | 1011 ---
calendar/libegdbus/e-gdbus-egdbuscalfactory.c | 1130 ---
calendar/libegdbus/e-gdbus-egdbuscalfactory.h | 205 -
calendar/libegdbus/e-gdbus-egdbuscalview.c | 2043 ------
calendar/libegdbus/e-gdbus-egdbuscalview.h | 287 -
calendar/libegdbus/e-gdbus-marshallers.c | 474 --
calendar/libegdbus/e-gdbus-marshallers.h | 104 -
calendar/libegdbus/e-gdbus-marshallers.list | 14 -
calendar/libegdbus/e-gdbus-typemappers.h | 11 -
configure.ac | 14 +-
libedataserver/Makefile.am | 17 +-
libedataserver/e-client-private.h | 122 +
libedataserver/e-client.c | 2489 +++++++
libedataserver/e-client.h | 167 +
libedataserver/e-credentials.c | 560 ++
libedataserver/e-credentials.h | 87 +
libedataserver/e-data-server-util.c | 84 +
libedataserver/e-data-server-util.h | 5 +
.../e-gdbus-marshallers.list | 17 +-
libedataserver/e-gdbus-templates.c | 1710 +++++
libedataserver/e-gdbus-templates.h | 750 ++
libedataserver/e-operation-pool.c | 136 +
libedataserver/e-operation-pool.h | 36 +
libedataserverui/Makefile.am | 11 +-
libedataserverui/e-client-utils.c | 773 +++
libedataserverui/e-client-utils.h | 61 +
po/POTFILES.in | 8 +
tests/libebook/Makefile.am | 2 +-
tests/libebook/client/Makefile.am | 98 +
tests/libebook/client/client-test-utils.c | 433 ++
tests/libebook/client/client-test-utils.h | 27 +
tests/libebook/client/test-client-add-contact.c | 95 +
tests/libebook/client/test-client-async.c | 121 +
tests/libebook/client/test-client-examine.c | 399 ++
tests/libebook/client/test-client-get-contact.c | 70 +
tests/libebook/client/test-client-get-view.c | 180 +
tests/libebook/client/test-client-modify-contact.c | 159 +
tests/libebook/client/test-client-nonexistent-id.c | 44 +
tests/libebook/client/test-client-refresh.c | 114 +
.../client/test-client-remove-contact-by-uid.c | 127 +
tests/libebook/client/test-client-remove-contact.c | 130 +
.../libebook/client/test-client-remove-contacts.c | 160 +
tests/libebook/client/test-client-remove.c | 69 +
tests/libebook/client/test-client-search.c | 67 +
tests/libebook/client/test-client-self.c | 46 +
.../client/test-client-stress-factory--fifo.c | 50 +
.../client/test-client-stress-factory--serial.c | 37 +
.../test-client-stress-factory--single-book.c | 62 +
tests/libebook/client/test-client-stress-views.c | 128 +
tests/libebook/client/test-client.c | 82 +
tests/libebook/test-categories.c | 2 +-
tests/libebook/test-date.c | 2 +-
tests/libebook/test-photo.c | 2 +-
tests/libebook/test-query.c | 2 +-
tests/libebook/test-string.c | 2 +-
tests/libebook/test-undefinedfield.c | 2 +-
tests/libebook/test-untyped-phones.c | 2 +-
tests/libecal/Makefile.am | 2 +
tests/libecal/client/Makefile.am | 89 +
tests/libecal/client/client-test-utils.c | 350 +
tests/libecal/client/client-test-utils.h | 25 +
tests/libecal/client/test-client-add-timezone.c | 209 +
tests/libecal/client/test-client-create-object.c | 297 +
tests/libecal/client/test-client-examine.c | 487 ++
.../client/test-client-get-attachment-uris.c | 191 +
tests/libecal/client/test-client-get-free-busy.c | 164 +
tests/libecal/client/test-client-get-object-list.c | 203 +
tests/libecal/client/test-client-get-view.c | 230 +
tests/libecal/client/test-client-modify-object.c | 194 +
tests/libecal/client/test-client-open.c | 124 +
tests/libecal/client/test-client-receive-objects.c | 142 +
tests/libecal/client/test-client-refresh.c | 134 +
tests/libecal/client/test-client-remove-object.c | 156 +
tests/libecal/client/test-client-send-objects.c | 169 +
.../client/test-client-stress-factory--fifo.c | 51 +
.../client/test-client-stress-factory--serial.c | 38 +
.../test-client-stress-factory--single-cal.c | 63 +
tests/libecal/client/test-client-stress-views.c | 116 +
tests/libecal/ecal-test-utils.c | 1 -
tests/libecal/test-ecal-get-free-busy.c | 3 +-
tests/libedataserverui/Makefile.am | 5 +
tests/libedataserverui/test-client-examine-auth.c | 418 ++
164 files changed, 34322 insertions(+), 29102 deletions(-)
---
diff --git a/addressbook/backends/file/e-book-backend-file.c b/addressbook/backends/file/e-book-backend-file.c
index 6f33d8d..1b09182 100644
--- a/addressbook/backends/file/e-book-backend-file.c
+++ b/addressbook/backends/file/e-book-backend-file.c
@@ -248,7 +248,7 @@ do_create (EBookBackendFile *bf,
static void
e_book_backend_file_create_contact (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
const gchar *vcard,
EContact **contact,
GError **perror)
@@ -263,18 +263,18 @@ e_book_backend_file_create_contact (EBookBackendSync *backend,
static void
e_book_backend_file_remove_contacts (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
- GList *id_list,
- GList **ids,
+ GCancellable *cancellable,
+ const GSList *id_list,
+ GSList **ids,
GError **perror)
{
EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
DB *db = bf->priv->file_db;
DBT id_dbt;
gint db_error;
- gchar *id;
- GList *l;
- GList *removed_cards = NULL;
+ const gchar *id;
+ const GSList *l;
+ GSList *removed_cards = NULL;
for (l = id_list; l; l = l->next) {
id = l->data;
@@ -288,7 +288,7 @@ e_book_backend_file_remove_contacts (EBookBackendSync *backend,
continue;
}
- removed_cards = g_list_prepend (removed_cards, id);
+ removed_cards = g_slist_prepend (removed_cards, g_strdup (id));
}
/* if we actually removed some, try to sync */
@@ -301,7 +301,7 @@ e_book_backend_file_remove_contacts (EBookBackendSync *backend,
*ids = removed_cards;
for (l = removed_cards; l; l = l->next) {
- gchar *id = l->data;
+ id = l->data;
e_book_backend_summary_remove_contact (bf->priv->summary, id);
}
}
@@ -309,7 +309,7 @@ e_book_backend_file_remove_contacts (EBookBackendSync *backend,
static void
e_book_backend_file_modify_contact (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
const gchar *vcard,
EContact **contact,
GError **perror)
@@ -368,7 +368,7 @@ e_book_backend_file_modify_contact (EBookBackendSync *backend,
static void
e_book_backend_file_get_contact (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
const gchar *id,
gchar **vcard,
GError **perror)
@@ -400,9 +400,9 @@ e_book_backend_file_get_contact (EBookBackendSync *backend,
static void
e_book_backend_file_get_contact_list (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
const gchar *query,
- GList **contacts,
+ GSList **contacts,
GError **perror)
{
EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
@@ -413,7 +413,7 @@ e_book_backend_file_get_contact_list (EBookBackendSync *backend,
EBookBackendSExp *card_sexp = NULL;
gboolean search_needed;
const gchar *search = query;
- GList *contact_list = NULL;
+ GSList *contact_list = NULL;
d(printf ("e_book_backend_file_get_contact_list (%s)\n", search));
if (e_book_backend_summary_is_summary_query (bf->priv->summary, search)) {
@@ -435,7 +435,7 @@ e_book_backend_file_get_contact_list (EBookBackendSync *backend,
db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0);
if (db_error == 0) {
- contact_list = g_list_prepend (contact_list, vcard_dbt.data);
+ contact_list = g_slist_prepend (contact_list, vcard_dbt.data);
} else {
g_warning (G_STRLOC ": db->get failed with %s", db_strerror (db_error));
db_error_to_gerror (db_error, perror);
@@ -475,7 +475,7 @@ e_book_backend_file_get_contact_list (EBookBackendSync *backend,
|| strcmp (id_dbt.data, E_BOOK_BACKEND_FILE_VERSION_NAME)) {
if ((!search_needed) || (card_sexp != NULL && e_book_backend_sexp_match_vcard (card_sexp, vcard_dbt.data))) {
- contact_list = g_list_prepend (contact_list, vcard_dbt.data);
+ contact_list = g_slist_prepend (contact_list, vcard_dbt.data);
}
}
@@ -567,10 +567,10 @@ book_view_thread (gpointer data)
query = e_data_book_view_get_card_query (book_view);
if ( !strcmp (query, "(contains \"x-evolution-any-field\" \"\")")) {
- e_data_book_view_notify_status_message (book_view, _("Loading..."));
+ e_data_book_view_notify_progress (book_view, -1, _("Loading..."));
allcontacts = TRUE;
} else {
- e_data_book_view_notify_status_message (book_view, _("Searching..."));
+ e_data_book_view_notify_progress (book_view, -1, _("Searching..."));
allcontacts = FALSE;
}
@@ -695,262 +695,59 @@ e_book_backend_file_stop_book_view (EBookBackend *backend,
g_thread_join (closure->thread);
}
-typedef struct {
- DB *db;
-
- GList *add_cards;
- GList *add_ids;
- GList *mod_cards;
- GList *mod_ids;
- GList *del_ids;
- GList *del_cards;
-} EBookBackendFileChangeContext;
-
-static void
-e_book_backend_file_changes_foreach_key (const gchar *key, gpointer user_data)
+static gchar *
+e_book_backend_file_extract_path_from_source (ESource *source)
{
- EBookBackendFileChangeContext *ctx = user_data;
- DB *db = ctx->db;
- DBT id_dbt, vcard_dbt;
- gint db_error = 0;
-
- string_to_dbt (key, &id_dbt);
- memset (&vcard_dbt, 0, sizeof (vcard_dbt));
- vcard_dbt.flags = DB_DBT_MALLOC;
-
- db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0);
-
- if (db_error != 0) {
- EContact *contact;
- gchar *id = id_dbt.data;
- gchar *vcard_string;
-
- contact = e_contact_new ();
- e_contact_set (contact, E_CONTACT_UID, id);
-
- vcard_string = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
-
- ctx->del_ids = g_list_append (ctx->del_ids,
- g_strdup (id));
- ctx->del_cards = g_list_append (ctx->del_cards,
- vcard_string);
+ gchar *filename = NULL;
+ const gchar *absolute_uri;
- g_object_unref (contact);
-
- g_free (vcard_dbt.data);
- }
-}
+ absolute_uri = e_source_peek_absolute_uri (source);
-static void
-e_book_backend_file_get_changes (EBookBackendSync *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *change_id,
- GList **changes_out,
- GError **perror)
-{
- EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
- gint db_error = 0;
- DBT id_dbt, vcard_dbt;
- gchar *filename;
- EDbHash *ehash;
- GList *i, *v;
- DB *db = bf->priv->file_db;
- DBC *dbc;
- GList *changes = NULL;
- EBookBackendFileChangeContext ctx;
+ if (absolute_uri && g_str_has_prefix (absolute_uri, "local://")) {
+ gchar *uri;
- memset (&id_dbt, 0, sizeof (id_dbt));
- memset (&vcard_dbt, 0, sizeof (vcard_dbt));
+ uri = g_strconcat ("file://", absolute_uri + 8, NULL);
+ filename = g_filename_from_uri (uri, NULL, NULL);
+ g_free (uri);
- memset (&ctx, 0, sizeof (ctx));
-
- ctx.db = db;
-
- /* Find the changed ids */
- filename = g_strdup_printf ("%s/%s" CHANGES_DB_SUFFIX, bf->priv->dirname, change_id);
- ehash = e_dbhash_new (filename);
- g_free (filename);
-
- db_error = db->cursor (db, NULL, &dbc, 0);
-
- if (db_error != 0) {
- g_warning (G_STRLOC ": db->cursor failed with %s", db_strerror (db_error));
- } else {
- db_error = dbc->c_get (dbc, &id_dbt, &vcard_dbt, DB_FIRST);
-
- while (db_error == 0) {
-
- /* don't include the version in the list of cards */
- if (id_dbt.size != strlen (E_BOOK_BACKEND_FILE_VERSION_NAME) + 1
- || strcmp (id_dbt.data, E_BOOK_BACKEND_FILE_VERSION_NAME)) {
- EContact *contact;
- gchar *id = id_dbt.data;
- gchar *vcard_string;
-
- /* Remove fields the user can't change
- * and can change without the rest of the
- * card changing
- */
- contact = create_contact (id_dbt.data, vcard_dbt.data);
-
-#ifdef notyet
- g_object_set (card, "last_use", NULL, "use_score", 0.0, NULL);
-#endif
- vcard_string = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
- g_object_unref (contact);
-
- /* check what type of change has occurred, if any */
- switch (e_dbhash_compare (ehash, id, vcard_string)) {
- case E_DBHASH_STATUS_SAME:
- g_free (vcard_string);
- break;
- case E_DBHASH_STATUS_NOT_FOUND:
- ctx.add_cards = g_list_append (ctx.add_cards, vcard_string);
- ctx.add_ids = g_list_append (ctx.add_ids, g_strdup (id));
- break;
- case E_DBHASH_STATUS_DIFFERENT:
- ctx.mod_cards = g_list_append (ctx.mod_cards, vcard_string);
- ctx.mod_ids = g_list_append (ctx.mod_ids, g_strdup (id));
- break;
- }
- }
-
- db_error = dbc->c_get (dbc, &id_dbt, &vcard_dbt, DB_NEXT);
- }
- dbc->c_close (dbc);
- }
-
- e_dbhash_foreach_key (ehash, (EDbHashFunc) e_book_backend_file_changes_foreach_key, &ctx);
-
- /* Send the changes */
- if (db_error != DB_NOTFOUND) {
- g_warning ("e_book_backend_file_changes: error building list\n");
- *changes_out = NULL;
- db_error_to_gerror (db_error, perror);
+ if (!g_file_test (filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
+ g_free (filename);
+ filename = NULL;
+ }
}
- else {
- /* Update the hash and build our changes list */
- for (i = ctx.add_ids, v = ctx.add_cards; i != NULL; i = i->next, v = v->next) {
- gchar *id = i->data;
- gchar *vcard = v->data;
- e_dbhash_add (ehash, id, vcard);
- changes = g_list_prepend (changes,
- e_book_backend_change_add_new (vcard));
+ if (!filename) {
+ const gchar *user_data_dir;
+ const gchar *source_dir;
+ gchar *mangled_source_dir;
- g_free (i->data);
- g_free (v->data);
- }
- for (i = ctx.mod_ids, v = ctx.mod_cards; i != NULL; i = i->next, v = v->next) {
- gchar *id = i->data;
- gchar *vcard = v->data;
+ user_data_dir = e_get_user_data_dir ();
+ source_dir = e_source_peek_relative_uri (source);
- e_dbhash_add (ehash, id, vcard);
- changes = g_list_prepend (changes,
- e_book_backend_change_modify_new (vcard));
+ if (!source_dir || !g_str_equal (source_dir, "system"))
+ source_dir = e_source_peek_uid (source);
- g_free (i->data);
- g_free (v->data);
- }
- for (i = ctx.del_ids, v = ctx.del_cards; i != NULL; i = i->next, v = v->next) {
- gchar *id = i->data;
- gchar *vcard = v->data;
-
- e_dbhash_remove (ehash, id);
+ /* Mangle the URI to not contain invalid characters. */
+ mangled_source_dir = g_strdelimit (g_strdup (source_dir), ":/", '_');
- changes = g_list_prepend (changes,
- e_book_backend_change_delete_new (vcard));
- g_free (i->data);
- g_free (v->data);
- }
+ filename = g_build_filename (
+ user_data_dir, "addressbook", mangled_source_dir, NULL);
- e_dbhash_write (ehash);
-
- *changes_out = changes;
+ g_free (mangled_source_dir);
}
- e_dbhash_destroy (ehash);
-}
-
-static gchar *
-e_book_backend_file_extract_path_from_source (ESource *source)
-{
- const gchar *user_data_dir;
- const gchar *source_dir;
- gchar *mangled_source_dir;
- gchar *filename;
-
- user_data_dir = e_get_user_data_dir ();
- source_dir = e_source_peek_relative_uri (source);
-
- if (!source_dir || !g_str_equal (source_dir, "system"))
- source_dir = e_source_peek_uid (source);
-
- /* Mangle the URI to not contain invalid characters. */
- mangled_source_dir = g_strdelimit (g_strdup (source_dir), ":/", '_');
-
- filename = g_build_filename (
- user_data_dir, "addressbook", mangled_source_dir, NULL);
-
- g_free (mangled_source_dir);
-
return filename;
}
static void
e_book_backend_file_authenticate_user (EBookBackendSync *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *user,
- const gchar *passwd,
- const gchar *auth_method,
+ GCancellable *cancellable,
+ ECredentials *credentials,
GError **perror)
{
/* Success */
}
-static void
-e_book_backend_file_get_required_fields (EBookBackendSync *backend,
- EDataBook *book,
- guint32 opid,
- GList **fields_out,
- GError **perror)
-{
- GList *fields = NULL;
-
- fields = g_list_append (fields , g_strdup (e_contact_field_name (E_CONTACT_FILE_AS)));
- *fields_out = fields;
-}
-
-static void
-e_book_backend_file_get_supported_auth_methods (EBookBackendSync *backend,
- EDataBook *book,
- guint32 opid,
- GList **methods_out,
- GError **perror)
-{
- *methods_out = NULL;
-}
-
-static void
-e_book_backend_file_get_supported_fields (EBookBackendSync *backend,
- EDataBook *book,
- guint32 opid,
- GList **fields_out,
- GError **perror)
-{
- GList *fields = NULL;
- gint i;
-
- /* XXX we need a way to say "we support everything", since the
- file backend does */
- for (i = 1; i < E_CONTACT_FIELD_LAST; i++)
- fields = g_list_append (fields, g_strdup (e_contact_field_name (i)));
-
- *fields_out = fields;
-}
-
/*
** versions:
**
@@ -1095,14 +892,16 @@ file_errcall (const gchar *buf1, gchar *buf2)
}
static void
-e_book_backend_file_load_source (EBookBackend *backend,
- ESource *source,
- gboolean only_if_exists,
- GError **perror)
+e_book_backend_file_open (EBookBackendSync *backend,
+ EDataBook *book,
+ GCancellable *cancellable,
+ gboolean only_if_exists,
+ GError **perror)
{
EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
gchar *dirname, *filename;
- gboolean writable = FALSE;
+ gboolean readonly = TRUE;
+ ESource *source = e_book_backend_get_source (E_BOOK_BACKEND (backend));
gint db_error;
DB *db;
DB_ENV *env;
@@ -1208,7 +1007,7 @@ e_book_backend_file_load_source (EBookBackend *backend,
}
if (db_error == 0) {
- writable = TRUE;
+ readonly = FALSE;
} else {
db->close (db, 0);
db_error = db_create (&db, env, 0);
@@ -1252,7 +1051,7 @@ e_book_backend_file_load_source (EBookBackend *backend,
db_error = (*db->open) (db, NULL, filename, NULL, DB_HASH, DB_CREATE | DB_THREAD, 0666);
if (db_error != 0) {
db->close (db, 0);
- g_warning ("db->open (... DB_CREATE ...) failed with %s", db_strerror (db_error));
+ g_warning ("db->open (... %s ... DB_CREATE ...) failed with %s", filename, db_strerror (db_error));
}
else {
#ifdef CREATE_DEFAULT_VCARD
@@ -1264,7 +1063,7 @@ e_book_backend_file_load_source (EBookBackend *backend,
g_object_unref (contact);
#endif
- writable = TRUE;
+ readonly = FALSE;
}
}
}
@@ -1313,8 +1112,9 @@ e_book_backend_file_load_source (EBookBackend *backend,
}
}
- e_book_backend_set_is_loaded (backend, TRUE);
- e_book_backend_set_is_writable (backend, writable);
+ e_book_backend_notify_online (E_BOOK_BACKEND (backend), TRUE);
+ e_book_backend_notify_readonly (E_BOOK_BACKEND (backend), readonly);
+ e_book_backend_notify_opened (E_BOOK_BACKEND (backend), NULL /* Success */);
}
static gboolean
@@ -1338,7 +1138,7 @@ select_changes (const gchar *name)
static void
e_book_backend_file_remove (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
GError **perror)
{
EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
@@ -1386,25 +1186,43 @@ e_book_backend_file_remove (EBookBackendSync *backend,
that the addressbook is still valid */
}
-static gchar *
-e_book_backend_file_get_static_capabilities (EBookBackend *backend)
+static gboolean
+e_book_backend_file_get_backend_property (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error)
{
- return g_strdup("local,do-initial-query,bulk-removes,contact-lists");
-}
+ gboolean processed = TRUE;
-static void
-e_book_backend_file_cancel_operation (EBookBackend *backend, EDataBook *book, GError **perror)
-{
- g_propagate_error (perror, EDB_ERROR (COULD_NOT_CANCEL));
+ g_return_val_if_fail (prop_name != NULL, FALSE);
+ g_return_val_if_fail (prop_value != NULL, FALSE);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ *prop_value = g_strdup ("local,do-initial-query,bulk-removes,contact-lists");
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+ *prop_value = g_strdup (e_contact_field_name (E_CONTACT_FILE_AS));
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+ GSList *fields = NULL;
+ gint i;
+
+ /* XXX we need a way to say "we support everything", since the
+ file backend does */
+ for (i = 1; i < E_CONTACT_FIELD_LAST; i++)
+ fields = g_slist_append (fields, (gpointer) e_contact_field_name (i));
+
+ *prop_value = e_data_book_string_slist_to_comma_string (fields);
+ g_slist_free (fields);
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS)) {
+ *prop_value = NULL;
+ } else {
+ processed = FALSE;
+ }
+
+ return processed;
}
static void
-e_book_backend_file_set_mode (EBookBackend *backend, EDataBookMode mode)
+e_book_backend_file_set_online (EBookBackend *backend, gboolean is_online)
{
- if (e_book_backend_is_loaded (backend)) {
- e_book_backend_notify_writable (backend, TRUE);
- e_book_backend_notify_connection_status (backend, TRUE);
- }
+ if (e_book_backend_is_opened (backend))
+ e_book_backend_notify_online (backend, TRUE);
}
static void
@@ -1530,24 +1348,20 @@ e_book_backend_file_class_init (EBookBackendFileClass *klass)
backend_class = E_BOOK_BACKEND_CLASS (klass);
/* Set the virtual methods. */
- backend_class->load_source = e_book_backend_file_load_source;
- backend_class->get_static_capabilities = e_book_backend_file_get_static_capabilities;
- backend_class->start_book_view = e_book_backend_file_start_book_view;
- backend_class->stop_book_view = e_book_backend_file_stop_book_view;
- backend_class->cancel_operation = e_book_backend_file_cancel_operation;
- backend_class->set_mode = e_book_backend_file_set_mode;
- backend_class->sync = e_book_backend_file_sync;
- sync_class->remove_sync = e_book_backend_file_remove;
- sync_class->create_contact_sync = e_book_backend_file_create_contact;
- sync_class->remove_contacts_sync = e_book_backend_file_remove_contacts;
- sync_class->modify_contact_sync = e_book_backend_file_modify_contact;
- sync_class->get_contact_sync = e_book_backend_file_get_contact;
- sync_class->get_contact_list_sync = e_book_backend_file_get_contact_list;
- sync_class->get_changes_sync = e_book_backend_file_get_changes;
- sync_class->authenticate_user_sync = e_book_backend_file_authenticate_user;
- sync_class->get_supported_auth_methods_sync = e_book_backend_file_get_supported_auth_methods;
- sync_class->get_supported_fields_sync = e_book_backend_file_get_supported_fields;
- sync_class->get_required_fields_sync = e_book_backend_file_get_required_fields;
+ backend_class->start_book_view = e_book_backend_file_start_book_view;
+ backend_class->stop_book_view = e_book_backend_file_stop_book_view;
+ backend_class->set_online = e_book_backend_file_set_online;
+ backend_class->sync = e_book_backend_file_sync;
+
+ sync_class->open_sync = e_book_backend_file_open;
+ sync_class->remove_sync = e_book_backend_file_remove;
+ sync_class->get_backend_property_sync = e_book_backend_file_get_backend_property;
+ sync_class->create_contact_sync = e_book_backend_file_create_contact;
+ sync_class->remove_contacts_sync = e_book_backend_file_remove_contacts;
+ sync_class->modify_contact_sync = e_book_backend_file_modify_contact;
+ sync_class->get_contact_sync = e_book_backend_file_get_contact;
+ sync_class->get_contact_list_sync = e_book_backend_file_get_contact_list;
+ sync_class->authenticate_user_sync = e_book_backend_file_authenticate_user;
object_class->dispose = e_book_backend_file_dispose;
object_class->finalize = e_book_backend_file_finalize;
diff --git a/addressbook/backends/google/e-book-backend-google.c b/addressbook/backends/google/e-book-backend-google.c
index 0d39bc2..0ac563e 100644
--- a/addressbook/backends/google/e-book-backend-google.c
+++ b/addressbook/backends/google/e-book-backend-google.c
@@ -51,7 +51,7 @@ typedef enum {
} CacheType;
struct _EBookBackendGooglePrivate {
- EDataBookMode mode;
+ gboolean is_online;
GList *bookviews;
CacheType cache_type;
@@ -371,7 +371,7 @@ cache_needs_update (EBookBackend *backend, guint *remaining_secs)
*remaining_secs = G_MAXUINT;
/* We never want to update in offline mode */
- if (priv->mode != E_DATA_BOOK_MODE_REMOTE)
+ if (!priv->is_online)
return FALSE;
rv = cache_get_last_update_tv (backend, &last);
@@ -463,19 +463,21 @@ on_sequence_complete (EBookBackend *backend, GError *error)
}
static GCancellable *
-start_operation (EBookBackend *backend, guint32 opid, const gchar *message)
+start_operation (EBookBackend *backend, guint32 opid, GCancellable *cancellable, const gchar *message)
{
EBookBackendGooglePrivate *priv = E_BOOK_BACKEND_GOOGLE (backend)->priv;
- GCancellable *cancellable;
GList *iter;
/* Insert the operation into the set of active cancellable operations */
- cancellable = g_cancellable_new ();
+ if (cancellable)
+ g_object_ref (cancellable);
+ else
+ cancellable = g_cancellable_new ();
g_hash_table_insert (priv->cancellables, GUINT_TO_POINTER (opid), g_object_ref (cancellable));
/* Send out a status message to each view */
for (iter = priv->bookviews; iter; iter = iter->next)
- e_data_book_view_notify_status_message (E_DATA_BOOK_VIEW (iter->data), message);
+ e_data_book_view_notify_progress (E_DATA_BOOK_VIEW (iter->data), -1, message);
return cancellable;
}
@@ -586,7 +588,7 @@ get_new_contacts (EBookBackend *backend)
}
/* Query for new contacts asynchronously */
- cancellable = start_operation (backend, 0, _("Querying for updated contactsâ?¦"));
+ cancellable = start_operation (backend, 0, NULL, _("Querying for updated contactsâ?¦"));
gdata_contacts_service_query_contacts_async (GDATA_CONTACTS_SERVICE (priv->service), query, cancellable,
(GDataQueryProgressCallback) (last_updated ? process_subsequent_entry : process_initial_entry),
backend, (GAsyncReadyCallback) get_new_contacts_cb, backend);
@@ -704,7 +706,7 @@ get_groups (EBookBackend *backend)
}
/* Run the query asynchronously */
- cancellable = start_operation (backend, 1, _("Querying for updated groupsâ?¦"));
+ cancellable = start_operation (backend, 1, NULL, _("Querying for updated groupsâ?¦"));
gdata_contacts_service_query_groups_async (GDATA_CONTACTS_SERVICE (priv->service), query, cancellable,
(GDataQueryProgressCallback) process_group, backend, (GAsyncReadyCallback) get_groups_cb, backend);
@@ -768,8 +770,8 @@ cache_refresh_if_needed (EBookBackend *backend)
__debug__ (G_STRFUNC);
- if (priv->mode != E_DATA_BOOK_MODE_REMOTE || !priv->service || !gdata_service_is_authenticated (priv->service)) {
- __debug__ ("We are not connected to Google%s.", (priv->mode != E_DATA_BOOK_MODE_REMOTE) ? " (offline mode)" : "");
+ if (!priv->is_online || !priv->service || !gdata_service_is_authenticated (priv->service)) {
+ __debug__ ("We are not connected to Google%s.", (!priv->is_online) ? " (offline mode)" : "");
return TRUE;
}
@@ -852,20 +854,19 @@ finish:
}
static void
-e_book_backend_google_create_contact (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *vcard_str)
+e_book_backend_google_create_contact (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *vcard_str)
{
EBookBackendGooglePrivate *priv = E_BOOK_BACKEND_GOOGLE (backend)->priv;
EContact *contact;
GDataEntry *entry;
gchar *xml;
CreateContactData *data;
- GCancellable *cancellable;
__debug__ (G_STRFUNC);
__debug__ ("Creating: %s", vcard_str);
- if (priv->mode != E_DATA_BOOK_MODE_REMOTE) {
+ if (!priv->is_online) {
e_data_book_respond_create (book, opid, EDB_ERROR (OFFLINE_UNAVAILABLE), NULL);
return;
}
@@ -888,7 +889,7 @@ e_book_backend_google_create_contact (EBookBackend *backend, EDataBook *book, gu
data->book = g_object_ref (book);
data->opid = opid;
- cancellable = start_operation (backend, opid, _("Creating new contactâ?¦"));
+ cancellable = start_operation (backend, opid, cancellable, _("Creating new contactâ?¦"));
gdata_contacts_service_insert_contact_async (GDATA_CONTACTS_SERVICE (priv->service), GDATA_CONTACTS_CONTACT (entry), cancellable,
(GAsyncReadyCallback) create_contact_cb, data);
g_object_unref (cancellable);
@@ -907,7 +908,7 @@ remove_contact_cb (GDataService *service, GAsyncResult *result, RemoveContactDat
{
GError *gdata_error = NULL;
gboolean success;
- GList *ids;
+ GSList *ids;
__debug__ (G_STRFUNC);
@@ -925,9 +926,9 @@ remove_contact_cb (GDataService *service, GAsyncResult *result, RemoveContactDat
}
/* List the entry's ID in the success list */
- ids = g_list_prepend (NULL, data->uid);
+ ids = g_slist_prepend (NULL, data->uid);
e_data_book_respond_remove_contacts (data->book, data->opid, NULL, ids);
- g_list_free (ids);
+ g_slist_free (ids);
finish:
g_free (data->uid);
@@ -937,18 +938,17 @@ finish:
}
static void
-e_book_backend_google_remove_contacts (EBookBackend *backend, EDataBook *book, guint32 opid, GList *id_list)
+e_book_backend_google_remove_contacts (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const GSList *id_list)
{
EBookBackendGooglePrivate *priv = E_BOOK_BACKEND_GOOGLE (backend)->priv;
const gchar *uid = id_list->data;
GDataEntry *entry = NULL;
EContact *cached_contact;
- GCancellable *cancellable;
RemoveContactData *data;
__debug__ (G_STRFUNC);
- if (priv->mode != E_DATA_BOOK_MODE_REMOTE) {
+ if (!priv->is_online) {
e_data_book_respond_remove_contacts (book, opid, EDB_ERROR (OFFLINE_UNAVAILABLE), NULL);
return;
}
@@ -981,7 +981,7 @@ e_book_backend_google_remove_contacts (EBookBackend *backend, EDataBook *book, g
data->opid = opid;
data->uid = g_strdup (uid);
- cancellable = start_operation (backend, opid, _("Deleting contactâ?¦"));
+ cancellable = start_operation (backend, opid, cancellable, _("Deleting contactâ?¦"));
gdata_service_delete_entry_async (GDATA_SERVICE (priv->service), entry, cancellable, (GAsyncReadyCallback) remove_contact_cb, data);
g_object_unref (cancellable);
g_object_unref (entry);
@@ -1035,20 +1035,19 @@ finish:
}
static void
-e_book_backend_google_modify_contact (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *vcard_str)
+e_book_backend_google_modify_contact (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *vcard_str)
{
EBookBackendGooglePrivate *priv = E_BOOK_BACKEND_GOOGLE (backend)->priv;
EContact *contact, *cached_contact;
GDataEntry *entry = NULL;
const gchar *uid;
ModifyContactData *data;
- GCancellable *cancellable;
__debug__ (G_STRFUNC);
__debug__ ("Updating: %s", vcard_str);
- if (priv->mode != E_DATA_BOOK_MODE_REMOTE) {
+ if (!priv->is_online) {
e_data_book_respond_modify (book, opid, EDB_ERROR (OFFLINE_UNAVAILABLE), NULL);
return;
}
@@ -1089,14 +1088,14 @@ e_book_backend_google_modify_contact (EBookBackend *backend, EDataBook *book, gu
data->book = g_object_ref (book);
data->opid = opid;
- cancellable = start_operation (backend, opid, _("Modifying contactâ?¦"));
+ cancellable = start_operation (backend, opid, cancellable, _("Modifying contactâ?¦"));
gdata_service_update_entry_async (GDATA_SERVICE (priv->service), entry, cancellable, (GAsyncReadyCallback) modify_contact_cb, data);
g_object_unref (cancellable);
g_object_unref (entry);
}
static void
-e_book_backend_google_get_contact (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *uid)
+e_book_backend_google_get_contact (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *uid)
{
EContact *contact;
gchar *vcard_str;
@@ -1120,10 +1119,11 @@ e_book_backend_google_get_contact (EBookBackend *backend, EDataBook *book, guint
}
static void
-e_book_backend_google_get_contact_list (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *query)
+e_book_backend_google_get_contact_list (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *query)
{
EBookBackendSExp *sexp;
- GList *all_contacts, *filtered_contacts = NULL;
+ GList *all_contacts;
+ GSList *filtered_contacts = NULL;
__debug__ (G_STRFUNC);
@@ -1137,7 +1137,7 @@ e_book_backend_google_get_contact_list (EBookBackend *backend, EDataBook *book,
/* If the search expression matches the contact, include it in the search results */
if (e_book_backend_sexp_match_contact (sexp, contact)) {
gchar *vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
- filtered_contacts = g_list_append (filtered_contacts, vcard_str);
+ filtered_contacts = g_slist_append (filtered_contacts, vcard_str);
}
g_object_unref (contact);
@@ -1146,7 +1146,9 @@ e_book_backend_google_get_contact_list (EBookBackend *backend, EDataBook *book,
g_object_unref (sexp);
e_data_book_respond_get_contact_list (book, opid, NULL, filtered_contacts);
- g_list_free (filtered_contacts);
+
+ g_slist_foreach (filtered_contacts, (GFunc) g_free, NULL);
+ g_slist_free (filtered_contacts);
}
static gboolean
@@ -1196,7 +1198,7 @@ e_book_backend_google_start_book_view (EBookBackend *backend, EDataBookView *boo
priv->bookviews = g_list_append (priv->bookviews, bookview);
e_data_book_view_ref (bookview);
- e_data_book_view_notify_status_message (bookview, _("Loadingâ?¦"));
+ e_data_book_view_notify_progress (bookview, -1, _("Loadingâ?¦"));
/* Ensure that we're ready to support a view */
set_live_mode (backend, TRUE);
@@ -1205,7 +1207,7 @@ e_book_backend_google_start_book_view (EBookBackend *backend, EDataBookView *boo
if (cache_needs_update (backend, NULL)) {
if (!priv->service || !gdata_service_is_authenticated (priv->service)) {
/* We need authorization first */
- e_book_backend_notify_auth_required (backend);
+ e_book_backend_notify_auth_required (backend, TRUE, NULL);
} else {
/* Update in an idle function, so that this call doesn't block */
priv->idle_id = g_idle_add ((GSourceFunc) on_refresh_idle, backend);
@@ -1268,7 +1270,6 @@ proxy_settings_changed (EProxy *proxy, EBookBackend *backend)
typedef struct {
EBookBackend *backend;
- EDataBook *book;
guint32 opid;
} AuthenticateUserData;
@@ -1288,40 +1289,38 @@ authenticate_user_cb (GDataService *service, GAsyncResult *result, AuthenticateU
}
finish_operation (data->backend, data->opid);
- e_book_backend_notify_writable (data->backend, (!gdata_error) ? TRUE : FALSE);
- e_data_book_respond_authenticate_user (data->book, data->opid, book_error);
+ e_book_backend_notify_readonly (data->backend, gdata_error ? TRUE : FALSE);
+ e_book_backend_notify_opened (data->backend, book_error);
- g_object_unref (data->book);
g_object_unref (data->backend);
g_slice_free (AuthenticateUserData, data);
}
static void
-e_book_backend_google_authenticate_user (EBookBackend *backend, EDataBook *book, guint32 opid,
- const gchar *username, const gchar *password, const gchar *auth_method)
+e_book_backend_google_authenticate_user (EBookBackend *backend, GCancellable *cancellable, ECredentials *credentials)
{
EBookBackendGooglePrivate *priv = E_BOOK_BACKEND_GOOGLE (backend)->priv;
AuthenticateUserData *data;
- GCancellable *cancellable;
+ guint32 opid;
__debug__ (G_STRFUNC);
- if (priv->mode != E_DATA_BOOK_MODE_REMOTE) {
- e_book_backend_notify_writable (backend, FALSE);
- e_book_backend_notify_connection_status (backend, FALSE);
- e_data_book_respond_authenticate_user (book, opid, EDB_ERROR (SUCCESS));
+ if (!priv->is_online) {
+ e_book_backend_notify_readonly (backend, TRUE);
+ e_book_backend_notify_online (backend, FALSE);
+ e_book_backend_notify_opened (backend, EDB_ERROR (SUCCESS));
return;
}
if (priv->service && gdata_service_is_authenticated (priv->service)) {
g_warning ("Connection to Google already established.");
- e_book_backend_notify_writable (backend, TRUE);
- e_data_book_respond_authenticate_user (book, opid, NULL);
+ e_book_backend_notify_readonly (backend, FALSE);
+ e_book_backend_notify_opened (backend, NULL);
return;
}
- if (!username || username[0] == 0 || !password || password[0] == 0) {
- e_data_book_respond_authenticate_user (book, opid, EDB_ERROR (AUTHENTICATION_FAILED));
+ if (!credentials || !e_credentials_has_key (credentials, E_CREDENTIALS_KEY_USERNAME) || !e_credentials_has_key (credentials, E_CREDENTIALS_KEY_PASSWORD)) {
+ e_book_backend_notify_opened (backend, EDB_ERROR (AUTHENTICATION_REQUIRED));
return;
}
@@ -1337,183 +1336,40 @@ e_book_backend_google_authenticate_user (EBookBackend *backend, EDataBook *book,
g_signal_connect (priv->proxy, "changed", G_CALLBACK (proxy_settings_changed), backend);
}
+ opid = -1;
+ while (g_hash_table_lookup (priv->cancellables, GUINT_TO_POINTER (opid)))
+ opid--;
+
/* Authenticate with the server asynchronously */
data = g_slice_new (AuthenticateUserData);
data->backend = g_object_ref (backend);
- data->book = g_object_ref (book);
data->opid = opid;
- cancellable = start_operation (backend, opid, _("Authenticating with the serverâ?¦"));
- gdata_service_authenticate_async (priv->service, username, password, cancellable, (GAsyncReadyCallback) authenticate_user_cb, data);
+ cancellable = start_operation (backend, opid, cancellable, _("Authenticating with the serverâ?¦"));
+ gdata_service_authenticate_async (priv->service, e_credentials_peek (credentials, E_CREDENTIALS_KEY_USERNAME), e_credentials_peek (credentials, E_CREDENTIALS_KEY_PASSWORD), cancellable, (GAsyncReadyCallback) authenticate_user_cb, data);
g_object_unref (cancellable);
}
static void
-e_book_backend_google_get_supported_auth_methods (EBookBackend *backend, EDataBook *book, guint32 opid)
-{
- GList methods = { (gpointer) "plain/password", NULL, NULL };
-
- __debug__ (G_STRFUNC);
- e_data_book_respond_get_supported_auth_methods (book, opid, NULL, &methods);
-}
-
-static void
-e_book_backend_google_get_required_fields (EBookBackend *backend, EDataBook *book, guint32 opid)
-{
- __debug__ (G_STRFUNC);
- e_data_book_respond_get_required_fields (book, opid, NULL, NULL);
-}
-
-static void
-e_book_backend_google_get_supported_fields (EBookBackend *backend, EDataBook *book, guint32 opid)
-{
- GList *fields = NULL;
- guint i;
- const gint supported_fields[] = {
- E_CONTACT_FULL_NAME,
- E_CONTACT_EMAIL_1,
- E_CONTACT_EMAIL_2,
- E_CONTACT_EMAIL_3,
- E_CONTACT_EMAIL_4,
- E_CONTACT_ADDRESS_LABEL_HOME,
- E_CONTACT_ADDRESS_LABEL_WORK,
- E_CONTACT_ADDRESS_LABEL_OTHER,
- E_CONTACT_PHONE_HOME,
- E_CONTACT_PHONE_HOME_FAX,
- E_CONTACT_PHONE_BUSINESS,
- E_CONTACT_PHONE_BUSINESS_FAX,
- E_CONTACT_PHONE_MOBILE,
- E_CONTACT_PHONE_PAGER,
- E_CONTACT_IM_AIM,
- E_CONTACT_IM_JABBER,
- E_CONTACT_IM_YAHOO,
- E_CONTACT_IM_MSN,
- E_CONTACT_IM_ICQ,
- E_CONTACT_IM_SKYPE,
- E_CONTACT_IM_GADUGADU,
- E_CONTACT_IM_GROUPWISE,
- E_CONTACT_ADDRESS,
- E_CONTACT_ADDRESS_HOME,
- E_CONTACT_ADDRESS_WORK,
- E_CONTACT_ADDRESS_OTHER,
- E_CONTACT_NAME,
- E_CONTACT_GIVEN_NAME,
- E_CONTACT_FAMILY_NAME,
- E_CONTACT_PHONE_ASSISTANT,
- E_CONTACT_PHONE_BUSINESS_2,
- E_CONTACT_PHONE_CALLBACK,
- E_CONTACT_PHONE_CAR,
- E_CONTACT_PHONE_COMPANY,
- E_CONTACT_PHONE_HOME_2,
- E_CONTACT_PHONE_ISDN,
- E_CONTACT_PHONE_OTHER,
- E_CONTACT_PHONE_OTHER_FAX,
- E_CONTACT_PHONE_PRIMARY,
- E_CONTACT_PHONE_RADIO,
- E_CONTACT_PHONE_TELEX,
- E_CONTACT_PHONE_TTYTDD,
- E_CONTACT_IM_AIM_HOME_1,
- E_CONTACT_IM_AIM_HOME_2,
- E_CONTACT_IM_AIM_HOME_3,
- E_CONTACT_IM_AIM_WORK_1,
- E_CONTACT_IM_AIM_WORK_2,
- E_CONTACT_IM_AIM_WORK_3,
- E_CONTACT_IM_GROUPWISE_HOME_1,
- E_CONTACT_IM_GROUPWISE_HOME_2,
- E_CONTACT_IM_GROUPWISE_HOME_3,
- E_CONTACT_IM_GROUPWISE_WORK_1,
- E_CONTACT_IM_GROUPWISE_WORK_2,
- E_CONTACT_IM_GROUPWISE_WORK_3,
- E_CONTACT_IM_JABBER_HOME_1,
- E_CONTACT_IM_JABBER_HOME_2,
- E_CONTACT_IM_JABBER_HOME_3,
- E_CONTACT_IM_JABBER_WORK_1,
- E_CONTACT_IM_JABBER_WORK_2,
- E_CONTACT_IM_JABBER_WORK_3,
- E_CONTACT_IM_YAHOO_HOME_1,
- E_CONTACT_IM_YAHOO_HOME_2,
- E_CONTACT_IM_YAHOO_HOME_3,
- E_CONTACT_IM_YAHOO_WORK_1,
- E_CONTACT_IM_YAHOO_WORK_2,
- E_CONTACT_IM_YAHOO_WORK_3,
- E_CONTACT_IM_MSN_HOME_1,
- E_CONTACT_IM_MSN_HOME_2,
- E_CONTACT_IM_MSN_HOME_3,
- E_CONTACT_IM_MSN_WORK_1,
- E_CONTACT_IM_MSN_WORK_2,
- E_CONTACT_IM_MSN_WORK_3,
- E_CONTACT_IM_ICQ_HOME_1,
- E_CONTACT_IM_ICQ_HOME_2,
- E_CONTACT_IM_ICQ_HOME_3,
- E_CONTACT_IM_ICQ_WORK_1,
- E_CONTACT_IM_ICQ_WORK_2,
- E_CONTACT_IM_ICQ_WORK_3,
- E_CONTACT_EMAIL,
- E_CONTACT_IM_GADUGADU_HOME_1,
- E_CONTACT_IM_GADUGADU_HOME_2,
- E_CONTACT_IM_GADUGADU_HOME_3,
- E_CONTACT_IM_GADUGADU_WORK_1,
- E_CONTACT_IM_GADUGADU_WORK_2,
- E_CONTACT_IM_GADUGADU_WORK_3,
- E_CONTACT_TEL,
- E_CONTACT_IM_SKYPE_HOME_1,
- E_CONTACT_IM_SKYPE_HOME_2,
- E_CONTACT_IM_SKYPE_HOME_3,
- E_CONTACT_IM_SKYPE_WORK_1,
- E_CONTACT_IM_SKYPE_WORK_2,
- E_CONTACT_IM_SKYPE_WORK_3,
- E_CONTACT_SIP,
- E_CONTACT_ORG,
- E_CONTACT_ORG_UNIT,
- E_CONTACT_TITLE,
- E_CONTACT_ROLE,
- E_CONTACT_HOMEPAGE_URL,
- E_CONTACT_BLOG_URL,
- E_CONTACT_BIRTH_DATE,
- E_CONTACT_ANNIVERSARY,
- E_CONTACT_NOTE,
- E_CONTACT_CATEGORIES,
- E_CONTACT_CATEGORY_LIST
- };
-
- __debug__ (G_STRFUNC);
-
- /* Add all the fields above to the list */
- for (i = 0; i < G_N_ELEMENTS (supported_fields); i++) {
- const gchar *field_name = e_contact_field_name (supported_fields[i]);
- fields = g_list_prepend (fields, (gpointer) field_name);
- }
-
- e_data_book_respond_get_supported_fields (book, opid, NULL, fields);
- g_list_free (fields);
-}
-
-static void
-e_book_backend_google_get_changes (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *change_id)
-{
- __debug__ (G_STRFUNC);
- e_data_book_respond_get_changes (book, opid, EDB_ERROR (OTHER_ERROR), NULL);
-}
-
-static void
-e_book_backend_google_remove (EBookBackend *backend, EDataBook *book, guint32 opid)
+e_book_backend_google_remove (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
{
__debug__ (G_STRFUNC);
e_data_book_respond_remove (book, opid, NULL);
}
static void
-e_book_backend_google_load_source (EBookBackend *backend, ESource *source, gboolean only_if_exists, GError **error)
+e_book_backend_google_open (EBookBackend *backend, EDataBook *book, guint opid, GCancellable *cancellable, gboolean only_if_exists)
{
EBookBackendGooglePrivate *priv = E_BOOK_BACKEND_GOOGLE (backend)->priv;
const gchar *refresh_interval_str, *use_ssl_str, *use_cache_str;
guint refresh_interval;
gboolean use_ssl, use_cache;
+ ESource *source = e_book_backend_get_source (backend);
__debug__ (G_STRFUNC);
if (priv->cancellables) {
- g_propagate_error (error, EDB_ERROR_EX (OTHER_ERROR, "Source already loaded!"));
+ e_book_backend_respond_opened (backend, book, opid, EDB_ERROR_EX (OTHER_ERROR, "Source already loaded!"));
return;
}
@@ -1551,26 +1407,163 @@ e_book_backend_google_load_source (EBookBackend *backend, ESource *source, gbool
}
/* Set up ready to be interacted with */
- e_book_backend_set_is_loaded (backend, TRUE);
- e_book_backend_set_is_writable (backend, FALSE);
- e_book_backend_notify_connection_status (backend, (priv->mode == E_DATA_BOOK_MODE_REMOTE) ? TRUE : FALSE);
+ e_book_backend_notify_online (backend, priv->is_online);
+ e_book_backend_notify_readonly (backend, TRUE);
- if (priv->mode == E_DATA_BOOK_MODE_REMOTE) {
+ if (priv->is_online) {
/* We're going online, so we need to authenticate and create the service and proxy.
* This is done in e_book_backend_google_authenticate_user() when it gets the authentication data. */
- e_book_backend_notify_auth_required (backend);
+ e_book_backend_notify_auth_required (backend, TRUE, NULL);
+ } else {
+ e_book_backend_notify_opened (backend, NULL /* Success */);
}
+
+ e_data_book_respond_open (book, opid, NULL /* Success */);
}
-static gchar *
-e_book_backend_google_get_static_capabilities (EBookBackend *backend)
+static void
+e_book_backend_google_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
{
__debug__ (G_STRFUNC);
- return g_strdup ("net,do-initial-query,contact-lists");
+
+ g_return_if_fail (prop_name != NULL);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ e_data_book_respond_get_backend_property (book, opid, NULL, "net,do-initial-query,contact-lists");
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+ e_data_book_respond_get_backend_property (book, opid, NULL, "");
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+ GSList *fields = NULL;
+ gchar *fields_str;
+ guint i;
+ const gint supported_fields[] = {
+ E_CONTACT_FULL_NAME,
+ E_CONTACT_EMAIL_1,
+ E_CONTACT_EMAIL_2,
+ E_CONTACT_EMAIL_3,
+ E_CONTACT_EMAIL_4,
+ E_CONTACT_ADDRESS_LABEL_HOME,
+ E_CONTACT_ADDRESS_LABEL_WORK,
+ E_CONTACT_ADDRESS_LABEL_OTHER,
+ E_CONTACT_PHONE_HOME,
+ E_CONTACT_PHONE_HOME_FAX,
+ E_CONTACT_PHONE_BUSINESS,
+ E_CONTACT_PHONE_BUSINESS_FAX,
+ E_CONTACT_PHONE_MOBILE,
+ E_CONTACT_PHONE_PAGER,
+ E_CONTACT_IM_AIM,
+ E_CONTACT_IM_JABBER,
+ E_CONTACT_IM_YAHOO,
+ E_CONTACT_IM_MSN,
+ E_CONTACT_IM_ICQ,
+ E_CONTACT_IM_SKYPE,
+ E_CONTACT_IM_GADUGADU,
+ E_CONTACT_IM_GROUPWISE,
+ E_CONTACT_ADDRESS,
+ E_CONTACT_ADDRESS_HOME,
+ E_CONTACT_ADDRESS_WORK,
+ E_CONTACT_ADDRESS_OTHER,
+ E_CONTACT_NAME,
+ E_CONTACT_GIVEN_NAME,
+ E_CONTACT_FAMILY_NAME,
+ E_CONTACT_PHONE_ASSISTANT,
+ E_CONTACT_PHONE_BUSINESS_2,
+ E_CONTACT_PHONE_CALLBACK,
+ E_CONTACT_PHONE_CAR,
+ E_CONTACT_PHONE_COMPANY,
+ E_CONTACT_PHONE_HOME_2,
+ E_CONTACT_PHONE_ISDN,
+ E_CONTACT_PHONE_OTHER,
+ E_CONTACT_PHONE_OTHER_FAX,
+ E_CONTACT_PHONE_PRIMARY,
+ E_CONTACT_PHONE_RADIO,
+ E_CONTACT_PHONE_TELEX,
+ E_CONTACT_PHONE_TTYTDD,
+ E_CONTACT_IM_AIM_HOME_1,
+ E_CONTACT_IM_AIM_HOME_2,
+ E_CONTACT_IM_AIM_HOME_3,
+ E_CONTACT_IM_AIM_WORK_1,
+ E_CONTACT_IM_AIM_WORK_2,
+ E_CONTACT_IM_AIM_WORK_3,
+ E_CONTACT_IM_GROUPWISE_HOME_1,
+ E_CONTACT_IM_GROUPWISE_HOME_2,
+ E_CONTACT_IM_GROUPWISE_HOME_3,
+ E_CONTACT_IM_GROUPWISE_WORK_1,
+ E_CONTACT_IM_GROUPWISE_WORK_2,
+ E_CONTACT_IM_GROUPWISE_WORK_3,
+ E_CONTACT_IM_JABBER_HOME_1,
+ E_CONTACT_IM_JABBER_HOME_2,
+ E_CONTACT_IM_JABBER_HOME_3,
+ E_CONTACT_IM_JABBER_WORK_1,
+ E_CONTACT_IM_JABBER_WORK_2,
+ E_CONTACT_IM_JABBER_WORK_3,
+ E_CONTACT_IM_YAHOO_HOME_1,
+ E_CONTACT_IM_YAHOO_HOME_2,
+ E_CONTACT_IM_YAHOO_HOME_3,
+ E_CONTACT_IM_YAHOO_WORK_1,
+ E_CONTACT_IM_YAHOO_WORK_2,
+ E_CONTACT_IM_YAHOO_WORK_3,
+ E_CONTACT_IM_MSN_HOME_1,
+ E_CONTACT_IM_MSN_HOME_2,
+ E_CONTACT_IM_MSN_HOME_3,
+ E_CONTACT_IM_MSN_WORK_1,
+ E_CONTACT_IM_MSN_WORK_2,
+ E_CONTACT_IM_MSN_WORK_3,
+ E_CONTACT_IM_ICQ_HOME_1,
+ E_CONTACT_IM_ICQ_HOME_2,
+ E_CONTACT_IM_ICQ_HOME_3,
+ E_CONTACT_IM_ICQ_WORK_1,
+ E_CONTACT_IM_ICQ_WORK_2,
+ E_CONTACT_IM_ICQ_WORK_3,
+ E_CONTACT_EMAIL,
+ E_CONTACT_IM_GADUGADU_HOME_1,
+ E_CONTACT_IM_GADUGADU_HOME_2,
+ E_CONTACT_IM_GADUGADU_HOME_3,
+ E_CONTACT_IM_GADUGADU_WORK_1,
+ E_CONTACT_IM_GADUGADU_WORK_2,
+ E_CONTACT_IM_GADUGADU_WORK_3,
+ E_CONTACT_TEL,
+ E_CONTACT_IM_SKYPE_HOME_1,
+ E_CONTACT_IM_SKYPE_HOME_2,
+ E_CONTACT_IM_SKYPE_HOME_3,
+ E_CONTACT_IM_SKYPE_WORK_1,
+ E_CONTACT_IM_SKYPE_WORK_2,
+ E_CONTACT_IM_SKYPE_WORK_3,
+ E_CONTACT_SIP,
+ E_CONTACT_ORG,
+ E_CONTACT_ORG_UNIT,
+ E_CONTACT_TITLE,
+ E_CONTACT_ROLE,
+ E_CONTACT_HOMEPAGE_URL,
+ E_CONTACT_BLOG_URL,
+ E_CONTACT_BIRTH_DATE,
+ E_CONTACT_ANNIVERSARY,
+ E_CONTACT_NOTE,
+ E_CONTACT_CATEGORIES,
+ E_CONTACT_CATEGORY_LIST
+ };
+
+ /* Add all the fields above to the list */
+ for (i = 0; i < G_N_ELEMENTS (supported_fields); i++) {
+ const gchar *field_name = e_contact_field_name (supported_fields[i]);
+ fields = g_slist_prepend (fields, (gpointer) field_name);
+ }
+
+ fields_str = e_data_book_string_slist_to_comma_string (fields);
+
+ e_data_book_respond_get_backend_property (book, opid, NULL, fields_str);
+
+ g_slist_free (fields);
+ g_free (fields_str);
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS)) {
+ e_data_book_respond_get_backend_property (book, opid, NULL, "plain/password");
+ } else {
+ E_BOOK_BACKEND_CLASS (e_book_backend_google_parent_class)->get_backend_property (backend, book, opid, cancellable, prop_name);
+ }
}
static void
-e_book_backend_google_cancel_operation (EBookBackend *backend, EDataBook *book, GError **error)
+google_cancel_all_operations (EBookBackend *backend)
{
GHashTableIter iter;
gpointer opid_ptr;
@@ -1579,6 +1572,9 @@ e_book_backend_google_cancel_operation (EBookBackend *backend, EDataBook *book,
__debug__ (G_STRFUNC);
+ if (!priv->cancellables)
+ return;
+
/* Cancel all active operations */
g_hash_table_iter_init (&iter, priv->cancellables);
while (g_hash_table_iter_next (&iter, &opid_ptr, (gpointer *) &cancellable)) {
@@ -1587,31 +1583,29 @@ e_book_backend_google_cancel_operation (EBookBackend *backend, EDataBook *book,
}
static void
-e_book_backend_google_set_mode (EBookBackend *backend, EDataBookMode mode)
+e_book_backend_google_set_online (EBookBackend *backend, gboolean is_online)
{
EBookBackendGooglePrivate *priv = E_BOOK_BACKEND_GOOGLE (backend)->priv;
- gboolean online = (mode == E_DATA_BOOK_MODE_REMOTE);
-
__debug__ (G_STRFUNC);
- if (mode == priv->mode)
+ if (is_online == priv->is_online)
return;
- priv->mode = mode;
+ priv->is_online = is_online;
- e_book_backend_notify_connection_status (backend, online);
+ e_book_backend_notify_online (backend, is_online);
- if (online) {
+ if (is_online && e_book_backend_is_opened (backend)) {
/* Going online, so we need to re-authenticate and re-create the service and proxy.
* This is done in e_book_backend_google_authenticate_user() when it gets the authentication data. */
- e_book_backend_notify_auth_required (backend);
+ e_book_backend_notify_auth_required (backend, TRUE, NULL);
} else {
/* Going offline, so cancel all running operations */
- e_book_backend_google_cancel_operation (backend, NULL, NULL);
+ google_cancel_all_operations (backend);
/* Mark the book as unwriteable if we're going offline, but don't do the inverse when we go online;
* e_book_backend_google_authenticate_user() will mark us as writeable again once the user's authenticated again. */
- e_book_backend_notify_writable (backend, FALSE);
+ e_book_backend_notify_readonly (backend, TRUE);
/* We can free our service and proxy */
if (priv->service)
@@ -1632,7 +1626,7 @@ e_book_backend_google_dispose (GObject *object)
__debug__ (G_STRFUNC);
/* Cancel all outstanding operations */
- e_book_backend_google_cancel_operation (E_BOOK_BACKEND (object), NULL, NULL);
+ google_cancel_all_operations (E_BOOK_BACKEND (object));
while (priv->bookviews) {
e_data_book_view_unref (priv->bookviews->data);
@@ -1664,9 +1658,11 @@ e_book_backend_google_finalize (GObject *object)
__debug__ (G_STRFUNC);
- g_hash_table_destroy (priv->groups_by_id);
- g_hash_table_destroy (priv->groups_by_name);
- g_hash_table_destroy (priv->cancellables);
+ if (priv->cancellables) {
+ g_hash_table_destroy (priv->groups_by_id);
+ g_hash_table_destroy (priv->groups_by_name);
+ g_hash_table_destroy (priv->cancellables);
+ }
G_OBJECT_CLASS (e_book_backend_google_parent_class)->finalize (object);
}
@@ -1680,23 +1676,18 @@ e_book_backend_google_class_init (EBookBackendGoogleClass *klass)
g_type_class_add_private (klass, sizeof (EBookBackendGooglePrivate));
/* Set the virtual methods. */
- backend_class->load_source = e_book_backend_google_load_source;
- backend_class->get_static_capabilities = e_book_backend_google_get_static_capabilities;
- backend_class->start_book_view = e_book_backend_google_start_book_view;
- backend_class->stop_book_view = e_book_backend_google_stop_book_view;
- backend_class->cancel_operation = e_book_backend_google_cancel_operation;
- backend_class->set_mode = e_book_backend_google_set_mode;
- backend_class->remove = e_book_backend_google_remove;
- backend_class->create_contact = e_book_backend_google_create_contact;
- backend_class->remove_contacts = e_book_backend_google_remove_contacts;
- backend_class->modify_contact = e_book_backend_google_modify_contact;
- backend_class->get_contact = e_book_backend_google_get_contact;
- backend_class->get_contact_list = e_book_backend_google_get_contact_list;
- backend_class->get_changes = e_book_backend_google_get_changes;
- backend_class->authenticate_user = e_book_backend_google_authenticate_user;
- backend_class->get_supported_fields = e_book_backend_google_get_supported_fields;
- backend_class->get_required_fields = e_book_backend_google_get_required_fields;
- backend_class->get_supported_auth_methods = e_book_backend_google_get_supported_auth_methods;
+ backend_class->open = e_book_backend_google_open;
+ backend_class->get_backend_property = e_book_backend_google_get_backend_property;
+ backend_class->start_book_view = e_book_backend_google_start_book_view;
+ backend_class->stop_book_view = e_book_backend_google_stop_book_view;
+ backend_class->set_online = e_book_backend_google_set_online;
+ backend_class->remove = e_book_backend_google_remove;
+ backend_class->create_contact = e_book_backend_google_create_contact;
+ backend_class->remove_contacts = e_book_backend_google_remove_contacts;
+ backend_class->modify_contact = e_book_backend_google_modify_contact;
+ backend_class->get_contact = e_book_backend_google_get_contact;
+ backend_class->get_contact_list = e_book_backend_google_get_contact_list;
+ backend_class->authenticate_user = e_book_backend_google_authenticate_user;
object_class->dispose = e_book_backend_google_dispose;
object_class->finalize = e_book_backend_google_finalize;
diff --git a/addressbook/backends/ldap/e-book-backend-ldap.c b/addressbook/backends/ldap/e-book-backend-ldap.c
index 1137557..fd72bb2 100644
--- a/addressbook/backends/ldap/e-book-backend-ldap.c
+++ b/addressbook/backends/ldap/e-book-backend-ldap.c
@@ -199,8 +199,8 @@ struct _EBookBackendLDAPPrivate {
LDAP *ldap;
- GList *supported_fields;
- GList *supported_auth_methods;
+ GSList *supported_fields;
+ GSList *supported_auth_methods;
EBookBackendCache *cache;
@@ -211,7 +211,7 @@ struct _EBookBackendLDAPPrivate {
gboolean evolutionPersonChecked;
gboolean marked_for_offline;
- gint mode;
+ gboolean is_online;
/* our operations */
GStaticRecMutex op_hash_mutex;
GHashTable *id_to_op;
@@ -444,46 +444,58 @@ can_browse (EBookBackend *backend)
strcmp (e_source_get_property (e_book_backend_get_source (backend), "can-browse"), "1") == 0;
}
+static gboolean
+pick_view_cb (EDataBookView *view, gpointer user_data)
+{
+ EDataBookView **pick = user_data;
+
+ g_return_val_if_fail (user_data != NULL, FALSE);
+
+ /* just always use the first book view */
+ *pick = view;
+
+ return view == NULL;
+}
+
static EDataBookView*
find_book_view (EBookBackendLDAP *bl)
{
- EList *views = e_book_backend_get_book_views (E_BOOK_BACKEND (bl));
- EIterator *iter = e_list_get_iterator (views);
- EDataBookView *rv = NULL;
-
- if (e_iterator_is_valid (iter)) {
- /* just always use the first book view */
- EDataBookView *v = (EDataBookView*) e_iterator_get (iter);
- if (v)
- rv = v;
- }
+ EDataBookView *pick = NULL;
- g_object_unref (iter);
- g_object_unref (views);
+ e_book_backend_foreach_view (E_BOOK_BACKEND (bl), pick_view_cb, &pick);
- return rv;
+ return pick;
}
+struct check_data
+{
+ EDataBookView *to_find;
+ gboolean found;
+};
+
static gboolean
-book_view_is_valid (EBookBackendLDAP *bl, EDataBookView *book_view)
+check_view_cb (EDataBookView *view, gpointer user_data)
{
- gboolean found = FALSE;
- EList *views;
- EIterator *iter;
+ struct check_data *cd = user_data;
- if (!book_view)
- return FALSE;
+ g_return_val_if_fail (user_data != NULL, FALSE);
- views = e_book_backend_get_book_views (E_BOOK_BACKEND (bl));
+ cd->found = view == cd->to_find;
- for (iter = e_list_get_iterator (views); e_iterator_is_valid (iter) && !found; e_iterator_next (iter)) {
- found = book_view == e_iterator_get (iter);
- }
+ return !cd->found;
+}
- g_object_unref (iter);
- g_object_unref (views);
+static gboolean
+book_view_is_valid (EBookBackendLDAP *bl, EDataBookView *book_view)
+{
+ struct check_data cd;
+
+ cd.to_find = book_view;
+ cd.found = FALSE;
+
+ e_book_backend_foreach_view (E_BOOK_BACKEND (bl), check_view_cb, &cd);
- return found;
+ return cd.found;
}
static void
@@ -491,7 +503,7 @@ book_view_notify_status (EBookBackendLDAP *bl, EDataBookView *view, const gchar
{
if (!book_view_is_valid (bl, view))
return;
- e_data_book_view_notify_status_message (view, status);
+ e_data_book_view_notify_progress (view, -1, status);
}
static void
@@ -502,23 +514,23 @@ add_to_supported_fields (EBookBackendLDAP *bl, gchar **attrs, GHashTable *attr_h
gchar *query_prop = g_hash_table_lookup (attr_hash, attrs[i]);
if (query_prop) {
- bl->priv->supported_fields = g_list_append (bl->priv->supported_fields, g_strdup (query_prop));
+ bl->priv->supported_fields = g_slist_append (bl->priv->supported_fields, g_strdup (query_prop));
/* handle the list attributes here */
if (!strcmp (query_prop, e_contact_field_name (E_CONTACT_EMAIL))) {
- bl->priv->supported_fields = g_list_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_1)));
- bl->priv->supported_fields = g_list_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_2)));
- bl->priv->supported_fields = g_list_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_3)));
- bl->priv->supported_fields = g_list_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_4)));
+ bl->priv->supported_fields = g_slist_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_1)));
+ bl->priv->supported_fields = g_slist_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_2)));
+ bl->priv->supported_fields = g_slist_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_3)));
+ bl->priv->supported_fields = g_slist_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_EMAIL_4)));
}
else if (!strcmp (query_prop, e_contact_field_name (E_CONTACT_PHONE_BUSINESS))) {
- bl->priv->supported_fields = g_list_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_BUSINESS_2)));
+ bl->priv->supported_fields = g_slist_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_BUSINESS_2)));
}
else if (!strcmp (query_prop, e_contact_field_name (E_CONTACT_PHONE_HOME))) {
- bl->priv->supported_fields = g_list_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_HOME_2)));
+ bl->priv->supported_fields = g_slist_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_PHONE_HOME_2)));
}
else if (!strcmp (query_prop, e_contact_field_name (E_CONTACT_CATEGORY_LIST) )) {
- bl->priv->supported_fields = g_list_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_CATEGORIES)));
+ bl->priv->supported_fields = g_slist_append (bl->priv->supported_fields, g_strdup (e_contact_field_name (E_CONTACT_CATEGORIES)));
}
}
@@ -622,7 +634,7 @@ check_schema_support (EBookBackendLDAP *bl)
of draconian acl's that keep subschema
reads from working until the user is
authed. */
- if (!e_book_backend_is_writable (E_BOOK_BACKEND (bl))) {
+ if (e_book_backend_is_readonly (E_BOOK_BACKEND (bl))) {
g_warning ("subschema read returned nothing before successful auth");
bl->priv->evolutionPersonChecked = FALSE;
}
@@ -756,20 +768,20 @@ query_ldap_root_dse (EBookBackendLDAP *bl)
if (values) {
gchar *auth_method;
if (bl->priv->supported_auth_methods) {
- g_list_foreach (bl->priv->supported_auth_methods, (GFunc) g_free, NULL);
- g_list_free (bl->priv->supported_auth_methods);
+ g_slist_foreach (bl->priv->supported_auth_methods, (GFunc) g_free, NULL);
+ g_slist_free (bl->priv->supported_auth_methods);
}
bl->priv->supported_auth_methods = NULL;
auth_method = g_strdup_printf ("ldap/simple-binddn|%s", _("Using Distinguished Name (DN)"));
- bl->priv->supported_auth_methods = g_list_append (bl->priv->supported_auth_methods, auth_method);
+ bl->priv->supported_auth_methods = g_slist_append (bl->priv->supported_auth_methods, auth_method);
auth_method = g_strdup_printf ("ldap/simple-email|%s", _("Using Email Address"));
- bl->priv->supported_auth_methods = g_list_append (bl->priv->supported_auth_methods, auth_method);
+ bl->priv->supported_auth_methods = g_slist_append (bl->priv->supported_auth_methods, auth_method);
for (i = 0; values[i]; i++) {
auth_method = g_strdup_printf ("sasl/%s|%s", values[i], values[i]);
- bl->priv->supported_auth_methods = g_list_append (bl->priv->supported_auth_methods, auth_method);
+ bl->priv->supported_auth_methods = g_slist_append (bl->priv->supported_auth_methods, auth_method);
if (enable_debug)
g_message ("supported SASL mechanism: %s", values[i]);
}
@@ -964,7 +976,6 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl)
if (ldap_error == LDAP_SUCCESS
|| ldap_error == LDAP_PARTIAL_RESULTS
|| LDAP_NAME_ERROR (ldap_error)) {
- e_book_backend_set_is_loaded (E_BOOK_BACKEND (bl), TRUE);
blpriv->connected = TRUE;
g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
@@ -984,7 +995,7 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl)
}
return EDB_ERROR (SUCCESS);
} else if (ldap_error == LDAP_UNWILLING_TO_PERFORM) {
- e_book_backend_notify_auth_required (E_BOOK_BACKEND (bl));
+ e_book_backend_notify_auth_required (E_BOOK_BACKEND (bl), TRUE, NULL);
g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
return EDB_ERROR (AUTHENTICATION_REQUIRED);
} else {
@@ -1564,6 +1575,7 @@ static void
e_book_backend_ldap_create_contact (EBookBackend *backend,
EDataBook *book,
guint32 opid,
+ GCancellable *cancellable,
const gchar *vcard)
{
LDAPCreateOp *create_op = g_new0 (LDAPCreateOp, 1);
@@ -1575,128 +1587,123 @@ e_book_backend_ldap_create_contact (EBookBackend *backend,
LDAPMod **ldap_mods;
gchar *new_uid;
- switch (bl->priv->mode) {
-
- case E_DATA_BOOK_MODE_LOCAL :
+ if (!bl->priv->is_online) {
e_data_book_respond_create (book, opid, EDB_ERROR (REPOSITORY_OFFLINE), NULL);
return;
- case E_DATA_BOOK_MODE_REMOTE :
+ }
- g_static_rec_mutex_lock (&eds_ldap_handler_lock);
- if (!bl->priv->ldap) {
- g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- e_data_book_respond_create (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
- return;
- }
+ g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+ if (!bl->priv->ldap) {
g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+ e_data_book_respond_create (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
+ return;
+ }
+ g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- book_view = find_book_view (bl);
+ book_view = find_book_view (bl);
- if (enable_debug)
- printf ("Create Contact: vcard = %s\n", vcard);
+ if (enable_debug)
+ printf ("Create Contact: vcard = %s\n", vcard);
- create_op->new_contact = e_contact_new_from_vcard (vcard);
+ create_op->new_contact = e_contact_new_from_vcard (vcard);
- new_uid = create_dn_from_contact (create_op->new_contact, bl->priv->ldap_rootdn);
- create_op->dn = create_full_dn_from_contact (new_uid, bl->priv->ldap_rootdn);
+ new_uid = create_dn_from_contact (create_op->new_contact, bl->priv->ldap_rootdn);
+ create_op->dn = create_full_dn_from_contact (new_uid, bl->priv->ldap_rootdn);
- e_contact_set (create_op->new_contact, E_CONTACT_UID, create_op->dn);
+ e_contact_set (create_op->new_contact, E_CONTACT_UID, create_op->dn);
- /* build our mods */
- mod_array = build_mods_from_contacts (bl, NULL, create_op->new_contact, NULL, new_uid);
- g_free (new_uid);
+ /* build our mods */
+ mod_array = build_mods_from_contacts (bl, NULL, create_op->new_contact, NULL, new_uid);
+ g_free (new_uid);
#if 0
- if (!mod_array) {
- /* there's an illegal field in there. report
- UnsupportedAttribute back */
- e_data_book_respond_create (book,
- EDB_ERROR (UNSUPPORTED_FIELD),
- NULL);
+ if (!mod_array) {
+ /* there's an illegal field in there. report
+ UnsupportedAttribute back */
+ e_data_book_respond_create (book,
+ EDB_ERROR (UNSUPPORTED_FIELD),
+ NULL);
- g_free (create_op->dn);
- g_object_unref (create_op->new_contact);
- g_free (create_op);
- return;
- }
+ g_free (create_op->dn);
+ g_object_unref (create_op->new_contact);
+ g_free (create_op);
+ return;
+ }
#endif
- /* remove the NULL at the end */
- g_ptr_array_remove (mod_array, NULL);
+ /* remove the NULL at the end */
+ g_ptr_array_remove (mod_array, NULL);
- /* add our objectclass(es) */
- if (e_contact_get (create_op->new_contact, E_CONTACT_IS_LIST))
- add_objectclass_mod (bl, mod_array, NULL, TRUE, FALSE);
- else
- add_objectclass_mod (bl, mod_array, NULL, FALSE, FALSE);
+ /* add our objectclass(es) */
+ if (e_contact_get (create_op->new_contact, E_CONTACT_IS_LIST))
+ add_objectclass_mod (bl, mod_array, NULL, TRUE, FALSE);
+ else
+ add_objectclass_mod (bl, mod_array, NULL, FALSE, FALSE);
- /* then put the NULL back */
- g_ptr_array_add (mod_array, NULL);
+ /* then put the NULL back */
+ g_ptr_array_add (mod_array, NULL);
#ifdef LDAP_DEBUG_ADD
- if (enable_debug) {
- gint i;
- printf ("Sending the following to the server as ADD\n");
- printf ("Adding DN: %s\n", create_op->dn);
-
- for (i = 0; g_ptr_array_index (mod_array, i); i++) {
- LDAPMod *mod = g_ptr_array_index (mod_array, i);
- if (mod->mod_op & LDAP_MOD_DELETE)
- printf ("del ");
- else if (mod->mod_op & LDAP_MOD_REPLACE)
- printf ("rep ");
- else
- printf ("add ");
- if (mod->mod_op & LDAP_MOD_BVALUES)
- printf ("ber ");
- else
- printf (" ");
+ if (enable_debug) {
+ gint i;
+ printf ("Sending the following to the server as ADD\n");
+ printf ("Adding DN: %s\n", create_op->dn);
+
+ for (i = 0; g_ptr_array_index (mod_array, i); i++) {
+ LDAPMod *mod = g_ptr_array_index (mod_array, i);
+ if (mod->mod_op & LDAP_MOD_DELETE)
+ printf ("del ");
+ else if (mod->mod_op & LDAP_MOD_REPLACE)
+ printf ("rep ");
+ else
+ printf ("add ");
+ if (mod->mod_op & LDAP_MOD_BVALUES)
+ printf ("ber ");
+ else
+ printf (" ");
- printf (" %s:\n", mod->mod_type);
+ printf (" %s:\n", mod->mod_type);
- if (mod->mod_op & LDAP_MOD_BVALUES) {
- gint j;
- for (j = 0; mod->mod_bvalues[j] && mod->mod_bvalues[j]->bv_val; j++)
- printf ("\t\t'%s'\n", mod->mod_bvalues[j]->bv_val);
- }
- else {
- gint j;
+ if (mod->mod_op & LDAP_MOD_BVALUES) {
+ gint j;
+ for (j = 0; mod->mod_bvalues[j] && mod->mod_bvalues[j]->bv_val; j++)
+ printf ("\t\t'%s'\n", mod->mod_bvalues[j]->bv_val);
+ } else {
+ gint j;
- for (j = 0; mod->mod_values[j]; j++)
- printf ("\t\t'%s'\n", mod->mod_values[j]);
- }
+ for (j = 0; mod->mod_values[j]; j++)
+ printf ("\t\t'%s'\n", mod->mod_values[j]);
}
}
+ }
#endif
- ldap_mods = (LDAPMod**) mod_array->pdata;
+ ldap_mods = (LDAPMod**) mod_array->pdata;
- do {
- book_view_notify_status (bl, book_view, _("Adding contact to LDAP server..."));
- g_static_rec_mutex_lock (&eds_ldap_handler_lock);
- err = ldap_add_ext (bl->priv->ldap, create_op->dn, ldap_mods,
- NULL, NULL, &create_contact_msgid);
- g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+ do {
+ book_view_notify_status (bl, book_view, _("Adding contact to LDAP server..."));
+ g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+ err = ldap_add_ext (bl->priv->ldap, create_op->dn, ldap_mods,
+ NULL, NULL, &create_contact_msgid);
+ g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- } while (e_book_backend_ldap_reconnect (bl, book_view, err));
+ } while (e_book_backend_ldap_reconnect (bl, book_view, err));
- /* and clean up */
- free_mods (mod_array);
+ /* and clean up */
+ free_mods (mod_array);
- if (LDAP_SUCCESS != err) {
- e_data_book_respond_create (create_op->op.book,
- opid,
- ldap_error_to_response (err),
- NULL);
- create_contact_dtor ((LDAPOp*) create_op);
- return;
- }
- else {
- g_print ("ldap_add_ext returned %d\n", err);
- ldap_op_add ((LDAPOp*) create_op, backend, book,
- book_view, opid, create_contact_msgid,
- create_contact_handler, create_contact_dtor);
- }
+ if (LDAP_SUCCESS != err) {
+ e_data_book_respond_create (create_op->op.book,
+ opid,
+ ldap_error_to_response (err),
+ NULL);
+ create_contact_dtor ((LDAPOp*) create_op);
+ return;
+ } else {
+ g_print ("ldap_add_ext returned %d\n", err);
+ ldap_op_add ((LDAPOp*) create_op, backend, book,
+ book_view, opid, create_contact_msgid,
+ create_contact_handler, create_contact_dtor);
}
}
@@ -1712,7 +1719,7 @@ remove_contact_handler (LDAPOp *op, LDAPMessage *res)
EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (op->backend);
gchar *ldap_error_msg;
gint ldap_error;
- GList *ids = NULL;
+ GSList *ids = NULL;
g_static_rec_mutex_lock (&eds_ldap_handler_lock);
if (!bl->priv->ldap) {
@@ -1748,12 +1755,12 @@ remove_contact_handler (LDAPOp *op, LDAPMessage *res)
ldap_memfree (ldap_error_msg);
- ids = g_list_append (ids, remove_op->id);
+ ids = g_slist_append (ids, remove_op->id);
e_data_book_respond_remove_contacts (remove_op->op.book,
op->opid,
ldap_error_to_response (ldap_error),
ldap_error == LDAP_SUCCESS ? ids : NULL);
- g_list_free (ids);
+ g_slist_free (ids);
ldap_op_finished (op);
}
@@ -1770,7 +1777,8 @@ static void
e_book_backend_ldap_remove_contacts (EBookBackend *backend,
EDataBook *book,
guint32 opid,
- GList *ids)
+ GCancellable *cancellable,
+ const GSList *ids)
{
LDAPRemoveOp *remove_op = g_new (LDAPRemoveOp, 1);
EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
@@ -1778,59 +1786,54 @@ e_book_backend_ldap_remove_contacts (EBookBackend *backend,
gint remove_msgid;
gint ldap_error;
- switch (bl->priv->mode) {
-
- case E_DATA_BOOK_MODE_LOCAL :
+ if (!bl->priv->is_online) {
e_data_book_respond_remove_contacts (book, opid, EDB_ERROR (REPOSITORY_OFFLINE), NULL);
g_free (remove_op);
return;
- case E_DATA_BOOK_MODE_REMOTE :
- g_static_rec_mutex_lock (&eds_ldap_handler_lock);
- if (!bl->priv->ldap) {
- g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- e_data_book_respond_remove_contacts (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
- g_free (remove_op);
- return;
- }
+ }
+
+ g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+ if (!bl->priv->ldap) {
g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+ e_data_book_respond_remove_contacts (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
+ g_free (remove_op);
+ return;
+ }
+ g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- book_view = find_book_view (bl);
+ book_view = find_book_view (bl);
- /*
- ** since we didn't pass "bulk-removes" in our static
- ** capabilities, we should only get 1 length lists here, so
- ** the id we're deleting is the first and only id in the list.
- */
- remove_op->id = g_strdup (ids->data);
+ /*
+ ** since we didn't pass "bulk-removes" in our static
+ ** capabilities, we should only get 1 length lists here, so
+ ** the id we're deleting is the first and only id in the list.
+ */
+ remove_op->id = g_strdup (ids->data);
- do {
- book_view_notify_status (bl, book_view, _("Removing contact from LDAP server..."));
+ do {
+ book_view_notify_status (bl, book_view, _("Removing contact from LDAP server..."));
- g_static_rec_mutex_lock (&eds_ldap_handler_lock);
- ldap_error = ldap_delete_ext (bl->priv->ldap,
- remove_op->id,
- NULL, NULL, &remove_msgid);
- g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- } while (e_book_backend_ldap_reconnect (bl, book_view, ldap_error));
+ g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+ ldap_error = ldap_delete_ext (bl->priv->ldap,
+ remove_op->id,
+ NULL, NULL, &remove_msgid);
+ g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+ } while (e_book_backend_ldap_reconnect (bl, book_view, ldap_error));
- if (ldap_error != LDAP_SUCCESS) {
- e_data_book_respond_remove_contacts (remove_op->op.book,
- opid,
- ldap_error_to_response (ldap_error),
- NULL);
- ldap_op_finished ((LDAPOp*) remove_op);
- remove_contact_dtor ((LDAPOp*) remove_op);
- return;
- }
- else {
- g_print ("ldap_delete_ext returned %d\n", ldap_error);
- ldap_op_add ((LDAPOp*) remove_op, backend, book,
- book_view, opid, remove_msgid,
- remove_contact_handler, remove_contact_dtor);
- }
- break;
+ if (ldap_error != LDAP_SUCCESS) {
+ e_data_book_respond_remove_contacts (remove_op->op.book,
+ opid,
+ ldap_error_to_response (ldap_error),
+ NULL);
+ ldap_op_finished ((LDAPOp*) remove_op);
+ remove_contact_dtor ((LDAPOp*) remove_op);
+ return;
+ } else {
+ g_print ("ldap_delete_ext returned %d\n", ldap_error);
+ ldap_op_add ((LDAPOp*) remove_op, backend, book,
+ book_view, opid, remove_msgid,
+ remove_contact_handler, remove_contact_dtor);
}
-
}
/*
@@ -2209,6 +2212,7 @@ static void
e_book_backend_ldap_modify_contact (EBookBackend *backend,
EDataBook *book,
guint32 opid,
+ GCancellable *cancellable,
const gchar *vcard)
{
LDAPModifyOp *modify_op = g_new0 (LDAPModifyOp, 1);
@@ -2217,54 +2221,51 @@ e_book_backend_ldap_modify_contact (EBookBackend *backend,
gint modify_contact_msgid;
EDataBookView *book_view;
- switch (bl->priv->mode) {
-
- case E_DATA_BOOK_MODE_LOCAL :
+ if (!bl->priv->is_online) {
e_data_book_respond_modify (book, opid, EDB_ERROR (REPOSITORY_OFFLINE), NULL);
return;
- case E_DATA_BOOK_MODE_REMOTE :
- g_static_rec_mutex_lock (&eds_ldap_handler_lock);
- if (!bl->priv->ldap) {
- g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- e_data_book_respond_modify (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
- g_free (modify_op);
- return;
- }
+ }
+
+ g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+ if (!bl->priv->ldap) {
g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+ e_data_book_respond_modify (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
+ g_free (modify_op);
+ return;
+ }
+ g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- book_view = find_book_view (bl);
+ book_view = find_book_view (bl);
- if (enable_debug)
- printf ("Modify Contact: vcard = %s\n", vcard);
- modify_op->contact = e_contact_new_from_vcard (vcard);
- modify_op->id = e_contact_get_const (modify_op->contact, E_CONTACT_UID);
+ if (enable_debug)
+ printf ("Modify Contact: vcard = %s\n", vcard);
+ modify_op->contact = e_contact_new_from_vcard (vcard);
+ modify_op->id = e_contact_get_const (modify_op->contact, E_CONTACT_UID);
- do {
- book_view_notify_status (bl, book_view, _("Modifying contact from LDAP server..."));
+ do {
+ book_view_notify_status (bl, book_view, _("Modifying contact from LDAP server..."));
- g_static_rec_mutex_lock (&eds_ldap_handler_lock);
- ldap_error = ldap_search_ext (bl->priv->ldap, modify_op->id,
- LDAP_SCOPE_BASE,
- "(objectclass=*)",
- NULL, 0, NULL, NULL,
- NULL, /* XXX timeout */
- 1, &modify_contact_msgid);
- g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+ g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+ ldap_error = ldap_search_ext (bl->priv->ldap, modify_op->id,
+ LDAP_SCOPE_BASE,
+ "(objectclass=*)",
+ NULL, 0, NULL, NULL,
+ NULL, /* XXX timeout */
+ 1, &modify_contact_msgid);
+ g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- } while (e_book_backend_ldap_reconnect (bl, book_view, ldap_error));
+ } while (e_book_backend_ldap_reconnect (bl, book_view, ldap_error));
- if (ldap_error == LDAP_SUCCESS) {
- ldap_op_add ((LDAPOp*) modify_op, backend, book,
- book_view, opid, modify_contact_msgid,
- modify_contact_search_handler, modify_contact_dtor);
- }
- else {
- e_data_book_respond_modify (book,
- opid,
- ldap_error_to_response (ldap_error),
- NULL);
- modify_contact_dtor ((LDAPOp*) modify_op);
- }
+ if (ldap_error == LDAP_SUCCESS) {
+ ldap_op_add ((LDAPOp*) modify_op, backend, book,
+ book_view, opid, modify_contact_msgid,
+ modify_contact_search_handler, modify_contact_dtor);
+ } else {
+ e_data_book_respond_modify (book,
+ opid,
+ ldap_error_to_response (ldap_error),
+ NULL);
+ modify_contact_dtor ((LDAPOp*) modify_op);
}
}
@@ -2381,6 +2382,7 @@ static void
e_book_backend_ldap_get_contact (EBookBackend *backend,
EDataBook *book,
guint32 opid,
+ GCancellable *cancellable,
const gchar *id)
{
LDAPGetContactOp *get_contact_op;
@@ -2391,9 +2393,7 @@ e_book_backend_ldap_get_contact (EBookBackend *backend,
GTimeVal start, end;
gulong diff;
- switch (bl->priv->mode) {
-
- case E_DATA_BOOK_MODE_LOCAL :
+ if (!bl->priv->is_online) {
if (bl->priv->marked_for_offline && bl->priv->cache) {
EContact *contact = e_book_backend_cache_get_contact (bl->priv->cache, id);
gchar *vcard_str;
@@ -2416,65 +2416,62 @@ e_book_backend_ldap_get_contact (EBookBackend *backend,
e_data_book_respond_get_contact(book, opid, EDB_ERROR (REPOSITORY_OFFLINE), "");
return;
+ }
- case E_DATA_BOOK_MODE_REMOTE :
-
- if (enable_debug) {
- printf("e_book_backend_ldap_get_contact ... \n");
- g_get_current_time (&start);
- }
+ if (enable_debug) {
+ printf("e_book_backend_ldap_get_contact ... \n");
+ g_get_current_time (&start);
+ }
- g_static_rec_mutex_lock (&eds_ldap_handler_lock);
- if (!bl->priv->ldap) {
- g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- e_data_book_respond_get_contact (book, opid, EDB_ERROR_NOT_CONNECTED (), "");
- if (enable_debug)
- printf("e_book_backend_ldap_get_contact ... ldap handler is NULL\n");
- return;
- }
+ g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+ if (!bl->priv->ldap) {
g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+ e_data_book_respond_get_contact (book, opid, EDB_ERROR_NOT_CONNECTED (), "");
+ if (enable_debug)
+ printf("e_book_backend_ldap_get_contact ... ldap handler is NULL\n");
+ return;
+ }
+ g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- get_contact_op = g_new0 (LDAPGetContactOp, 1);
- book_view = find_book_view (bl);
+ get_contact_op = g_new0 (LDAPGetContactOp, 1);
+ book_view = find_book_view (bl);
- do {
- g_static_rec_mutex_lock (&eds_ldap_handler_lock);
- ldap_error = ldap_search_ext (bl->priv->ldap, id,
- LDAP_SCOPE_BASE,
- "(objectclass=*)",
- NULL, 0, NULL, NULL,
- NULL, /* XXX timeout */
- 1, &get_contact_msgid);
- g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- } while (e_book_backend_ldap_reconnect (bl, book_view, ldap_error));
+ do {
+ g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+ ldap_error = ldap_search_ext (bl->priv->ldap, id,
+ LDAP_SCOPE_BASE,
+ "(objectclass=*)",
+ NULL, 0, NULL, NULL,
+ NULL, /* XXX timeout */
+ 1, &get_contact_msgid);
+ g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+ } while (e_book_backend_ldap_reconnect (bl, book_view, ldap_error));
- if (ldap_error == LDAP_SUCCESS) {
- ldap_op_add ((LDAPOp*) get_contact_op, backend, book,
- book_view, opid, get_contact_msgid,
- get_contact_handler, get_contact_dtor);
+ if (ldap_error == LDAP_SUCCESS) {
+ ldap_op_add ((LDAPOp*) get_contact_op, backend, book,
+ book_view, opid, get_contact_msgid,
+ get_contact_handler, get_contact_dtor);
- if (enable_debug) {
- printf("e_book_backend_ldap_get_contact invoked get_contact_handler\n");
- g_get_current_time (&end);
- diff = end.tv_sec * 1000 + end.tv_usec/1000;
- diff -= start.tv_sec * 1000 + start.tv_usec/1000;
- printf("and took %ld.%03ld seconds\n",
- diff/1000, diff%1000);
- }
- }
- else {
- e_data_book_respond_get_contact (book,
- opid,
- ldap_error_to_response (ldap_error),
- "");
- get_contact_dtor ((LDAPOp*) get_contact_op);
+ if (enable_debug) {
+ printf("e_book_backend_ldap_get_contact invoked get_contact_handler\n");
+ g_get_current_time (&end);
+ diff = end.tv_sec * 1000 + end.tv_usec/1000;
+ diff -= start.tv_sec * 1000 + start.tv_usec/1000;
+ printf("and took %ld.%03ld seconds\n",
+ diff/1000, diff%1000);
}
+ } else {
+ e_data_book_respond_get_contact (book,
+ opid,
+ ldap_error_to_response (ldap_error),
+ "");
+ get_contact_dtor ((LDAPOp*) get_contact_op);
}
}
typedef struct {
LDAPOp op;
- GList *contacts;
+ GSList *contacts;
} LDAPGetContactListOp;
static void
@@ -2520,8 +2517,7 @@ contact_list_handler (LDAPOp *op, LDAPMessage *res)
if (enable_debug)
printf ("vcard = %s\n", vcard);
- contact_list_op->contacts = g_list_append (contact_list_op->contacts,
- vcard);
+ contact_list_op->contacts = g_slist_append (contact_list_op->contacts, vcard);
g_object_unref (contact);
@@ -2593,6 +2589,9 @@ contact_list_dtor (LDAPOp *op)
{
LDAPGetContactListOp *contact_list_op = (LDAPGetContactListOp*) op;
+ g_slist_foreach (contact_list_op->contacts, (GFunc) g_free, NULL);
+ g_slist_free (contact_list_op->contacts);
+
g_free (contact_list_op);
}
@@ -2600,6 +2599,7 @@ static void
e_book_backend_ldap_get_contact_list (EBookBackend *backend,
EDataBook *book,
guint32 opid,
+ GCancellable *cancellable,
const gchar *query)
{
LDAPGetContactListOp *contact_list_op;
@@ -2616,85 +2616,83 @@ e_book_backend_ldap_get_contact_list (EBookBackend *backend,
g_get_current_time (&start);
}
- switch (bl->priv->mode) {
-
- case E_DATA_BOOK_MODE_LOCAL :
+ if (!bl->priv->is_online) {
if (bl->priv->marked_for_offline && bl->priv->cache) {
GList *contacts;
- GList *vcard_strings = NULL;
+ GSList *vcard_strings = NULL;
GList *l;
contacts = e_book_backend_cache_get_contacts (bl->priv->cache, query);
for (l = contacts; l; l = g_list_next (l)) {
EContact *contact = l->data;
- vcard_strings = g_list_prepend (vcard_strings, e_vcard_to_string (E_VCARD (contact),
- EVC_FORMAT_VCARD_30));
+ vcard_strings = g_slist_prepend (vcard_strings, e_vcard_to_string (E_VCARD (contact),
+ EVC_FORMAT_VCARD_30));
g_object_unref (contact);
}
g_list_free (contacts);
e_data_book_respond_get_contact_list (book, opid, EDB_ERROR (SUCCESS), vcard_strings);
+ g_slist_foreach (vcard_strings, (GFunc) g_free, NULL);
+ g_slist_free (vcard_strings);
return;
}
e_data_book_respond_get_contact_list (book, opid, EDB_ERROR (REPOSITORY_OFFLINE), NULL);
return;
+ }
- case E_DATA_BOOK_MODE_REMOTE:
- g_static_rec_mutex_lock (&eds_ldap_handler_lock);
- if (!bl->priv->ldap) {
- g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- e_data_book_respond_get_contact_list (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
- if (enable_debug)
- printf ("e_book_backend_ldap_get_contact_list... ldap handler is NULL\n");
- return;
- }
+ g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+ if (!bl->priv->ldap) {
g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+ e_data_book_respond_get_contact_list (book, opid, EDB_ERROR_NOT_CONNECTED (), NULL);
+ if (enable_debug)
+ printf ("e_book_backend_ldap_get_contact_list... ldap handler is NULL\n");
+ return;
+ }
+ g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- contact_list_op = g_new0 (LDAPGetContactListOp, 1);
- book_view = find_book_view (bl);
+ contact_list_op = g_new0 (LDAPGetContactListOp, 1);
+ book_view = find_book_view (bl);
- ldap_query = e_book_backend_ldap_build_query (bl, query);
+ ldap_query = e_book_backend_ldap_build_query (bl, query);
- if (enable_debug)
- printf ("getting contact list with filter: %s\n", ldap_query);
+ if (enable_debug)
+ printf ("getting contact list with filter: %s\n", ldap_query);
- do {
- g_static_rec_mutex_lock (&eds_ldap_handler_lock);
- ldap_error = ldap_search_ext (bl->priv->ldap,
- bl->priv->ldap_rootdn,
- bl->priv->ldap_scope,
- ldap_query,
- NULL, 0, NULL, NULL,
- NULL, /* XXX timeout */
- LDAP_NO_LIMIT, &contact_list_msgid);
- g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- } while (e_book_backend_ldap_reconnect (bl, book_view, ldap_error));
+ do {
+ g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+ ldap_error = ldap_search_ext (bl->priv->ldap,
+ bl->priv->ldap_rootdn,
+ bl->priv->ldap_scope,
+ ldap_query,
+ NULL, 0, NULL, NULL,
+ NULL, /* XXX timeout */
+ LDAP_NO_LIMIT, &contact_list_msgid);
+ g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+ } while (e_book_backend_ldap_reconnect (bl, book_view, ldap_error));
- g_free (ldap_query);
+ g_free (ldap_query);
- if (ldap_error == LDAP_SUCCESS) {
- ldap_op_add ((LDAPOp*) contact_list_op, backend, book,
- book_view, opid, contact_list_msgid,
- contact_list_handler, contact_list_dtor);
- if (enable_debug) {
- g_get_current_time (&end);
+ if (ldap_error == LDAP_SUCCESS) {
+ ldap_op_add ((LDAPOp*) contact_list_op, backend, book,
+ book_view, opid, contact_list_msgid,
+ contact_list_handler, contact_list_dtor);
+ if (enable_debug) {
+ g_get_current_time (&end);
- diff = end.tv_sec * 1000 + end.tv_usec/1000;
- diff -= start.tv_sec * 1000 + start.tv_usec/1000;
+ diff = end.tv_sec * 1000 + end.tv_usec/1000;
+ diff -= start.tv_sec * 1000 + start.tv_usec/1000;
- printf ("e_book_backend_ldap_get_contact_list invoked contact_list_handler ");
- printf ("and took %ld.%03ld seconds\n", diff/1000, diff%1000);
- }
- }
- else {
- e_data_book_respond_get_contact_list (book,
- opid,
- ldap_error_to_response (ldap_error),
- NULL);
- contact_list_dtor ((LDAPOp*) contact_list_op);
+ printf ("e_book_backend_ldap_get_contact_list invoked contact_list_handler ");
+ printf ("and took %ld.%03ld seconds\n", diff/1000, diff%1000);
}
+ } else {
+ e_data_book_respond_get_contact_list (book,
+ opid,
+ ldap_error_to_response (ldap_error),
+ NULL);
+ contact_list_dtor ((LDAPOp*) contact_list_op);
}
}
@@ -4172,8 +4170,6 @@ build_contact_from_entry (EBookBackendLDAP *bl,
/* get the e-mail id for each member and add them to the list */
book_view = find_book_view (bl);
- if (book_view)
- view_limit = e_data_book_view_get_max_results (book_view);
if (view_limit == -1 || view_limit > bl->priv->ldap_limit)
view_limit = bl->priv->ldap_limit;
@@ -4457,8 +4453,7 @@ e_book_backend_ldap_search (EBookBackendLDAP *bl,
g_get_current_time (&start);
}
- switch (bl->priv->mode) {
- case E_DATA_BOOK_MODE_LOCAL :
+ if (!bl->priv->is_online) {
if (!(bl->priv->marked_for_offline && bl->priv->cache)) {
GError *edb_err = EDB_ERROR (REPOSITORY_OFFLINE);
e_data_book_view_notify_complete (view, edb_err);
@@ -4479,86 +4474,82 @@ e_book_backend_ldap_search (EBookBackendLDAP *bl,
e_data_book_view_notify_complete (view, NULL /* Success */);
return;
+ }
- case E_DATA_BOOK_MODE_REMOTE :
- ldap_query = e_book_backend_ldap_build_query (bl, e_data_book_view_get_card_query (view));
+ ldap_query = e_book_backend_ldap_build_query (bl, e_data_book_view_get_card_query (view));
- /* search for nonempty full names */
- if (!ldap_query && can_browse ((EBookBackend *) bl))
- ldap_query = g_strdup ("(cn=*)");
+ /* search for nonempty full names */
+ if (!ldap_query && can_browse ((EBookBackend *) bl))
+ ldap_query = g_strdup ("(cn=*)");
- g_static_rec_mutex_lock (&eds_ldap_handler_lock);
- if (ldap_query != NULL && bl->priv->ldap) {
- gint ldap_err;
- gint search_msgid;
- gint view_limit;
+ g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+ if (ldap_query != NULL && bl->priv->ldap) {
+ gint ldap_err;
+ gint search_msgid;
+ gint view_limit;
- g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+ g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- view_limit = e_data_book_view_get_max_results (view);
- if (view_limit == -1 || view_limit > bl->priv->ldap_limit)
- view_limit = bl->priv->ldap_limit;
+ view_limit = -1;
+ if (view_limit == -1 || view_limit > bl->priv->ldap_limit)
+ view_limit = bl->priv->ldap_limit;
- if (enable_debug)
- printf ("searching server using filter: %s (expecting max %d results)\n", ldap_query, view_limit);
+ if (enable_debug)
+ printf ("searching server using filter: %s (expecting max %d results)\n", ldap_query, view_limit);
- do {
- book_view_notify_status (bl, view, _("Searching..."));
+ do {
+ book_view_notify_status (bl, view, _("Searching..."));
- g_static_rec_mutex_lock (&eds_ldap_handler_lock);
- ldap_err = ldap_search_ext (bl->priv->ldap, bl->priv->ldap_rootdn,
- bl->priv->ldap_scope,
- ldap_query,
- NULL, 0,
- NULL, /* XXX */
- NULL, /* XXX */
- NULL, /* XXX timeout */
- view_limit, &search_msgid);
- g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- } while (e_book_backend_ldap_reconnect (bl, view, ldap_err));
+ g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+ ldap_err = ldap_search_ext (bl->priv->ldap, bl->priv->ldap_rootdn,
+ bl->priv->ldap_scope,
+ ldap_query,
+ NULL, 0,
+ NULL, /* XXX */
+ NULL, /* XXX */
+ NULL, /* XXX timeout */
+ view_limit, &search_msgid);
+ g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+ } while (e_book_backend_ldap_reconnect (bl, view, ldap_err));
- g_free (ldap_query);
+ g_free (ldap_query);
- if (ldap_err != LDAP_SUCCESS) {
- book_view_notify_status (bl, view, ldap_err2string (ldap_err));
- return;
- }
- else if (search_msgid == -1) {
- book_view_notify_status (bl, view,
- _("Error performing search"));
- return;
- }
- else {
- LDAPSearchOp *op = g_new0 (LDAPSearchOp, 1);
+ if (ldap_err != LDAP_SUCCESS) {
+ book_view_notify_status (bl, view, ldap_err2string (ldap_err));
+ return;
+ } else if (search_msgid == -1) {
+ book_view_notify_status (bl, view,
+ _("Error performing search"));
+ return;
+ } else {
+ LDAPSearchOp *op = g_new0 (LDAPSearchOp, 1);
- d(printf ("adding search_op (%p, %d)\n", view, search_msgid));
+ d(printf ("adding search_op (%p, %d)\n", view, search_msgid));
- op->view = view;
- op->aborted = FALSE;
- e_data_book_view_ref (view);
+ op->view = view;
+ op->aborted = FALSE;
+ e_data_book_view_ref (view);
- ldap_op_add ((LDAPOp*) op, E_BOOK_BACKEND (bl), book, view,
- 0, search_msgid,
- ldap_search_handler, ldap_search_dtor);
+ ldap_op_add ((LDAPOp*) op, E_BOOK_BACKEND (bl), book, view,
+ 0, search_msgid,
+ ldap_search_handler, ldap_search_dtor);
- if (enable_debug) {
- printf ("e_book_backend_ldap_search invoked ldap_search_handler ");
- g_get_current_time (&end);
- diff = end.tv_sec * 1000 + end.tv_usec/1000;
- diff -= start.tv_sec * 1000 + start.tv_usec/1000;
- printf("and took %ld.%03ld seconds\n", diff/1000,diff%1000);
- }
-
- g_object_set_data (G_OBJECT (view), "EBookBackendLDAP.BookView::search_op", op);
+ if (enable_debug) {
+ printf ("e_book_backend_ldap_search invoked ldap_search_handler ");
+ g_get_current_time (&end);
+ diff = end.tv_sec * 1000 + end.tv_usec/1000;
+ diff -= start.tv_sec * 1000 + start.tv_usec/1000;
+ printf("and took %ld.%03ld seconds\n", diff/1000,diff%1000);
}
- return;
- }
- else {
- g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
- /* Ignore NULL query */
- e_data_book_view_notify_complete (view, NULL /* Success */);
- return;
+
+ g_object_set_data (G_OBJECT (view), "EBookBackendLDAP.BookView::search_op", op);
}
+ return;
+ } else {
+ g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+ /* Ignore NULL query */
+ e_data_book_view_notify_complete (view, NULL /* Success */);
+ return;
}
}
@@ -4570,11 +4561,6 @@ e_book_backend_ldap_start_book_view (EBookBackend *backend,
d(printf ("start_book_view (%p)\n", view));
- /* we start at 1 so the user sees stuff as it appears and we
- aren't left waiting for more cards to show up, if the
- connection is slow. */
- e_data_book_view_set_thresholds (view, 1, 3000);
-
e_book_backend_ldap_search (bl, NULL /* XXX ugh */, view);
}
@@ -4594,15 +4580,6 @@ e_book_backend_ldap_stop_book_view (EBookBackend *backend,
}
}
-static void
-e_book_backend_ldap_get_changes (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *change_id)
-{
- /* FIXME: implement */
-}
-
#define LDAP_SIMPLE_PREFIX "ldap/simple-"
#define SASL_PREFIX "sasl/"
@@ -4643,21 +4620,21 @@ generate_cache_handler (LDAPOp *op, LDAPMessage *res)
while (e != NULL) {
EContact *contact = build_contact_from_entry (bl, e, NULL, NULL);
- contact_list_op->contacts = g_list_prepend (contact_list_op->contacts, contact);
+ contact_list_op->contacts = g_slist_prepend (contact_list_op->contacts, contact);
g_static_rec_mutex_lock (&eds_ldap_handler_lock);
e = ldap_next_entry (bl->priv->ldap, e);
g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
}
} else {
- GList *l;
+ GSList *l;
gint contact_num = 0;
gchar *status_msg;
e_file_cache_clean (E_FILE_CACHE (bl->priv->cache));
e_file_cache_freeze_changes (E_FILE_CACHE (bl->priv->cache));
- for (l = contact_list_op->contacts; l; l = g_list_next (l)) {
+ for (l = contact_list_op->contacts; l; l = g_slist_next (l)) {
EContact *contact = l->data;
contact_num++;
@@ -4688,13 +4665,13 @@ static void
generate_cache_dtor (LDAPOp *op)
{
LDAPGetContactListOp *contact_list_op = (LDAPGetContactListOp *) op;
- GList *l;
+ GSList *l;
- for (l = contact_list_op->contacts; l; l = g_list_next (l)) {
+ for (l = contact_list_op->contacts; l; l = g_slist_next (l)) {
g_object_unref (l->data);
}
- g_list_free (contact_list_op->contacts);
+ g_slist_free (contact_list_op->contacts);
g_free (contact_list_op);
}
@@ -4755,33 +4732,30 @@ generate_cache (EBookBackendLDAP *book_backend_ldap)
static void
e_book_backend_ldap_authenticate_user (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *user,
- const gchar *passwd,
- const gchar *auth_method)
+ GCancellable *cancellable,
+ ECredentials *credentials)
{
EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
gint ldap_error;
gchar *dn = NULL;
+ const gchar *auth_method = e_credentials_peek (credentials, E_CREDENTIALS_KEY_AUTH_METHOD);
+ const gchar *user = e_credentials_peek (credentials, E_CREDENTIALS_KEY_USERNAME);
if (enable_debug)
printf ("e_book_backend_ldap_authenticate_user ... \n");
g_static_rec_mutex_lock (&eds_ldap_handler_lock);
- if (bl->priv->mode == E_DATA_BOOK_MODE_LOCAL) {
- e_book_backend_notify_writable (backend, FALSE);
- e_book_backend_notify_connection_status (backend, FALSE);
- e_data_book_respond_authenticate_user (book,
- opid,
- EDB_ERROR (SUCCESS));
+ if (!bl->priv->is_online) {
+ e_book_backend_notify_readonly (backend, TRUE);
+ e_book_backend_notify_online (backend, FALSE);
+ e_book_backend_notify_opened (backend, EDB_ERROR (SUCCESS));
g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
return;
}
if (bl->priv->connected) {
/* other client connected meanwhile, report success and return */
- e_data_book_respond_authenticate_user (book, opid, EDB_ERROR (SUCCESS));
+ e_book_backend_notify_opened (backend, EDB_ERROR (SUCCESS));
g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
return;
}
@@ -4811,9 +4785,7 @@ e_book_backend_ldap_authenticate_user (EBookBackend *backend,
if (!e) {
g_warning ("Failed to get the DN for %s", user);
ldap_msgfree (res);
- e_data_book_respond_authenticate_user (book,
- opid,
- EDB_ERROR (AUTHENTICATION_FAILED));
+ e_book_backend_notify_opened (backend, EDB_ERROR (AUTHENTICATION_FAILED));
return;
}
@@ -4825,11 +4797,8 @@ e_book_backend_ldap_authenticate_user (EBookBackend *backend,
ldap_memfree (entry_dn);
ldap_msgfree (res);
- }
- else {
- e_data_book_respond_authenticate_user (book,
- opid,
- EDB_ERROR (PERMISSION_DENIED));
+ } else {
+ e_book_backend_notify_opened (backend, EDB_ERROR (PERMISSION_DENIED));
return;
}
}
@@ -4838,10 +4807,10 @@ e_book_backend_ldap_authenticate_user (EBookBackend *backend,
}
g_free (bl->priv->auth_dn);
- g_free (bl->priv->auth_passwd);
+ e_credentials_util_safe_free_string (bl->priv->auth_passwd);
bl->priv->auth_dn = dn;
- bl->priv->auth_passwd = g_strdup (passwd);
+ bl->priv->auth_passwd = e_credentials_get (credentials, E_CREDENTIALS_KEY_PASSWORD);
/* now authenticate against the DN we were either supplied or queried for */
if (enable_debug)
@@ -4854,7 +4823,7 @@ e_book_backend_ldap_authenticate_user (EBookBackend *backend,
error = e_book_backend_ldap_connect (bl);
if (error) {
- e_data_book_respond_authenticate_user (book, opid, error);
+ e_book_backend_notify_opened (backend, error);
return;
}
}
@@ -4876,9 +4845,7 @@ e_book_backend_ldap_authenticate_user (EBookBackend *backend,
}
- e_data_book_respond_authenticate_user (book,
- opid,
- ldap_error_to_response (ldap_error));
+ e_book_backend_notify_opened (backend, ldap_error_to_response (ldap_error));
}
#ifdef ENABLE_SASL_BINDS
else if (!g_ascii_strncasecmp (auth_method, SASL_PREFIX, strlen (SASL_PREFIX))) {
@@ -4891,39 +4858,32 @@ e_book_backend_ldap_authenticate_user (EBookBackend *backend,
error = e_book_backend_ldap_connect (bl);
if (error) {
- e_data_book_respond_authenticate_user (book, opid, error);
+ e_book_backend_notify_opened (backend, error);
return;
}
}
ldap_error = ldap_sasl_bind_s (bl->priv->ldap,
NULL,
auth_method + strlen (SASL_PREFIX),
- passwd,
+ e_credentials_peek (credentials, E_CREDENTIALS_KEY_PASSWORD),
NULL,
NULL,
NULL);
g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
if (ldap_error == LDAP_NOT_SUPPORTED)
- e_data_book_respond_authenticate_user (book,
- opid,
- EDB_ERROR (UNSUPPORTED_AUTHENTICATION_METHOD));
+ e_book_backend_notify_opened (backend, EDB_ERROR (UNSUPPORTED_AUTHENTICATION_METHOD));
else
- e_data_book_respond_authenticate_user (book,
- opid,
- ldap_error_to_response (ldap_error));
+ e_book_backend_notify_opened (backend, ldap_error_to_response (ldap_error));
}
#endif
else {
- e_data_book_respond_authenticate_user (book,
- opid,
- EDB_ERROR (UNSUPPORTED_AUTHENTICATION_METHOD));
+ e_book_backend_notify_opened (backend, EDB_ERROR (UNSUPPORTED_AUTHENTICATION_METHOD));
return;
}
if (ldap_error == LDAP_SUCCESS) {
-
- e_book_backend_set_is_writable (backend, TRUE);
+ e_book_backend_notify_readonly (backend, FALSE);
/* force a requery on the root dse since some ldap
servers are set up such that they don't report
@@ -4940,63 +4900,12 @@ e_book_backend_ldap_authenticate_user (EBookBackend *backend,
g_warning ("Failed to perform root dse query after authenticating, (ldap_error 0x%02x)", ldap_error);
}
- e_data_book_report_writable (book, TRUE);
-
if (bl->priv->marked_for_offline && bl->priv->cache)
generate_cache (bl);
}
}
static void
-e_book_backend_ldap_get_required_fields (EBookBackend *backend,
- EDataBook *book,
- guint32 opid)
-
-{
- GList *fields = NULL;
-
- /*FIMEME we should look at mandatory attributs in the schema
- and return all those fields here */
- fields = g_list_append (fields, (gchar *) e_contact_field_name (E_CONTACT_FILE_AS));
- fields = g_list_append (fields, (gchar *) e_contact_field_name (E_CONTACT_FULL_NAME));
- fields = g_list_append (fields, (gchar *) e_contact_field_name (E_CONTACT_FAMILY_NAME));
-
- e_data_book_respond_get_required_fields (book,
- opid,
- EDB_ERROR (SUCCESS),
- fields);
- g_list_free (fields);
-}
-
-static void
-e_book_backend_ldap_get_supported_fields (EBookBackend *backend,
- EDataBook *book,
- guint32 opid)
-
-{
- EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
-
- e_data_book_respond_get_supported_fields (book,
- opid,
- EDB_ERROR (SUCCESS),
- bl->priv->supported_fields);
-}
-
-static void
-e_book_backend_ldap_get_supported_auth_methods (EBookBackend *backend,
- EDataBook *book,
- guint32 opid)
-
-{
- EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
-
- e_data_book_respond_get_supported_auth_methods (book,
- opid,
- EDB_ERROR (SUCCESS),
- bl->priv->supported_auth_methods);
-}
-
-static void
ldap_cancel_op (gpointer key, gpointer value, gpointer data)
{
EBookBackendLDAP *bl = data;
@@ -5010,7 +4919,7 @@ ldap_cancel_op (gpointer key, gpointer value, gpointer data)
}
static void
-e_book_backend_ldap_cancel_operation (EBookBackend *backend, EDataBook *book, GError **perror)
+ldap_cancel_all_operations (EBookBackend *backend)
{
EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
@@ -5020,12 +4929,14 @@ e_book_backend_ldap_cancel_operation (EBookBackend *backend, EDataBook *book, GE
}
static void
-e_book_backend_ldap_load_source (EBookBackend *backend,
- ESource *source,
- gboolean only_if_exists,
- GError **perror)
+e_book_backend_ldap_open (EBookBackend *backend,
+ EDataBook *book,
+ guint opid,
+ GCancellable *cancellable,
+ gboolean only_if_exists)
{
EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
+ ESource *source = e_book_backend_get_source (backend);
LDAPURLDesc *lud;
gint ldap_error;
gint limit = 100;
@@ -5041,7 +4952,7 @@ e_book_backend_ldap_load_source (EBookBackend *backend,
g_assert (bl->priv->connected == FALSE);
if (enable_debug)
- printf ("e_book_backend_ldap_load_source ... \n");
+ printf ("%s ... \n", G_STRFUNC);
uri = e_source_get_uri (source);
cache_dir = e_book_backend_get_cache_dir (backend);
@@ -5088,9 +4999,9 @@ e_book_backend_ldap_load_source (EBookBackend *backend,
ldap_free_urldesc (lud);
} else {
if (enable_debug)
- printf ("e_book_backend_ldap_load_source ... failed to parse the ldap URI %s\n", uri);
+ printf ("%s ... failed to parse the ldap URI %s\n", G_STRFUNC, uri);
g_free (uri);
- g_propagate_error (perror, EDB_ERROR_EX (OTHER_ERROR, "Failed to parse LDAP URI"));
+ e_book_backend_respond_opened (backend, book, opid, EDB_ERROR_EX (OTHER_ERROR, "Failed to parse LDAP URI"));
return;
}
@@ -5105,31 +5016,28 @@ e_book_backend_ldap_load_source (EBookBackend *backend,
g_free (uri);
- if (bl->priv->mode == E_DATA_BOOK_MODE_LOCAL) {
+ if (!bl->priv->is_online) {
/* Offline */
- e_book_backend_set_is_loaded (backend, TRUE);
- e_book_backend_set_is_writable (backend, FALSE);
- e_book_backend_notify_writable (backend, FALSE);
- e_book_backend_notify_connection_status (backend, FALSE);
+ e_book_backend_notify_readonly (backend, TRUE);
+ e_book_backend_notify_online (backend, FALSE);
if (!bl->priv->marked_for_offline) {
- g_propagate_error (perror, EDB_ERROR (OFFLINE_UNAVAILABLE));
+ e_book_backend_respond_opened (backend, book, opid, EDB_ERROR (OFFLINE_UNAVAILABLE));
return;
}
#if 0
if (!e_book_backend_cache_is_populated (bl->priv->cache)) {
- g_propagate_error (perror, EDB_ERROR (OFFLINE_UNAVAILABLE));
+ e_book_backend_respond_opened (backend, book, opid, EDB_ERROR (OFFLINE_UNAVAILABLE));
return;
}
#endif
-
+ e_book_backend_respond_opened (backend, book, opid, NULL /* Success */);
return;
} else {
- e_book_backend_set_is_writable (backend, TRUE);
- e_book_backend_notify_writable (backend, TRUE);
- e_book_backend_notify_connection_status (backend, TRUE);
+ e_book_backend_notify_readonly (backend, FALSE);
+ e_book_backend_notify_online (backend, TRUE);
}
str = e_source_get_property (source, "auth");
@@ -5138,11 +5046,13 @@ e_book_backend_ldap_load_source (EBookBackend *backend,
/* Requires authentication, do not try to bind without it,
but report success instead, as we are loaded. */
if (enable_debug)
- printf ("e_book_backend_ldap_load_source ... skipping anonymous bind, because auth required\n");
+ printf ("%s ... skipping anonymous bind, because auth required\n", G_STRFUNC);
- if (!e_book_backend_is_loaded (backend))
- e_book_backend_notify_auth_required (backend);
- e_book_backend_set_is_loaded (backend, TRUE);
+ if (!e_book_backend_is_opened (backend))
+ e_book_backend_notify_auth_required (backend, TRUE, NULL);
+ else
+ e_book_backend_notify_opened (backend, NULL);
+ e_book_backend_respond_opened (backend, book, opid, NULL /* Success */);
return;
}
@@ -5150,22 +5060,25 @@ e_book_backend_ldap_load_source (EBookBackend *backend,
err = e_book_backend_ldap_connect (bl);
if (err) {
if (enable_debug)
- printf ("e_book_backend_ldap_load_source ... failed to connect to server \n");
- g_propagate_error (perror, err);
+ printf ("%s ... failed to connect to server \n", G_STRFUNC);
+ e_book_backend_respond_opened (backend, book, opid, err);
return;
}
- if (auth_required && !e_book_backend_is_loaded (backend)) {
- e_book_backend_notify_auth_required (E_BOOK_BACKEND (bl));
+ if (auth_required && !e_book_backend_is_opened (backend)) {
+ e_book_backend_notify_auth_required (E_BOOK_BACKEND (bl), TRUE, NULL);
+ e_data_book_respond_open (book, opid, NULL /* Success */);
return;
}
if (bl->priv->marked_for_offline)
generate_cache (bl);
+
+ e_book_backend_respond_opened (backend, book, opid, NULL /* Success */);
}
static void
-e_book_backend_ldap_remove (EBookBackend *backend, EDataBook *book, guint32 opid)
+e_book_backend_ldap_remove (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
{
/* if we ever add caching, we'll remove it here, but for now,
just report back Success */
@@ -5173,78 +5086,120 @@ e_book_backend_ldap_remove (EBookBackend *backend, EDataBook *book, guint32 opid
e_data_book_respond_remove (book, opid, EDB_ERROR (SUCCESS));
}
-static gchar *
-e_book_backend_ldap_get_static_capabilities (EBookBackend *backend)
+static void
+e_book_backend_ldap_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
{
- if (can_browse (backend) || E_BOOK_BACKEND_LDAP (backend)->priv->marked_for_offline)
- return g_strdup ("net,anon-access,contact-lists,do-initial-query");
- else
- return g_strdup("net,anon-access,contact-lists");
+ g_return_if_fail (prop_name != NULL);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ if (can_browse (backend) || E_BOOK_BACKEND_LDAP (backend)->priv->marked_for_offline)
+ e_data_book_respond_get_backend_property (book, opid, NULL, "net,anon-access,contact-lists,do-initial-query");
+ else
+ e_data_book_respond_get_backend_property (book, opid, NULL, "net,anon-access,contact-lists");
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+ gchar *fields_str;
+ GSList *fields = NULL;
+
+ /*FIMEME we should look at mandatory attributs in the schema
+ and return all those fields here */
+ fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_FILE_AS));
+ fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_FULL_NAME));
+ fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_FAMILY_NAME));
+
+ fields_str = e_data_book_string_slist_to_comma_string (fields);
+
+ e_data_book_respond_get_backend_property (book, opid, NULL, fields_str);
+
+ g_slist_free (fields);
+ g_free (fields_str);
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+ EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
+ gchar *str;
+
+ str = e_data_book_string_slist_to_comma_string (bl->priv->supported_fields);
+
+ e_data_book_respond_get_backend_property (book, opid, NULL, str);
+
+ g_free (str);
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS)) {
+ EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
+ gchar *str;
+
+ str = e_data_book_string_slist_to_comma_string (bl->priv->supported_auth_methods);
+
+ e_data_book_respond_get_backend_property (book, opid, NULL, str);
+
+ g_free (str);
+ } else {
+ E_BOOK_BACKEND_CLASS (e_book_backend_ldap_parent_class)->get_backend_property (backend, book, opid, cancellable, prop_name);
+ }
}
#if 0
+
+struct call_data {
+ EBookBackend *backend;
+ static void (* func) (EBookBackend *backend, EDataBookView *view);
+};
+
+static gboolean
+call_cb (EDataBookView *view, gpointer user_data)
+{
+ struct call_data *cd = user_data;
+
+ g_return_val_if_fail (user_data != NULL, FALSE);
+ g_return_val_if_fail (cd->func != NULL, FALSE);
+ g_return_val_if_fail (cd->backend != NULL, FALSE);
+
+ (* cd->func) (cd->backend, view);
+
+ return TRUE;
+}
+
static void
stop_views (EBookBackend *backend)
{
- EList *book_views;
- EIterator *iter;
+ struct call_data cd;
- book_views = e_book_backend_get_book_views (backend);
- iter = e_list_get_iterator (book_views);
+ cd.backend = backend;
+ cd.func = e_book_backend_ldap_stop_book_view;
- while (e_iterator_is_valid (iter)) {
- EDataBookView *data_book_view = (EDataBookView *) e_iterator_get (iter);
- e_book_backend_ldap_stop_book_view (backend, data_book_view);
- e_iterator_next (iter);
- }
-
- g_object_unref (iter);
- g_object_unref (book_views);
+ e_book_backend_foreach_view (backend, call_cb, &cd);
}
static void
start_views (EBookBackend *backend)
{
- EList *book_views;
- EIterator *iter;
+ struct call_data cd;
- book_views = e_book_backend_get_book_views (backend);
- iter = e_list_get_iterator (book_views);
+ cd.backend = backend;
+ cd.func = e_book_backend_ldap_start_book_view;
- while (e_iterator_is_valid (iter)) {
- EDataBookView *data_book_view = (EDataBookView *) e_iterator_get (iter);
- e_book_backend_ldap_start_book_view (backend, data_book_view);
- e_iterator_next (iter);
- }
-
- g_object_unref (iter);
- g_object_unref (book_views);
+ e_book_backend_foreach_view (backend, call_cb, &cd);
}
#endif
static void
-e_book_backend_ldap_set_mode (EBookBackend *backend,
- EDataBookMode mode)
+e_book_backend_ldap_set_online (EBookBackend *backend, gboolean is_online)
{
EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
- if (bl->priv->mode == mode)
+ if (bl->priv->is_online == is_online)
return;
- bl->priv->mode = mode;
+ bl->priv->is_online = is_online;
#if 0
stop_views (backend);
#endif
/* Cancel all running operations */
- e_book_backend_ldap_cancel_operation (backend, NULL, NULL);
+ ldap_cancel_all_operations (backend);
- if (mode == E_DATA_BOOK_MODE_LOCAL) {
+ if (!is_online) {
/* Go offline */
- e_book_backend_set_is_writable (backend, FALSE);
- e_book_backend_notify_writable (backend, FALSE);
- e_book_backend_notify_connection_status (backend, FALSE);
+ e_book_backend_notify_readonly (backend, TRUE);
+ e_book_backend_notify_online (backend, FALSE);
#if 0
g_static_rec_mutex_lock (&eds_ldap_handler_lock);
@@ -5258,22 +5213,20 @@ e_book_backend_ldap_set_mode (EBookBackend *backend,
bl->priv->connected = FALSE;
#if 0
- if (e_book_backend_is_loaded (backend))
+ if (e_book_backend_is_opened (backend))
start_views (backend);
#endif
- }
- else if (mode == E_DATA_BOOK_MODE_REMOTE) {
+ } else {
/* Go online */
- e_book_backend_set_is_writable (backend, TRUE);
- e_book_backend_notify_writable (backend, TRUE);
- e_book_backend_notify_connection_status (backend, TRUE);
+ e_book_backend_notify_readonly (backend, FALSE);
+ e_book_backend_notify_online (backend, TRUE);
- if (e_book_backend_is_loaded (backend)) {
+ if (e_book_backend_is_opened (backend)) {
GError *error;
error = e_book_backend_ldap_connect (bl);
- e_book_backend_notify_auth_required (backend);
+ e_book_backend_notify_auth_required (backend, TRUE, NULL);
if (error)
g_error_free (error);
@@ -5337,13 +5290,13 @@ e_book_backend_ldap_dispose (GObject *object)
}
if (bl->priv->supported_fields) {
- g_list_foreach (bl->priv->supported_fields, (GFunc) g_free, NULL);
- g_list_free (bl->priv->supported_fields);
+ g_slist_foreach (bl->priv->supported_fields, (GFunc) g_free, NULL);
+ g_slist_free (bl->priv->supported_fields);
}
if (bl->priv->supported_auth_methods) {
- g_list_foreach (bl->priv->supported_auth_methods, (GFunc) g_free, NULL);
- g_list_free (bl->priv->supported_auth_methods);
+ g_slist_foreach (bl->priv->supported_auth_methods, (GFunc) g_free, NULL);
+ g_slist_free (bl->priv->supported_auth_methods);
}
if (bl->priv->summary_file_name) {
g_free (bl->priv->summary_file_name);
@@ -5355,6 +5308,11 @@ e_book_backend_ldap_dispose (GObject *object)
bl->priv->summary = NULL;
}
+ if (bl->priv->cache) {
+ g_object_unref (bl->priv->cache);
+ bl->priv->cache = NULL;
+ }
+
g_free (bl->priv->ldap_host);
g_free (bl->priv->ldap_rootdn);
g_free (bl->priv->ldap_search_filter);
@@ -5380,24 +5338,19 @@ e_book_backend_ldap_class_init (EBookBackendLDAPClass *klass)
parent_class = E_BOOK_BACKEND_CLASS (klass);
/* Set the virtual methods. */
- parent_class->load_source = e_book_backend_ldap_load_source;
- parent_class->remove = e_book_backend_ldap_remove;
- parent_class->get_static_capabilities = e_book_backend_ldap_get_static_capabilities;
-
- parent_class->create_contact = e_book_backend_ldap_create_contact;
- parent_class->remove_contacts = e_book_backend_ldap_remove_contacts;
- parent_class->modify_contact = e_book_backend_ldap_modify_contact;
- parent_class->get_contact = e_book_backend_ldap_get_contact;
- parent_class->get_contact_list = e_book_backend_ldap_get_contact_list;
- parent_class->start_book_view = e_book_backend_ldap_start_book_view;
- parent_class->stop_book_view = e_book_backend_ldap_stop_book_view;
- parent_class->get_changes = e_book_backend_ldap_get_changes;
- parent_class->authenticate_user = e_book_backend_ldap_authenticate_user;
- parent_class->get_required_fields = e_book_backend_ldap_get_required_fields;
- parent_class->get_supported_fields = e_book_backend_ldap_get_supported_fields;
- parent_class->get_supported_auth_methods = e_book_backend_ldap_get_supported_auth_methods;
- parent_class->cancel_operation = e_book_backend_ldap_cancel_operation;
- parent_class->set_mode = e_book_backend_ldap_set_mode;
+ parent_class->open = e_book_backend_ldap_open;
+ parent_class->remove = e_book_backend_ldap_remove;
+ parent_class->get_backend_property = e_book_backend_ldap_get_backend_property;
+
+ parent_class->create_contact = e_book_backend_ldap_create_contact;
+ parent_class->remove_contacts = e_book_backend_ldap_remove_contacts;
+ parent_class->modify_contact = e_book_backend_ldap_modify_contact;
+ parent_class->get_contact = e_book_backend_ldap_get_contact;
+ parent_class->get_contact_list = e_book_backend_ldap_get_contact_list;
+ parent_class->start_book_view = e_book_backend_ldap_start_book_view;
+ parent_class->stop_book_view = e_book_backend_ldap_stop_book_view;
+ parent_class->authenticate_user = e_book_backend_ldap_authenticate_user;
+ parent_class->set_online = e_book_backend_ldap_set_online;
object_class->dispose = e_book_backend_ldap_dispose;
}
@@ -5415,7 +5368,7 @@ e_book_backend_ldap_init (EBookBackendLDAP *backend)
priv->id_to_op = g_hash_table_new (g_int_hash, g_int_equal);
priv->poll_timeout = -1;
priv->marked_for_offline = FALSE;
- priv->mode = E_DATA_BOOK_MODE_REMOTE;
+ priv->is_online = TRUE;
priv->is_summary_ready = FALSE;
priv->reserved1 = NULL;
priv->reserved2 = NULL;
diff --git a/addressbook/backends/vcf/e-book-backend-vcf.c b/addressbook/backends/vcf/e-book-backend-vcf.c
index a9515f8..3d9d9f6 100644
--- a/addressbook/backends/vcf/e-book-backend-vcf.c
+++ b/addressbook/backends/vcf/e-book-backend-vcf.c
@@ -273,7 +273,7 @@ do_create (EBookBackendVCF *bvcf,
static void
e_book_backend_vcf_create_contact (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
const gchar *vcard,
EContact **contact,
GError **perror)
@@ -291,14 +291,14 @@ e_book_backend_vcf_create_contact (EBookBackendSync *backend,
static void
e_book_backend_vcf_remove_contacts (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
- GList *id_list,
- GList **ids,
+ GCancellable *cancellable,
+ const GSList *id_list,
+ GSList **ids,
GError **perror)
{
/* FIXME: make this handle bulk deletes like the file backend does */
EBookBackendVCF *bvcf = E_BOOK_BACKEND_VCF (backend);
- gchar *id = id_list->data;
+ const gchar *id = id_list->data;
GList *elem;
g_mutex_lock (bvcf->priv->mutex);
@@ -324,13 +324,13 @@ e_book_backend_vcf_remove_contacts (EBookBackendSync *backend,
vcf_flush_file, bvcf);
g_mutex_unlock (bvcf->priv->mutex);
- *ids = g_list_append (*ids, id);
+ *ids = g_slist_append (*ids, g_strdup (id));
}
static void
e_book_backend_vcf_modify_contact (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
const gchar *vcard,
EContact **contact,
GError **perror)
@@ -363,7 +363,7 @@ e_book_backend_vcf_modify_contact (EBookBackendSync *backend,
static void
e_book_backend_vcf_get_contact (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
const gchar *id,
gchar **vcard,
GError **perror)
@@ -385,23 +385,23 @@ typedef struct {
EBookBackendVCF *bvcf;
gboolean search_needed;
EBookBackendSExp *card_sexp;
- GList *list;
+ GSList *list;
} GetContactListClosure;
static void
foreach_get_contact_compare (gchar *vcard_string, GetContactListClosure *closure)
{
if ((!closure->search_needed) || e_book_backend_sexp_match_vcard (closure->card_sexp, vcard_string)) {
- closure->list = g_list_append (closure->list, g_strdup (vcard_string));
+ closure->list = g_slist_append (closure->list, g_strdup (vcard_string));
}
}
static void
e_book_backend_vcf_get_contact_list (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
const gchar *query,
- GList **contacts,
+ GSList **contacts,
GError **perror)
{
EBookBackendVCF *bvcf = E_BOOK_BACKEND_VCF (backend);
@@ -472,9 +472,9 @@ book_view_thread (gpointer data)
query = e_data_book_view_get_card_query (book_view);
if ( !strcmp (query, "(contains \"x-evolution-any-field\" \"\")"))
- e_data_book_view_notify_status_message (book_view, _("Loading..."));
+ e_data_book_view_notify_progress (book_view, -1, _("Loading..."));
else
- e_data_book_view_notify_status_message (book_view, _("Searching..."));
+ e_data_book_view_notify_progress (book_view, -1, _("Searching..."));
d(printf ("signalling parent thread\n"));
e_flag_set (closure->running);
@@ -541,60 +541,28 @@ e_book_backend_vcf_extract_path_from_uri (const gchar *uri)
static void
e_book_backend_vcf_authenticate_user (EBookBackendSync *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *user,
- const gchar *passwd,
- const gchar *auth_method,
+ GCancellable *cancellable,
+ ECredentials *credentials,
GError **perror)
{
/* Success */
}
-static void
-e_book_backend_vcf_get_required_fields (EBookBackendSync *backend,
- EDataBook *book,
- guint32 opid,
- GList **fields_out,
- GError **perror)
-{
- GList *fields = NULL;
-
- fields = g_list_append (fields , g_strdup (e_contact_field_name (E_CONTACT_FILE_AS)));
- *fields_out = fields;
-}
-
-static void
-e_book_backend_vcf_get_supported_fields (EBookBackendSync *backend,
- EDataBook *book,
- guint32 opid,
- GList **fields_out,
- GError **perror)
-{
- GList *fields = NULL;
- gint i;
-
- /* XXX we need a way to say "we support everything", since the
- vcf backend does */
- for (i = 0; i < E_CONTACT_FIELD_LAST; i++)
- fields = g_list_append (fields, (gchar *) e_contact_field_name (i));
-
- *fields_out = fields;
-}
-
#ifdef CREATE_DEFAULT_VCARD
# include <libedata-book/ximian-vcard.h>
#endif
static void
-e_book_backend_vcf_load_source (EBookBackend *backend,
- ESource *source,
- gboolean only_if_exists,
- GError **perror)
+e_book_backend_vcf_open (EBookBackendSync *backend,
+ EDataBook *book,
+ GCancellable *cancellable,
+ gboolean only_if_exists,
+ GError **perror)
{
EBookBackendVCF *bvcf = E_BOOK_BACKEND_VCF (backend);
+ ESource *source = e_book_backend_get_source (E_BOOK_BACKEND (backend));
gchar *dirname;
- gboolean writable = FALSE;
+ gboolean readonly = TRUE;
gchar *uri;
gint fd;
@@ -611,7 +579,7 @@ e_book_backend_vcf_load_source (EBookBackend *backend,
(GDestroyNotify) NULL);
if (fd != -1) {
- writable = TRUE;
+ readonly = FALSE;
} else {
fd = g_open (bvcf->priv->filename, O_RDONLY | O_BINARY, 0);
@@ -644,7 +612,7 @@ e_book_backend_vcf_load_source (EBookBackend *backend,
g_object_unref (contact);
#endif
- writable = TRUE;
+ readonly = FALSE;
}
}
}
@@ -659,32 +627,50 @@ e_book_backend_vcf_load_source (EBookBackend *backend,
load_file (bvcf, fd);
- e_book_backend_set_is_loaded (backend, TRUE);
- e_book_backend_set_is_writable (backend, writable);
+ e_book_backend_notify_readonly (E_BOOK_BACKEND (backend), readonly);
+ e_book_backend_notify_online (E_BOOK_BACKEND (backend), TRUE);
+ e_book_backend_notify_opened (E_BOOK_BACKEND (backend), NULL);
g_free (uri);
}
-static gchar *
-e_book_backend_vcf_get_static_capabilities (EBookBackend *backend)
+static gboolean
+e_book_backend_vcf_get_backend_property (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error)
{
- return g_strdup("local,do-initial-query,contact-lists");
-}
+ gboolean processed = TRUE;
+
+ g_return_val_if_fail (prop_name != NULL, FALSE);
+ g_return_val_if_fail (prop_value != NULL, FALSE);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ *prop_value = g_strdup ("local,do-initial-query,contact-lists");
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+ *prop_value = g_strdup (e_contact_field_name (E_CONTACT_FILE_AS));
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+ GSList *fields = NULL;
+ gint i;
+
+ /* XXX we need a way to say "we support everything", since the
+ vcf backend does */
+ for (i = 1; i < E_CONTACT_FIELD_LAST; i++)
+ fields = g_slist_append (fields, (gpointer) e_contact_field_name (i));
+
+ *prop_value = e_data_book_string_slist_to_comma_string (fields);
+ g_slist_free (fields);
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS)) {
+ *prop_value = NULL;
+ } else {
+ processed = FALSE;
+ }
-static void
-e_book_backend_vcf_cancel_operation (EBookBackend *backend, EDataBook *book, GError **perror)
-{
- g_propagate_error (perror, EDB_ERROR (COULD_NOT_CANCEL));
+ return processed;
}
static void
-e_book_backend_vcf_set_mode (EBookBackend *backend,
- EDataBookMode mode)
+e_book_backend_vcf_set_online (EBookBackend *backend, gboolean is_online)
{
- if (e_book_backend_is_loaded (backend)) {
- e_book_backend_notify_writable (backend, TRUE);
- e_book_backend_notify_connection_status (backend, TRUE);
- }
+ if (e_book_backend_is_opened (backend))
+ e_book_backend_notify_online (backend, TRUE);
}
/**
@@ -743,20 +729,18 @@ e_book_backend_vcf_class_init (EBookBackendVCFClass *klass)
backend_class = E_BOOK_BACKEND_CLASS (klass);
/* Set the virtual methods. */
- backend_class->load_source = e_book_backend_vcf_load_source;
- backend_class->get_static_capabilities = e_book_backend_vcf_get_static_capabilities;
- backend_class->start_book_view = e_book_backend_vcf_start_book_view;
- backend_class->stop_book_view = e_book_backend_vcf_stop_book_view;
- backend_class->cancel_operation = e_book_backend_vcf_cancel_operation;
- backend_class->set_mode = e_book_backend_vcf_set_mode;
- sync_class->create_contact_sync = e_book_backend_vcf_create_contact;
- sync_class->remove_contacts_sync = e_book_backend_vcf_remove_contacts;
- sync_class->modify_contact_sync = e_book_backend_vcf_modify_contact;
- sync_class->get_contact_sync = e_book_backend_vcf_get_contact;
- sync_class->get_contact_list_sync = e_book_backend_vcf_get_contact_list;
- sync_class->authenticate_user_sync = e_book_backend_vcf_authenticate_user;
- sync_class->get_required_fields_sync = e_book_backend_vcf_get_required_fields;
- sync_class->get_supported_fields_sync = e_book_backend_vcf_get_supported_fields;
+ backend_class->start_book_view = e_book_backend_vcf_start_book_view;
+ backend_class->stop_book_view = e_book_backend_vcf_stop_book_view;
+ backend_class->set_online = e_book_backend_vcf_set_online;
+
+ sync_class->open_sync = e_book_backend_vcf_open;
+ sync_class->get_backend_property_sync = e_book_backend_vcf_get_backend_property;
+ sync_class->create_contact_sync = e_book_backend_vcf_create_contact;
+ sync_class->remove_contacts_sync = e_book_backend_vcf_remove_contacts;
+ sync_class->modify_contact_sync = e_book_backend_vcf_modify_contact;
+ sync_class->get_contact_sync = e_book_backend_vcf_get_contact;
+ sync_class->get_contact_list_sync = e_book_backend_vcf_get_contact_list;
+ sync_class->authenticate_user_sync = e_book_backend_vcf_authenticate_user;
object_class->dispose = e_book_backend_vcf_dispose;
}
diff --git a/addressbook/backends/webdav/e-book-backend-webdav.c b/addressbook/backends/webdav/e-book-backend-webdav.c
index 5b0213a..53033a8 100644
--- a/addressbook/backends/webdav/e-book-backend-webdav.c
+++ b/addressbook/backends/webdav/e-book-backend-webdav.c
@@ -65,7 +65,7 @@ G_DEFINE_TYPE (EBookBackendWebdav, e_book_backend_webdav, E_TYPE_BOOK_BACKEND)
static EBookBackendClass *parent_class;
struct _EBookBackendWebdavPrivate {
- gint mode;
+ gboolean is_online;
gboolean marked_for_offline;
SoupSession *session;
EProxy *proxy;
@@ -288,7 +288,7 @@ webdav_handle_auth_request (EBookBackendWebdav *webdav)
if (priv->username != NULL) {
g_free (priv->username);
priv->username = NULL;
- g_free (priv->password);
+ e_credentials_util_safe_free_string (priv->password);
priv->password = NULL;
return EDB_ERROR (AUTHENTICATION_FAILED);
@@ -298,8 +298,7 @@ webdav_handle_auth_request (EBookBackendWebdav *webdav)
}
static void
-e_book_backend_webdav_create_contact (EBookBackend *backend,
- EDataBook *book, guint32 opid, const gchar *vcard)
+e_book_backend_webdav_create_contact (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *vcard)
{
EBookBackendWebdav *webdav = E_BOOK_BACKEND_WEBDAV (backend);
EBookBackendWebdavPrivate *priv = webdav->priv;
@@ -308,7 +307,7 @@ e_book_backend_webdav_create_contact (EBookBackend *backend,
guint status;
gchar *status_reason = NULL;
- if (priv->mode == E_DATA_BOOK_MODE_LOCAL) {
+ if (!priv->is_online) {
e_data_book_respond_create (book, opid, EDB_ERROR (REPOSITORY_OFFLINE), NULL);
return;
}
@@ -386,15 +385,14 @@ delete_contact (EBookBackendWebdav *webdav, const gchar *uri)
}
static void
-e_book_backend_webdav_remove_contacts (EBookBackend *backend,
- EDataBook *book, guint32 opid, GList *id_list)
+e_book_backend_webdav_remove_contacts (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const GSList *id_list)
{
EBookBackendWebdav *webdav = E_BOOK_BACKEND_WEBDAV (backend);
EBookBackendWebdavPrivate *priv = webdav->priv;
- GList *deleted_ids = NULL;
- GList *list;
+ GSList *deleted_ids = NULL;
+ const GSList *list;
- if (priv->mode == E_DATA_BOOK_MODE_LOCAL) {
+ if (!priv->is_online) {
e_data_book_respond_remove_contacts (book, opid,
EDB_ERROR (REPOSITORY_OFFLINE), NULL);
return;
@@ -415,16 +413,17 @@ e_book_backend_webdav_remove_contacts (EBookBackend *backend,
continue;
}
e_book_backend_cache_remove_contact (priv->cache, uid);
- deleted_ids = g_list_append (deleted_ids, list->data);
+ deleted_ids = g_slist_append (deleted_ids, list->data);
}
e_data_book_respond_remove_contacts (book, opid,
EDB_ERROR (SUCCESS), deleted_ids);
+
+ g_slist_free (deleted_ids);
}
static void
-e_book_backend_webdav_modify_contact (EBookBackend *backend,
- EDataBook *book, guint32 opid, const gchar *vcard)
+e_book_backend_webdav_modify_contact (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *vcard)
{
EBookBackendWebdav *webdav = E_BOOK_BACKEND_WEBDAV (backend);
EBookBackendWebdavPrivate *priv = webdav->priv;
@@ -434,7 +433,7 @@ e_book_backend_webdav_modify_contact (EBookBackend *backend,
guint status;
gchar *status_reason = NULL;
- if (priv->mode == E_DATA_BOOK_MODE_LOCAL) {
+ if (!priv->is_online) {
e_data_book_respond_create (book, opid,
EDB_ERROR (REPOSITORY_OFFLINE), NULL);
g_object_unref (contact);
@@ -494,15 +493,14 @@ e_book_backend_webdav_modify_contact (EBookBackend *backend,
}
static void
-e_book_backend_webdav_get_contact (EBookBackend *backend, EDataBook *book,
- guint32 opid, const gchar *uid)
+e_book_backend_webdav_get_contact (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *uid)
{
EBookBackendWebdav *webdav = E_BOOK_BACKEND_WEBDAV (backend);
EBookBackendWebdavPrivate *priv = webdav->priv;
EContact *contact;
gchar *vcard;
- if (priv->mode == E_DATA_BOOK_MODE_LOCAL) {
+ if (!priv->is_online) {
contact = e_book_backend_cache_get_contact (priv->cache, uid);
} else {
contact = download_contact (webdav, uid);
@@ -860,7 +858,7 @@ download_contacts (EBookBackendWebdav *webdav, EFlag *running,
}
if (book_view != NULL) {
- e_data_book_view_notify_status_message (book_view,
+ e_data_book_view_notify_progress (book_view, -1,
"Loading Addressbook summary...");
}
@@ -920,7 +918,7 @@ download_contacts (EBookBackendWebdav *webdav, EFlag *running,
gfloat percent = 100.0 / count * i;
gchar buf[100];
snprintf(buf, sizeof(buf), "Loading Contacts (%d%%)", (gint)percent);
- e_data_book_view_notify_status_message (book_view, buf);
+ e_data_book_view_notify_progress (book_view, -1, buf);
}
/* skip collections */
@@ -1012,7 +1010,7 @@ e_book_backend_webdav_start_book_view (EBookBackend *backend,
EBookBackendWebdav *webdav = E_BOOK_BACKEND_WEBDAV (backend);
EBookBackendWebdavPrivate *priv = webdav->priv;
- if (priv->mode == E_DATA_BOOK_MODE_REMOTE) {
+ if (priv->is_online) {
WebdavBackendSearchClosure *closure
= init_closure (book_view, E_BOOK_BACKEND_WEBDAV (backend));
@@ -1043,7 +1041,7 @@ e_book_backend_webdav_stop_book_view (EBookBackend *backend,
WebdavBackendSearchClosure *closure;
gboolean need_join;
- if (webdav->priv->mode == E_DATA_BOOK_MODE_LOCAL)
+ if (!webdav->priv->is_online)
return;
closure = get_closure (book_view);
@@ -1059,16 +1057,15 @@ e_book_backend_webdav_stop_book_view (EBookBackend *backend,
}
static void
-e_book_backend_webdav_get_contact_list (EBookBackend *backend, EDataBook *book,
- guint32 opid, const gchar *query)
+e_book_backend_webdav_get_contact_list (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *query)
{
EBookBackendWebdav *webdav = E_BOOK_BACKEND_WEBDAV (backend);
EBookBackendWebdavPrivate *priv = webdav->priv;
GList *contact_list;
- GList *vcard_list;
+ GSList *vcard_list;
GList *c;
- if (priv->mode == E_DATA_BOOK_MODE_REMOTE) {
+ if (priv->is_online) {
/* make sure the cache is up to date */
GError *error = download_contacts (webdav, NULL, NULL);
@@ -1085,26 +1082,27 @@ e_book_backend_webdav_get_contact_list (EBookBackend *backend, EDataBook *book,
EContact *contact = c->data;
gchar *vcard
= e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
- vcard_list = g_list_append (vcard_list, vcard);
+ vcard_list = g_slist_append (vcard_list, vcard);
g_object_unref (contact);
}
g_list_free (contact_list);
e_data_book_respond_get_contact_list (book, opid, EDB_ERROR (SUCCESS), vcard_list);
+
+ g_slist_foreach (vcard_list, (GFunc) g_free, NULL);
+ g_slist_free (vcard_list);
}
static void
-e_book_backend_webdav_authenticate_user (EBookBackend *backend, EDataBook *book,
- guint32 opid, const gchar *user, const gchar *password,
- const gchar *auth_method)
+e_book_backend_webdav_authenticate_user (EBookBackend *backend, GCancellable *cancellable, ECredentials *credentials)
{
EBookBackendWebdav *webdav = E_BOOK_BACKEND_WEBDAV (backend);
EBookBackendWebdavPrivate *priv = webdav->priv;
SoupMessage *message;
guint status;
- priv->username = g_strdup (user);
- priv->password = g_strdup (password);
+ priv->username = e_credentials_get (credentials, E_CREDENTIALS_KEY_USERNAME);
+ priv->password = e_credentials_get (credentials, E_CREDENTIALS_KEY_PASSWORD);
/* Evolution API requires a direct feedback on the authentication,
* so we send a PROPFIND to test wether user/password is correct */
@@ -1115,60 +1113,15 @@ e_book_backend_webdav_authenticate_user (EBookBackend *backend, EDataBook *book,
if (status == 401 || status == 407) {
g_free (priv->username);
priv->username = NULL;
- g_free (priv->password);
+ e_credentials_util_safe_free_string (priv->password);
priv->password = NULL;
- e_data_book_respond_authenticate_user (book, opid, EDB_ERROR (AUTHENTICATION_FAILED));
+ e_book_backend_notify_opened (backend, EDB_ERROR (AUTHENTICATION_FAILED));
} else {
- e_data_book_respond_authenticate_user (book, opid, EDB_ERROR (SUCCESS));
+ e_book_backend_notify_opened (backend, EDB_ERROR (SUCCESS));
}
}
-static void
-e_book_backend_webdav_get_supported_fields (EBookBackend *backend,
- EDataBook *book, guint32 opid)
-{
- GList *fields = NULL;
- gint i;
-
- /* we support everything */
- for (i = 1; i < E_CONTACT_FIELD_LAST; ++i) {
- fields = g_list_append (fields, g_strdup (e_contact_field_name (i)));
- }
-
- e_data_book_respond_get_supported_fields (book, opid, EDB_ERROR (SUCCESS), fields);
- g_list_foreach (fields, (GFunc) g_free, NULL);
- g_list_free (fields);
-}
-
-static void
-e_book_backend_webdav_get_supported_auth_methods (EBookBackend *backend,
- EDataBook *book, guint32 opid)
-{
- GList *auth_methods = NULL;
-
- auth_methods = g_list_append(auth_methods, g_strdup("plain/password"));
-
- e_data_book_respond_get_supported_auth_methods (book, opid, EDB_ERROR (SUCCESS), auth_methods);
-
- g_list_foreach (auth_methods, (GFunc) g_free, NULL);
- g_list_free (auth_methods);
-}
-
-static void
-e_book_backend_webdav_get_required_fields (EBookBackend *backend,
- EDataBook *book, guint32 opid)
-{
- GList *fields = NULL;
- const gchar *field_name;
-
- field_name = e_contact_field_name (E_CONTACT_FILE_AS);
- fields = g_list_append (fields , g_strdup (field_name));
-
- e_data_book_respond_get_supported_fields (book, opid, EDB_ERROR (SUCCESS), fields);
- g_list_free (fields);
-}
-
/** authentication callback for libsoup */
static void soup_authenticate (SoupSession *session, SoupMessage *message,
SoupAuth *auth, gboolean retrying, gpointer data)
@@ -1180,8 +1133,7 @@ static void soup_authenticate (SoupSession *session, SoupMessage *message,
return;
if (priv->username != NULL) {
- soup_auth_authenticate (auth, g_strdup (priv->username),
- g_strdup (priv->password));
+ soup_auth_authenticate (auth, priv->username, priv->password);
}
}
@@ -1203,11 +1155,11 @@ proxy_settings_changed (EProxy *proxy, gpointer user_data)
}
static void
-e_book_backend_webdav_load_source (EBookBackend *backend,
- ESource *source, gboolean only_if_exists, GError **perror)
+e_book_backend_webdav_open (EBookBackend *backend, EDataBook *book, guint opid, GCancellable *cancellable, gboolean only_if_exists)
{
EBookBackendWebdav *webdav = E_BOOK_BACKEND_WEBDAV (backend);
EBookBackendWebdavPrivate *priv = webdav->priv;
+ ESource *source = e_book_backend_get_source (backend);
gchar *uri;
const gchar *cache_dir;
const gchar *offline;
@@ -1224,7 +1176,7 @@ e_book_backend_webdav_load_source (EBookBackend *backend,
uri = e_source_get_uri (source);
if (uri == NULL) {
- g_propagate_error (perror, EDB_ERROR_EX (OTHER_ERROR, "No uri given for addressbook"));
+ e_book_backend_respond_opened (backend, book, opid, EDB_ERROR_EX (OTHER_ERROR, "No uri given for addressbook"));
return;
}
@@ -1232,7 +1184,7 @@ e_book_backend_webdav_load_source (EBookBackend *backend,
g_free (uri);
if (!suri) {
- g_propagate_error (perror, EDB_ERROR_EX (OTHER_ERROR, "Invalid uri given for addressbook"));
+ e_book_backend_respond_opened (backend, book, opid, EDB_ERROR_EX (OTHER_ERROR, "Invalid uri given for addressbook"));
return;
}
@@ -1240,17 +1192,16 @@ e_book_backend_webdav_load_source (EBookBackend *backend,
if (offline && g_str_equal(offline, "1"))
priv->marked_for_offline = TRUE;
- if (priv->mode == E_DATA_BOOK_MODE_LOCAL
- && !priv->marked_for_offline ) {
+ if (!priv->is_online && !priv->marked_for_offline ) {
soup_uri_free (suri);
- g_propagate_error (perror, EDB_ERROR (OFFLINE_UNAVAILABLE));
+ e_book_backend_respond_opened (backend, book, opid, EDB_ERROR (OFFLINE_UNAVAILABLE));
return;
}
if (!suri->scheme || !g_str_equal (suri->scheme, "webdav")) {
/* the book is not for us */
soup_uri_free (suri);
- g_propagate_error (perror, EDB_ERROR_EX (OTHER_ERROR, "Not a webdav uri"));
+ e_book_backend_respond_opened (backend, book, opid, EDB_ERROR_EX (OTHER_ERROR, "Not a webdav uri"));
return;
}
@@ -1291,7 +1242,7 @@ e_book_backend_webdav_load_source (EBookBackend *backend,
priv->uri = soup_uri_to_string (suri, FALSE);
if (!priv->uri) {
soup_uri_free (suri);
- g_propagate_error (perror, EDB_ERROR_EX (OTHER_ERROR, "Cannot transform SoupURI to string"));
+ e_book_backend_respond_opened (backend, book, opid, EDB_ERROR_EX (OTHER_ERROR, "Cannot transform SoupURI to string"));
return;
}
@@ -1310,55 +1261,71 @@ e_book_backend_webdav_load_source (EBookBackend *backend,
proxy_settings_changed (priv->proxy, priv);
webdav_debug_setup (priv->session);
- e_book_backend_notify_auth_required (backend);
- e_book_backend_set_is_loaded (backend, TRUE);
- e_book_backend_notify_connection_status (backend, TRUE);
- e_book_backend_set_is_writable (backend, TRUE);
- e_book_backend_notify_writable (backend, TRUE);
+ e_book_backend_notify_auth_required (backend, TRUE, NULL);
+ e_book_backend_notify_online (backend, TRUE);
+ e_book_backend_notify_readonly (backend, FALSE);
soup_uri_free (suri);
+
+ e_data_book_respond_open (book, opid, NULL /* Success */);
}
static void
-e_book_backend_webdav_remove (EBookBackend *backend, EDataBook *book,
- guint32 opid)
+e_book_backend_webdav_remove (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
{
e_data_book_respond_remove (book, opid, EDB_ERROR (SUCCESS));
}
static void
-e_book_backend_webdav_set_mode (EBookBackend *backend,
- EDataBookMode mode)
+e_book_backend_webdav_set_online (EBookBackend *backend, gboolean is_online)
{
EBookBackendWebdav *webdav = E_BOOK_BACKEND_WEBDAV (backend);
- webdav->priv->mode = mode;
+ webdav->priv->is_online = is_online;
/* set_mode is called before the backend is loaded */
- if (!e_book_backend_is_loaded (backend))
+ if (!e_book_backend_is_opened (backend))
return;
- if (mode == E_DATA_BOOK_MODE_LOCAL) {
- e_book_backend_set_is_writable (backend, FALSE);
- e_book_backend_notify_writable (backend, FALSE);
- e_book_backend_notify_connection_status (backend, FALSE);
- } else if (mode == E_DATA_BOOK_MODE_REMOTE) {
- e_book_backend_set_is_writable (backend, TRUE);
- e_book_backend_notify_writable (backend, TRUE);
- e_book_backend_notify_connection_status (backend, TRUE);
+ if (!is_online) {
+ e_book_backend_notify_readonly (backend, TRUE);
+ e_book_backend_notify_online (backend, FALSE);
+ } else {
+ e_book_backend_notify_readonly (backend, FALSE);
+ e_book_backend_notify_online (backend, TRUE);
}
}
-static gchar *
-e_book_backend_webdav_get_static_capabilities (EBookBackend *backend)
-{
- return g_strdup("net,do-initial-query,contact-lists");
-}
-
static void
-e_book_backend_webdav_cancel_operation (EBookBackend *backend, EDataBook *book, GError **perror)
+e_book_backend_webdav_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
{
- g_propagate_error (perror, EDB_ERROR (COULD_NOT_CANCEL));
+ g_return_if_fail (prop_name != NULL);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ e_data_book_respond_get_backend_property (book, opid, NULL, "net,do-initial-query,contact-lists");
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+ e_data_book_respond_get_backend_property (book, opid, NULL, e_contact_field_name (E_CONTACT_FILE_AS));
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+ gchar *fields_str;
+ GSList *fields = NULL;
+ gint i;
+
+ /* we support everything */
+ for (i = 1; i < E_CONTACT_FIELD_LAST; ++i) {
+ fields = g_slist_append (fields, (gpointer) e_contact_field_name (i));
+ }
+
+ fields_str = e_data_book_string_slist_to_comma_string (fields);
+
+ e_data_book_respond_get_backend_property (book, opid, NULL, fields_str);
+
+ g_slist_free (fields);
+ g_free (fields_str);
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS)) {
+ e_data_book_respond_get_backend_property (book, opid, NULL, "plain/password");
+ } else {
+ E_BOOK_BACKEND_CLASS (e_book_backend_webdav_parent_class)->get_backend_property (backend, book, opid, cancellable, prop_name);
+ }
}
EBookBackend *
@@ -1381,7 +1348,7 @@ e_book_backend_webdav_dispose (GObject *object)
do_unref (priv->cache);
do_free (priv->uri);
do_free (priv->username);
- do_free (priv->password);
+ if (priv->password) { e_credentials_util_safe_free_string (priv->password); priv->password = NULL; }
#undef do_unref
#undef do_free
@@ -1400,25 +1367,21 @@ e_book_backend_webdav_class_init (EBookBackendWebdavClass *klass)
backend_class = E_BOOK_BACKEND_CLASS (klass);
/* Set the virtual methods. */
- backend_class->load_source = e_book_backend_webdav_load_source;
- backend_class->get_static_capabilities = e_book_backend_webdav_get_static_capabilities;
-
- backend_class->create_contact = e_book_backend_webdav_create_contact;
- backend_class->remove_contacts = e_book_backend_webdav_remove_contacts;
- backend_class->modify_contact = e_book_backend_webdav_modify_contact;
- backend_class->get_contact = e_book_backend_webdav_get_contact;
- backend_class->get_contact_list = e_book_backend_webdav_get_contact_list;
- backend_class->start_book_view = e_book_backend_webdav_start_book_view;
- backend_class->stop_book_view = e_book_backend_webdav_stop_book_view;
- backend_class->authenticate_user = e_book_backend_webdav_authenticate_user;
- backend_class->get_supported_fields = e_book_backend_webdav_get_supported_fields;
- backend_class->get_required_fields = e_book_backend_webdav_get_required_fields;
- backend_class->cancel_operation = e_book_backend_webdav_cancel_operation;
- backend_class->get_supported_auth_methods = e_book_backend_webdav_get_supported_auth_methods;
- backend_class->remove = e_book_backend_webdav_remove;
- backend_class->set_mode = e_book_backend_webdav_set_mode;
-
- object_class->dispose = e_book_backend_webdav_dispose;
+ backend_class->open = e_book_backend_webdav_open;
+ backend_class->get_backend_property = e_book_backend_webdav_get_backend_property;
+
+ backend_class->create_contact = e_book_backend_webdav_create_contact;
+ backend_class->remove_contacts = e_book_backend_webdav_remove_contacts;
+ backend_class->modify_contact = e_book_backend_webdav_modify_contact;
+ backend_class->get_contact = e_book_backend_webdav_get_contact;
+ backend_class->get_contact_list = e_book_backend_webdav_get_contact_list;
+ backend_class->start_book_view = e_book_backend_webdav_start_book_view;
+ backend_class->stop_book_view = e_book_backend_webdav_stop_book_view;
+ backend_class->authenticate_user = e_book_backend_webdav_authenticate_user;
+ backend_class->remove = e_book_backend_webdav_remove;
+ backend_class->set_online = e_book_backend_webdav_set_online;
+
+ object_class->dispose = e_book_backend_webdav_dispose;
g_type_class_add_private (object_class, sizeof (EBookBackendWebdavPrivate));
}
diff --git a/addressbook/libebook/Makefile.am b/addressbook/libebook/Makefile.am
index de9f7f1..99e3edc 100644
--- a/addressbook/libebook/Makefile.am
+++ b/addressbook/libebook/Makefile.am
@@ -23,6 +23,9 @@ libebook_1_2_la_CPPFLAGS = \
libebook_1_2_la_SOURCES = \
$(MARSHAL_GENERATED) \
e-address-western.c \
+ e-book-client.c \
+ e-book-client-view.c \
+ e-book-client-view-private.h \
e-book-query.c \
e-book-view-private.h \
e-book-view.c \
@@ -48,6 +51,8 @@ libebookincludedir = $(privincludedir)/libebook
libebookinclude_HEADERS = \
e-address-western.h \
+ e-book-client.h \
+ e-book-client-view.h \
e-book-query.h \
e-book-view.h \
e-book-types.h \
diff --git a/addressbook/libedata-book/opid.h b/addressbook/libebook/e-book-client-view-private.h
similarity index 73%
rename from addressbook/libedata-book/opid.h
rename to addressbook/libebook/e-book-client-view-private.h
index 20bbf1a..26d8a7f 100644
--- a/addressbook/libedata-book/opid.h
+++ b/addressbook/libebook/e-book-client-view-private.h
@@ -19,10 +19,16 @@
* Author: Ross Burton <ross linux intel com>
*/
-#include <glib.h>
+#ifndef E_BOOK_CLIENT_VIEW_PRIVATE_H
+#define E_BOOK_CLIENT_VIEW_PRIVATE_H
-/* Stupid EDS internal API */
+#include "e-book-client.h"
+#include "e-book-view.h"
-guint32 opid_store (gpointer p);
+struct _EGdbusBookView;
-gpointer opid_fetch (guint32 id);
+EBookClientView *_e_book_client_view_new (EBookClient *book_client, struct _EGdbusBookView *gdbus_bookview);
+
+G_END_DECLS
+
+#endif /* E_BOOK_CLIENT_VIEW_PRIVATE_H */
diff --git a/addressbook/libebook/e-book-client-view.c b/addressbook/libebook/e-book-client-view.c
new file mode 100644
index 0000000..8b99cf2
--- /dev/null
+++ b/addressbook/libebook/e-book-client-view.c
@@ -0,0 +1,384 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This library 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 this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Ross Burton <ross linux intel com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+
+#include "e-book-client.h"
+#include "e-book-client-view.h"
+#include "e-book-client-view-private.h"
+#include "e-book-marshal.h"
+#include "libedata-book/e-data-book-types.h"
+#include "e-gdbus-book-view.h"
+
+G_DEFINE_TYPE (EBookClientView, e_book_client_view, G_TYPE_OBJECT);
+
+struct _EBookClientViewPrivate {
+ GDBusProxy *gdbus_bookview;
+ EBookClient *client;
+ gboolean running;
+};
+
+enum {
+ OBJECTS_ADDED,
+ OBJECTS_MODIFIED,
+ OBJECTS_REMOVED,
+ PROGRESS,
+ COMPLETE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+static void
+objects_added_cb (EGdbusBookView *object, const gchar * const *vcards, EBookClientView *view)
+{
+ const gchar * const *p;
+ GSList *contacts = NULL;
+
+ if (!view->priv->running)
+ return;
+
+ for (p = vcards; *p; p++) {
+ contacts = g_slist_prepend (contacts, e_contact_new_from_vcard (*p));
+ }
+
+ contacts = g_slist_reverse (contacts);
+
+ g_signal_emit (view, signals[OBJECTS_ADDED], 0, contacts);
+
+ g_slist_foreach (contacts, (GFunc) g_object_unref, NULL);
+ g_slist_free (contacts);
+}
+
+static void
+objects_modified_cb (EGdbusBookView *object, const gchar * const *vcards, EBookClientView *view)
+{
+ const gchar * const *p;
+ GSList *contacts = NULL;
+
+ if (!view->priv->running)
+ return;
+
+ for (p = vcards; *p; p++) {
+ contacts = g_slist_prepend (contacts, e_contact_new_from_vcard (*p));
+ }
+ contacts = g_slist_reverse (contacts);
+
+ g_signal_emit (view, signals[OBJECTS_MODIFIED], 0, contacts);
+
+ g_slist_foreach (contacts, (GFunc) g_object_unref, NULL);
+ g_slist_free (contacts);
+}
+
+static void
+objects_removed_cb (EGdbusBookView *object, const gchar * const *ids, EBookClientView *view)
+{
+ const gchar * const *p;
+ GSList *list = NULL;
+
+ if (!view->priv->running)
+ return;
+
+ for (p = ids; *p; p++) {
+ list = g_slist_prepend (list, (gchar *) *p);
+ }
+ list = g_slist_reverse (list);
+
+ g_signal_emit (view, signals[OBJECTS_REMOVED], 0, list);
+
+ /* No need to free the values, our caller will */
+ g_slist_free (list);
+}
+
+static void
+progress_cb (EGdbusBookView *object, guint percent, const gchar *message, EBookClientView *view)
+{
+ if (!view->priv->running)
+ return;
+
+ g_signal_emit (view, signals[PROGRESS], 0, percent, message);
+}
+
+static void
+complete_cb (EGdbusBookView *object, const gchar * const *in_error_strv, EBookClientView *view)
+{
+ GError *error = NULL;
+
+ if (!view->priv->running)
+ return;
+
+ g_return_if_fail (e_gdbus_templates_decode_error (in_error_strv, &error));
+
+ g_signal_emit (view, signals[COMPLETE], 0, error);
+
+ if (error)
+ g_error_free (error);
+}
+
+/*
+ * _e_book_client_view_new:
+ * @book_client: an #EBookClient
+ * @gdbus_bookview: The #EGdbusBookView to get signals from
+ *
+ * Creates a new #EBookClientView based on #EBookClient and listening to @gdbus_bookview.
+ * This is a private function, applications should call e_book_client_get_view() or
+ * e_book_client_get_view_sync().
+ *
+ * Returns: A new #EBookClientView.
+ **/
+EBookClientView *
+_e_book_client_view_new (EBookClient *book_client, EGdbusBookView *gdbus_bookview)
+{
+ EBookClientView *view;
+ EBookClientViewPrivate *priv;
+
+ view = g_object_new (E_TYPE_BOOK_CLIENT_VIEW, NULL);
+ priv = view->priv;
+
+ priv->client = g_object_ref (book_client);
+
+ /* Take ownership of the gdbus_bookview object */
+ priv->gdbus_bookview = g_object_ref (G_DBUS_PROXY (gdbus_bookview));
+
+ g_object_add_weak_pointer (G_OBJECT (gdbus_bookview), (gpointer) &priv->gdbus_bookview);
+ g_signal_connect (priv->gdbus_bookview, "objects-added", G_CALLBACK (objects_added_cb), view);
+ g_signal_connect (priv->gdbus_bookview, "objects-modified", G_CALLBACK (objects_modified_cb), view);
+ g_signal_connect (priv->gdbus_bookview, "objects-removed", G_CALLBACK (objects_removed_cb), view);
+ g_signal_connect (priv->gdbus_bookview, "progress", G_CALLBACK (progress_cb), view);
+ g_signal_connect (priv->gdbus_bookview, "complete", G_CALLBACK (complete_cb), view);
+
+ return view;
+}
+
+/**
+ * e_book_client_view_get_client:
+ * @view: an #EBookClientView
+ *
+ * Returns the #EBookClient that this book view is monitoring.
+ *
+ * Returns: an #EBookClient.
+ **/
+EBookClient *
+e_book_client_view_get_client (EBookClientView *view)
+{
+ g_return_val_if_fail (E_IS_BOOK_CLIENT_VIEW (view), NULL);
+
+ return view->priv->client;
+}
+
+/**
+ * e_book_client_view_start:
+ * @error: A #GError
+ * @view: an #EBookClientView
+ *
+ * Tells @view to start processing events.
+ */
+void
+e_book_client_view_start (EBookClientView *view, GError **error)
+{
+ EBookClientViewPrivate *priv;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (E_IS_BOOK_CLIENT_VIEW (view));
+
+ priv = view->priv;
+
+ if (priv->gdbus_bookview) {
+ GError *local_error = NULL;
+
+ if (e_gdbus_book_view_call_start_sync (priv->gdbus_bookview, NULL, &local_error))
+ priv->running = TRUE;
+
+ e_client_util_unwrap_dbus_error (local_error, error, NULL, 0, 0, FALSE);
+ } else {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR, _("Cannot start view, D-Bus proxy gone"));
+ }
+}
+
+/**
+ * e_book_client_view_stop:
+ * @view: an #EBookClientView
+ * @error: A #GError
+ *
+ * Tells @view to stop processing events.
+ **/
+void
+e_book_client_view_stop (EBookClientView *view, GError **error)
+{
+ EBookClientViewPrivate *priv;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (E_IS_BOOK_CLIENT_VIEW (view));
+
+ priv = view->priv;
+ priv->running = FALSE;
+
+ if (priv->gdbus_bookview) {
+ GError *local_error = NULL;
+
+ e_gdbus_book_view_call_stop_sync (priv->gdbus_bookview, NULL, &local_error);
+
+ e_client_util_unwrap_dbus_error (local_error, error, NULL, 0, 0, FALSE);
+ } else {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR, _("Cannot stop view, D-Bus proxy gone"));
+ }
+}
+
+/**
+ * e_book_client_view_set_fields_of_interest:
+ * @view: An #EBookClientView object
+ * @fields_of_interest: List of field names in which the client is interested
+ * @error: A #GError
+ *
+ * Client can instruct server to which fields it is interested in only, thus
+ * the server can return less data over the wire. The server can still return
+ * complete objects, this is just a hint to it that the listed fields will
+ * be used only. The UID field is returned always. Initial views has no fields
+ * of interest and using %NULL for @fields_of_interest will unset any previous
+ * changes.
+ *
+ * Some backends can use summary information of its cache to create artifical
+ * objects, which will omit stored object parsing. If this cannot be done then
+ * it will simply return object as is stored in the cache.
+ **/
+void
+e_book_client_view_set_fields_of_interest (EBookClientView *view, const GSList *fields_of_interest, GError **error)
+{
+ EBookClientViewPrivate *priv;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (E_IS_BOOK_CLIENT_VIEW (view));
+
+ priv = view->priv;
+
+ if (priv->gdbus_bookview) {
+ GError *local_error = NULL;
+ gchar **strv;
+
+ strv = e_client_util_slist_to_strv (fields_of_interest);
+ e_gdbus_book_view_call_set_fields_of_interest_sync (priv->gdbus_bookview, (const gchar * const *) strv, NULL, &local_error);
+ g_strfreev (strv);
+
+ e_client_util_unwrap_dbus_error (local_error, error, NULL, 0, 0, FALSE);
+ } else {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR, _("Cannot set fields of interest, D-Bus proxy gone"));
+ }
+}
+
+static void
+e_book_client_view_init (EBookClientView *view)
+{
+ view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view, E_TYPE_BOOK_CLIENT_VIEW, EBookClientViewPrivate);
+ view->priv->gdbus_bookview = NULL;
+
+ view->priv->client = NULL;
+ view->priv->running = FALSE;
+}
+
+static void
+book_client_view_dispose (GObject *object)
+{
+ EBookClientView *view = E_BOOK_CLIENT_VIEW (object);
+
+ if (view->priv->gdbus_bookview) {
+ GError *error = NULL;
+
+ g_signal_handlers_disconnect_matched (view->priv->gdbus_bookview, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view);
+ e_gdbus_book_view_call_dispose_sync (G_DBUS_PROXY (view->priv->gdbus_bookview), NULL, &error);
+ g_object_unref (view->priv->gdbus_bookview);
+ view->priv->gdbus_bookview = NULL;
+
+ if (error) {
+ g_warning ("Failed to dispose book view: %s", error->message);
+ g_error_free (error);
+ }
+ }
+
+ if (view->priv->client) {
+ g_object_unref (view->priv->client);
+ view->priv->client = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_book_client_view_parent_class)->dispose (object);
+}
+
+static void
+e_book_client_view_class_init (EBookClientViewClass *klass)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (klass, sizeof (EBookClientViewPrivate));
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = book_client_view_dispose;
+
+ signals [OBJECTS_ADDED] =
+ g_signal_new ("objects-added",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookClientViewClass, objects_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+ signals [OBJECTS_MODIFIED] =
+ g_signal_new ("objects-modified",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookClientViewClass, objects_modified),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+ signals [OBJECTS_REMOVED] =
+ g_signal_new ("objects-removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookClientViewClass, objects_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+ signals [PROGRESS] =
+ g_signal_new ("progress",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookClientViewClass, progress),
+ NULL, NULL,
+ e_gdbus_marshallers_VOID__UINT_STRING,
+ G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
+
+ signals [COMPLETE] =
+ g_signal_new ("complete",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookClientViewClass, complete),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1, G_TYPE_ERROR);
+}
diff --git a/addressbook/libebook/e-book-client-view.h b/addressbook/libebook/e-book-client-view.h
new file mode 100644
index 0000000..c11495d
--- /dev/null
+++ b/addressbook/libebook/e-book-client-view.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * 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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_BOOK_CLIENT_VIEW_H
+#define E_BOOK_CLIENT_VIEW_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#define E_TYPE_BOOK_CLIENT_VIEW (e_book_client_view_get_type ())
+#define E_BOOK_CLIENT_VIEW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_BOOK_CLIENT_VIEW, EBookClientView))
+#define E_BOOK_CLIENT_VIEW_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), E_TYPE_BOOK_CLIENT_VIEW, EBookClientViewClass))
+#define E_IS_BOOK_CLIENT_VIEW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_BOOK_CLIENT_VIEW))
+#define E_IS_BOOK_CLIENT_VIEW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_BOOK_CLIENT_VIEW))
+#define E_BOOK_CLIENT_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_BOOK_CLIENT_VIEW, EBookClientViewClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EBookClientView EBookClientView;
+typedef struct _EBookClientViewClass EBookClientViewClass;
+typedef struct _EBookClientViewPrivate EBookClientViewPrivate;
+
+struct _EBookClient; /* Forward reference */
+
+struct _EBookClientView {
+ GObject parent;
+ /*< private >*/
+ EBookClientViewPrivate *priv;
+};
+
+struct _EBookClientViewClass {
+ GObjectClass parent;
+
+ /*
+ * Signals.
+ */
+ void (* objects_added) (EBookClientView *view, const GSList *objects);
+ void (* objects_modified) (EBookClientView *view, const GSList *objects);
+ void (* objects_removed) (EBookClientView *view, const GSList *uids);
+
+ void (* progress) (EBookClientView *view, const gchar *message);
+ void (* complete) (EBookClientView *view, const GError *error);
+};
+
+GType e_book_client_view_get_type (void);
+struct _EBookClient * e_book_client_view_get_client (EBookClientView *view);
+gboolean e_book_client_view_is_running (EBookClientView *view);
+void e_book_client_view_set_fields_of_interest(EBookClientView *view, const GSList *fields_of_interest, GError **error);
+void e_book_client_view_start (EBookClientView *view, GError **error);
+void e_book_client_view_stop (EBookClientView *view, GError **error);
+
+G_END_DECLS
+
+#endif /* E_BOOK_CLIENT_VIEW_H */
diff --git a/addressbook/libebook/e-book-client.c b/addressbook/libebook/e-book-client.c
new file mode 100644
index 0000000..be9ceb9
--- /dev/null
+++ b/addressbook/libebook/e-book-client.c
@@ -0,0 +1,2093 @@
+/*
+ * e-book-client.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include "libedataserver/e-data-server-util.h"
+#include "libedataserver/e-client-private.h"
+
+#include "e-book-client.h"
+#include "e-contact.h"
+#include "e-name-western.h"
+#include "e-book-client-view-private.h"
+
+#include "e-gdbus-book.h"
+#include "e-gdbus-book-factory.h"
+#include "e-gdbus-book-view.h"
+
+struct _EBookClientPrivate
+{
+ /* GDBus data */
+ GDBusProxy *gdbus_book;
+ guint gone_signal_id;
+};
+
+G_DEFINE_TYPE (EBookClient, e_book_client, E_TYPE_CLIENT)
+
+/**
+ * Well-known book backend properties:
+ * @BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS: Retrieves comma-separated list
+ * of required fields by the backend. Use e_client_util_parse_comma_strings()
+ * to parse returned string value into a #GSList. These fields are required
+ * to be filled in for all contacts.
+ * @BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS: Retrieves comma-separated list
+ * of supported fields by the backend. Use e_client_util_parse_comma_strings()
+ * to parse returned string value into a #GSList. These fields can be
+ * stored for contacts.
+ * @BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS: Retrieves comma-separated list
+ * of supported authentication methods by the backend.
+ * Use e_client_util_parse_comma_strings() to parse returned string value
+ * into a #GSList.
+ *
+ * See also: @CLIENT_BACKEND_PROPERTY_OPENED, @CLIENT_BACKEND_PROPERTY_OPENING,
+ * @CLIENT_BACKEND_PROPERTY_ONLINE, @CLIENT_BACKEND_PROPERTY_READONLY
+ * @CLIENT_BACKEND_PROPERTY_CACHE_DIR, @CLIENT_BACKEND_PROPERTY_CAPABILITIES
+ **/
+
+GQuark
+e_book_client_error_quark (void)
+{
+ static GQuark q = 0;
+ if (q == 0)
+ q = g_quark_from_static_string ("e-book-client-error-quark");
+
+ return q;
+}
+
+const gchar *
+e_book_client_error_to_string (EBookClientError code)
+{
+ switch (code) {
+ case E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK:
+ return C_("BookClientError", "No such book");
+ case E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND:
+ return C_("BookClientError", "Contact not found");
+ case E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS:
+ return C_("BookClientError", "Contact ID already exists");
+ case E_BOOK_CLIENT_ERROR_TLS_NOT_AVAILABLE:
+ return C_("BookClientError", "TLS not available");
+ case E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE:
+ return C_("BookClientError", "No such source");
+ case E_BOOK_CLIENT_ERROR_OFFLINE_UNAVAILABLE:
+ return C_("BookClientError", "Offline unavailable");
+ case E_BOOK_CLIENT_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD:
+ return C_("BookClientError", "Unsupported authentication method");
+ case E_BOOK_CLIENT_ERROR_NO_SPACE:
+ return C_("BookClientError", "No space");
+ }
+
+ return C_("BookClientError", "Unknown error");
+}
+
+/**
+ * If the specified GError is a remote error, then create a new error
+ * representing the remote error. If the error is anything else, then
+ * leave it alone.
+ */
+static gboolean
+unwrap_dbus_error (GError *error, GError **client_error)
+{
+ #define err(a,b) "org.gnome.evolution.dataserver.AddressBook." a, b
+ static struct EClientErrorsList
+ book_errors[] = {
+ { err ("Success", -1) },
+ { err ("ContactNotFound", E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND) },
+ { err ("ContactIDAlreadyExists", E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS) },
+ { err ("UnsupportedAuthenticationMethod", E_BOOK_CLIENT_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD) },
+ { err ("TLSNotAvailable", E_BOOK_CLIENT_ERROR_TLS_NOT_AVAILABLE) },
+ { err ("NoSuchBook", E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK) },
+ { err ("BookRemoved", E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE) },
+ { err ("OfflineUnavailable", E_BOOK_CLIENT_ERROR_OFFLINE_UNAVAILABLE) },
+ { err ("NoSpace", E_BOOK_CLIENT_ERROR_NO_SPACE) }
+ }, cl_errors[] = {
+ { err ("Busy", E_CLIENT_ERROR_BUSY) },
+ { err ("RepositoryOffline", E_CLIENT_ERROR_REPOSITORY_OFFLINE) },
+ { err ("PermissionDenied", E_CLIENT_ERROR_PERMISSION_DENIED) },
+ { err ("AuthenticationFailed", E_CLIENT_ERROR_AUTHENTICATION_FAILED) },
+ { err ("AuthenticationRequired", E_CLIENT_ERROR_AUTHENTICATION_REQUIRED) },
+ { err ("CouldNotCancel", E_CLIENT_ERROR_COULD_NOT_CANCEL) },
+ { err ("InvalidArg", E_CLIENT_ERROR_INVALID_ARG) },
+ { err ("NotSupported", E_CLIENT_ERROR_NOT_SUPPORTED) },
+ { err ("UnsupportedField", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("SearchSizeLimitExceeded", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("SearchTimeLimitExceeded", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("InvalidQuery", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("QueryRefused", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("InvalidServerVersion", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("OtherError", E_CLIENT_ERROR_OTHER_ERROR) }
+ };
+ #undef err
+
+ if (error == NULL)
+ return TRUE;
+
+ if (!e_client_util_unwrap_dbus_error (error, client_error, book_errors, G_N_ELEMENTS (book_errors), E_BOOK_CLIENT_ERROR, TRUE))
+ e_client_util_unwrap_dbus_error (error, client_error, cl_errors, G_N_ELEMENTS (cl_errors), E_CLIENT_ERROR, FALSE);
+
+ return FALSE;
+}
+
+static void
+set_proxy_gone_error (GError **error)
+{
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_DBUS_ERROR, _("D-Bus book proxy gone"));
+}
+
+static guint active_book_clients = 0, book_connection_closed_id = 0;
+static EGdbusBookFactory *book_factory_proxy = NULL;
+static GStaticRecMutex book_factory_proxy_lock = G_STATIC_REC_MUTEX_INIT;
+#define LOCK_FACTORY() g_static_rec_mutex_lock (&book_factory_proxy_lock)
+#define UNLOCK_FACTORY() g_static_rec_mutex_unlock (&book_factory_proxy_lock)
+
+static void gdbus_book_factory_proxy_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, gpointer user_data);
+
+static void
+gdbus_book_factory_proxy_disconnect (GDBusConnection *connection)
+{
+ LOCK_FACTORY ();
+
+ if (!connection && book_factory_proxy)
+ connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy));
+
+ if (connection && book_connection_closed_id) {
+ g_dbus_connection_signal_unsubscribe (connection, book_connection_closed_id);
+ g_signal_handlers_disconnect_by_func (connection, gdbus_book_factory_proxy_closed_cb, NULL);
+ }
+
+ if (book_factory_proxy)
+ g_object_unref (book_factory_proxy);
+
+ book_connection_closed_id = 0;
+ book_factory_proxy = NULL;
+
+ UNLOCK_FACTORY ();
+}
+
+static void
+gdbus_book_factory_proxy_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, gpointer user_data)
+{
+ GError *err = NULL;
+
+ LOCK_FACTORY ();
+
+ gdbus_book_factory_proxy_disconnect (connection);
+
+ if (error)
+ unwrap_dbus_error (g_error_copy (error), &err);
+
+ if (err) {
+ g_debug ("GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
+ g_error_free (err);
+ } else if (active_book_clients) {
+ g_debug ("GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
+ }
+
+ UNLOCK_FACTORY ();
+}
+
+static void
+gdbus_book_factory_connection_gone_cb (GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data)
+{
+ /* signal subscription takes care of correct parameters,
+ thus just do what is to be done here */
+ gdbus_book_factory_proxy_closed_cb (connection, TRUE, NULL, user_data);
+}
+
+static gboolean
+gdbus_book_factory_activate (GError **error)
+{
+ GDBusConnection *connection;
+
+ LOCK_FACTORY ();
+
+ if (G_LIKELY (book_factory_proxy)) {
+ UNLOCK_FACTORY ();
+ return TRUE;
+ }
+
+ book_factory_proxy = e_gdbus_book_factory_proxy_new_for_bus_sync (
+ G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ ADDRESS_BOOK_DBUS_SERVICE_NAME,
+ "/org/gnome/evolution/dataserver/AddressBookFactory",
+ NULL,
+ error);
+
+ if (!book_factory_proxy) {
+ UNLOCK_FACTORY ();
+ return FALSE;
+ }
+
+ connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy));
+ book_connection_closed_id = g_dbus_connection_signal_subscribe (connection,
+ NULL, /* sender */
+ "org.freedesktop.DBus", /* interface */
+ "NameOwnerChanged", /* member */
+ "/org/freedesktop/DBus", /* object_path */
+ "org.gnome.evolution.dataserver.AddressBook", /* arg0 */
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ gdbus_book_factory_connection_gone_cb, NULL, NULL);
+
+ g_signal_connect (connection, "closed", G_CALLBACK (gdbus_book_factory_proxy_closed_cb), NULL);
+
+ UNLOCK_FACTORY ();
+
+ return TRUE;
+}
+
+static void gdbus_book_client_disconnect (EBookClient *client);
+
+/*
+ * Called when the addressbook server dies.
+ */
+static void
+gdbus_book_client_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, EBookClient *client)
+{
+ GError *err = NULL;
+
+ g_assert (E_IS_BOOK_CLIENT (client));
+
+ if (error)
+ unwrap_dbus_error (g_error_copy (error), &err);
+
+ if (err) {
+ g_debug (G_STRLOC ": EBookClient GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
+ g_error_free (err);
+ } else {
+ g_debug (G_STRLOC ": EBookClient GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
+ }
+
+ gdbus_book_client_disconnect (client);
+
+ e_client_emit_backend_died (E_CLIENT (client));
+}
+
+static void
+gdbus_book_client_connection_gone_cb (GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data)
+{
+ /* signal subscription takes care of correct parameters,
+ thus just do what is to be done here */
+ gdbus_book_client_closed_cb (connection, TRUE, NULL, user_data);
+}
+
+static void
+gdbus_book_client_disconnect (EBookClient *client)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_BOOK_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+
+ /* Ensure that everything relevant is NULL */
+ LOCK_FACTORY ();
+
+ if (client->priv->gdbus_book) {
+ GDBusConnection *connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (client->priv->gdbus_book));
+
+ g_signal_handlers_disconnect_by_func (connection, gdbus_book_client_closed_cb, client);
+ g_dbus_connection_signal_unsubscribe (connection, client->priv->gone_signal_id);
+ client->priv->gone_signal_id = 0;
+
+ e_gdbus_book_call_close_sync (client->priv->gdbus_book, NULL, NULL);
+ g_object_unref (client->priv->gdbus_book);
+ client->priv->gdbus_book = NULL;
+ }
+
+ UNLOCK_FACTORY ();
+}
+
+static void
+backend_error_cb (EGdbusBook *object, const gchar *message, EBookClient *client)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_BOOK_CLIENT (client));
+ g_return_if_fail (message != NULL);
+
+ e_client_emit_backend_error (E_CLIENT (client), message);
+}
+
+static void
+readonly_cb (EGdbusBook *object, gboolean readonly, EBookClient *client)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_BOOK_CLIENT (client));
+
+ e_client_set_readonly (E_CLIENT (client), readonly);
+}
+
+static void
+online_cb (EGdbusBook *object, gboolean is_online, EBookClient *client)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_BOOK_CLIENT (client));
+
+ e_client_set_online (E_CLIENT (client), is_online);
+}
+
+static void
+auth_required_cb (EGdbusBook *object, const gchar * const *credentials_strv, EBookClient *client)
+{
+ ECredentials *credentials;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_BOOK_CLIENT (client));
+
+ if (credentials_strv)
+ credentials = e_credentials_new_strv (credentials_strv);
+ else
+ credentials = e_credentials_new ();
+
+ e_client_process_authentication (E_CLIENT (client), credentials);
+
+ e_credentials_free (credentials);
+}
+
+static void
+opened_cb (EGdbusBook *object, const gchar * const *error_strv, EBookClient *client)
+{
+ GError *error = NULL;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_BOOK_CLIENT (client));
+ g_return_if_fail (error_strv != NULL);
+ g_return_if_fail (e_gdbus_templates_decode_error (error_strv, &error));
+
+ e_client_emit_opened (E_CLIENT (client), error);
+
+ if (error)
+ g_error_free (error);
+}
+
+/**
+ * e_book_client_new:
+ * @source: An #ESource pointer
+ * @error: A #GError pointer
+ *
+ * Creates a new #EBookClient corresponding to the given source. There are
+ * only two operations that are valid on this book at this point:
+ * e_client_open(), and e_client_remove().
+ *
+ * Returns: a new but unopened #EBookClient.
+ *
+ * Since: 3.2
+ **/
+EBookClient *
+e_book_client_new (ESource *source, GError **error)
+{
+ EBookClient *client;
+ GError *err = NULL;
+ GDBusConnection *connection;
+ gchar *xml, *gdbus_xml = NULL;
+ gchar *path = NULL;
+
+ g_return_val_if_fail (source != NULL, NULL);
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ if (!gdbus_book_factory_activate (&err)) {
+ if (err) {
+ unwrap_dbus_error (err, &err);
+ g_warning ("%s: Failed to run book factory: %s", G_STRFUNC, err->message);
+ g_propagate_error (error, err);
+ } else {
+ g_warning ("%s: Failed to run book factory: Unknown error", G_STRFUNC);
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_DBUS_ERROR, _("Failed to run book factory"));
+ }
+
+ return NULL;
+ }
+
+ xml = e_source_to_standalone_xml (source);
+ if (!xml || !*xml) {
+ g_free (xml);
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG, _("Invalid source"));
+ return NULL;
+ }
+
+ client = g_object_new (E_TYPE_BOOK_CLIENT, "source", source, NULL);
+
+ if (!e_gdbus_book_factory_call_get_book_sync (G_DBUS_PROXY (book_factory_proxy), e_util_ensure_gdbus_string (xml, &gdbus_xml), &path, NULL, &err)) {
+ unwrap_dbus_error (err, &err);
+ g_free (xml);
+ g_free (gdbus_xml);
+ g_warning ("%s: Cannot get book from factory: %s", G_STRFUNC, err ? err->message : "[no error]");
+ if (err)
+ g_propagate_error (error, err);
+ g_object_unref (client);
+
+ return NULL;
+ }
+
+ g_free (xml);
+ g_free (gdbus_xml);
+
+ client->priv->gdbus_book = G_DBUS_PROXY (e_gdbus_book_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy)),
+ G_DBUS_PROXY_FLAGS_NONE,
+ ADDRESS_BOOK_DBUS_SERVICE_NAME,
+ path,
+ NULL,
+ &err));
+
+ if (!client->priv->gdbus_book) {
+ g_free (path);
+ unwrap_dbus_error (err, &err);
+ g_warning ("%s: Cannot create cal proxy: %s", G_STRFUNC, err ? err->message : "Unknown error");
+ if (err)
+ g_propagate_error (error, err);
+
+ g_object_unref (client);
+
+ return NULL;
+ }
+
+ g_free (path);
+
+ connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (client->priv->gdbus_book));
+ client->priv->gone_signal_id = g_dbus_connection_signal_subscribe (connection,
+ "org.freedesktop.DBus", /* sender */
+ "org.freedesktop.DBus", /* interface */
+ "NameOwnerChanged", /* member */
+ "/org/freedesktop/DBus", /* object_path */
+ "org.gnome.evolution.dataserver.AddressBook", /* arg0 */
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ gdbus_book_client_connection_gone_cb, client, NULL);
+
+ g_signal_connect (connection, "closed", G_CALLBACK (gdbus_book_client_closed_cb), client);
+
+ g_signal_connect (client->priv->gdbus_book, "backend_error", G_CALLBACK (backend_error_cb), client);
+ g_signal_connect (client->priv->gdbus_book, "readonly", G_CALLBACK (readonly_cb), client);
+ g_signal_connect (client->priv->gdbus_book, "online", G_CALLBACK (online_cb), client);
+ g_signal_connect (client->priv->gdbus_book, "auth-required", G_CALLBACK (auth_required_cb), client);
+ g_signal_connect (client->priv->gdbus_book, "opened", G_CALLBACK (opened_cb), client);
+
+ return client;
+}
+
+/**
+ * e_book_client_new_from_uri:
+ * @uri: the URI to load
+ * @error: A #GError pointer
+ *
+ * Creates a new #EBookClient corresponding to the given uri. See the
+ * documentation for e_book_client_new() for further information.
+ *
+ * Returns: a new but unopened #EBookClient.
+ *
+ * Since: 3.2
+ **/
+EBookClient *
+e_book_client_new_from_uri (const gchar *uri, GError **error)
+{
+ ESourceList *source_list = NULL;
+ ESource *source;
+ EBookClient *client;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ if (!e_book_client_get_sources (&source_list, error))
+ return NULL;
+
+ source = e_client_util_get_source_for_uri (source_list, uri);
+ if (!source && g_str_has_prefix (uri, "file://")) {
+ gchar *local_uri;
+
+ local_uri = g_strconcat ("local://", uri + 7, NULL);
+ source = e_client_util_get_source_for_uri (source_list, uri);
+
+ g_free (local_uri);
+ }
+
+ if (!source) {
+ g_object_unref (source_list);
+ g_set_error (error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG, _("Incorrect uri '%s'"), uri);
+
+ return NULL;
+ }
+
+ client = e_book_client_new (source, error);
+
+ g_object_unref (source);
+ g_object_unref (source_list);
+
+ return client;
+}
+
+/**
+ * e_book_client_new_system:
+ * @error: A #GError pointer
+ *
+ * Creates a new #EBookClient corresponding to the user's system
+ * addressbook. See the documentation for e_book_client_new() for further
+ * information.
+ *
+ * Returns: a new but unopened #EBookClient.
+ *
+ * Since: 3.2
+ **/
+EBookClient *
+e_book_client_new_system (GError **error)
+{
+ ESourceList *source_list = NULL;
+ ESource *source;
+ EBookClient *client;
+
+ if (!e_book_client_get_sources (&source_list, error))
+ return NULL;
+
+ source = e_client_util_get_system_source (source_list);
+ if (!source) {
+ g_object_unref (source_list);
+ g_set_error_literal (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE, _("Failed to find system book"));
+
+ return NULL;
+ }
+
+ client = e_book_client_new (source, error);
+
+ g_object_unref (source);
+ g_object_unref (source_list);
+
+ return client;
+}
+
+/**
+ * e_book_client_new_default:
+ * @error: return location for a #GError, or %NULL
+ *
+ * Creates a new #EBookClient corresponding to the user's default
+ * address book. See the documentation for e_book_client_new() for
+ * further information.
+ *
+ * Returns: a new but unopened #EBookClient
+ *
+ * Since: 3.2
+ **/
+EBookClient *
+e_book_client_new_default (GError **error)
+{
+ ESourceList *source_list = NULL;
+ ESource *source;
+ EBookClient *client;
+
+ if (!e_book_client_get_sources (&source_list, error))
+ return NULL;
+
+ source = e_source_list_peek_default_source (source_list);
+ if (!source) {
+ g_set_error_literal (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK, _("Address book does not exist"));
+ g_object_unref (source_list);
+
+ return NULL;
+ }
+
+ client = e_book_client_new (source, error);
+
+ g_object_unref (source_list);
+
+ return client;
+}
+
+/**
+ * e_book_client_set_default:
+ * @client: An #EBookClient pointer
+ * @error: A #GError pointer
+ *
+ * Sets the #ESource of the #EBookClient as the "default" addressbook. This is the source
+ * that will be loaded in the e_book_client_get_default_addressbook() call.
+ *
+ * Returns: %TRUE if the setting was stored in libebook's ESourceList, otherwise %FALSE.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_set_default (EBookClient *client, GError **error)
+{
+ ESource *source;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+
+ source = e_client_get_source (E_CLIENT (client));
+ g_return_val_if_fail (source != NULL, FALSE);
+
+ return e_book_client_set_default_source (source, error);
+}
+
+/**
+ * e_book_client_set_default_source:
+ * @source: An #ESource pointer
+ * @error: A #GError pointer
+ *
+ * Sets @source as the "default" addressbook. This is the source that
+ * will be loaded in the e_book_client_get_default_addressbook() call.
+ *
+ * Returns: %TRUE if the setting was stored in libebook's ESourceList, otherwise %FALSE.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_set_default_source (ESource *source, GError **error)
+{
+ ESourceList *source_list = NULL;
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (source != NULL, FALSE);
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+ if (!e_book_client_get_sources (&source_list, error))
+ return FALSE;
+
+ res = e_client_util_set_default (source_list, source);
+
+ if (res)
+ res = e_source_list_sync (source_list, error);
+ else
+ g_set_error (error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG,
+ _("There was no source for UID '%s' stored in a source list."), e_source_peek_uid (source));
+
+ g_object_unref (source_list);
+
+ return res;
+}
+
+/**
+ * e_book_client_get_sources:
+ * @sources: (out): A pointer to an #ESourceList to set
+ * @error: A pointer to a GError to set on error
+ *
+ * Populate @*sources with the list of all sources which have been
+ * added to Evolution.
+ *
+ * Returns: %TRUE if @sources was set, otherwise %FALSE.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_get_sources (ESourceList **sources, GError **error)
+{
+ GConfClient *gconf;
+
+ g_return_val_if_fail (sources != NULL, FALSE);
+
+ gconf = gconf_client_get_default ();
+ *sources = e_source_list_new_for_gconf (gconf, "/apps/evolution/addressbook/sources");
+ g_object_unref (gconf);
+
+ return TRUE;
+}
+
+#define SELF_UID_KEY "/apps/evolution/addressbook/self/self_uid"
+
+static EContact *
+make_me_card (void)
+{
+ GString *vcard;
+ const gchar *s;
+ EContact *contact;
+
+ vcard = g_string_new ("BEGIN:VCARD\nVERSION:3.0\n");
+
+ s = g_get_user_name ();
+ if (s)
+ g_string_append_printf (vcard, "NICKNAME:%s\n", s);
+
+ s = g_get_real_name ();
+ if (s && strcmp (s, "Unknown") != 0) {
+ ENameWestern *western;
+
+ g_string_append_printf (vcard, "FN:%s\n", s);
+
+ western = e_name_western_parse (s);
+ g_string_append_printf (vcard, "N:%s;%s;%s;%s;%s\n",
+ western->last ? western->last : "",
+ western->first ? western->first : "",
+ western->middle ? western->middle : "",
+ western->prefix ? western->prefix : "",
+ western->suffix ? western->suffix : "");
+ e_name_western_free (western);
+ }
+ g_string_append (vcard, "END:VCARD");
+
+ contact = e_contact_new_from_vcard (vcard->str);
+
+ g_string_free (vcard, TRUE);
+
+ return contact;
+}
+
+/**
+ * e_book_client_get_self:
+ * @contact: an #EContact pointer to set
+ * @client: an #EBookClient pointer to set
+ * @error: a #GError to set on failure
+ *
+ * Get the #EContact referring to the user of the address book
+ * and set it in @contact and @client.
+ *
+ * Returns: %TRUE if successful, otherwise %FALSE.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_get_self (EContact **contact, EBookClient **client, GError **error)
+{
+ GError *local_error = NULL;
+ GConfClient *gconf;
+ gchar *uid;
+
+ g_return_val_if_fail (contact != NULL, FALSE);
+ g_return_val_if_fail (client != NULL, FALSE);
+
+ *client = e_book_client_new_system (&local_error);
+ if (!*client) {
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
+
+ if (!e_client_open_sync (E_CLIENT (*client), FALSE, NULL, &local_error)) {
+ g_object_unref (*client);
+ *client = NULL;
+ g_propagate_error (error, local_error);
+
+ return FALSE;
+ }
+
+ gconf = gconf_client_get_default ();
+ uid = gconf_client_get_string (gconf, SELF_UID_KEY, NULL);
+ g_object_unref (gconf);
+
+ if (uid) {
+ gboolean got;
+
+ /* Don't care about errors because we'll create a new card on failure */
+ got = e_book_client_get_contact_sync (*client, uid, contact, NULL, NULL);
+ g_free (uid);
+ if (got)
+ return TRUE;
+ }
+
+ uid = NULL;
+ *contact = make_me_card ();
+ if (!e_book_client_add_contact_sync (*client, *contact, &uid, NULL, &local_error)) {
+ g_object_unref (*client);
+ *client = NULL;
+ g_object_unref (*contact);
+ *contact = NULL;
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
+
+ if (uid) {
+ e_contact_set (*contact, E_CONTACT_UID, uid);
+ g_free (uid);
+ }
+
+ e_book_client_set_self (*client, *contact, NULL);
+
+ return TRUE;
+}
+
+/**
+ * e_book_client_set_self:
+ * @client: an #EBookClient
+ * @contact: an #EContact
+ * @error: a #GError to set on failure
+ *
+ * Specify that @contact residing in @client is the #EContact that
+ * refers to the user of the address book.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_set_self (EBookClient *client, EContact *contact, GError **error)
+{
+ GConfClient *gconf;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (contact != NULL, FALSE);
+ g_return_val_if_fail (e_contact_get_const (contact, E_CONTACT_UID) != NULL, FALSE);
+
+ gconf = gconf_client_get_default ();
+ gconf_client_set_string (gconf, SELF_UID_KEY, e_contact_get_const (contact, E_CONTACT_UID), NULL);
+ g_object_unref (gconf);
+
+ return TRUE;
+}
+
+/**
+ * e_book_client_is_self:
+ * @contact: an #EContact
+ *
+ * Check if @contact is the user of the address book.
+ *
+ * Returns: %TRUE if @contact is the user, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_is_self (EContact *contact)
+{
+ GConfClient *gconf;
+ gchar *uid;
+ gboolean is_self;
+
+ g_return_val_if_fail (contact && E_IS_CONTACT (contact), FALSE);
+
+ gconf = gconf_client_get_default ();
+ uid = gconf_client_get_string (gconf, SELF_UID_KEY, NULL);
+ g_object_unref (gconf);
+
+ is_self = uid && !g_strcmp0 (uid, e_contact_get_const (contact, E_CONTACT_UID));
+
+ g_free (uid);
+
+ return is_self;
+}
+
+static void
+book_client_get_backend_property (EClient *client, const gchar *prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_client_proxy_call_string (client, prop_name, cancellable, callback, user_data, book_client_get_backend_property,
+ e_gdbus_book_call_get_backend_property,
+ NULL, NULL, e_gdbus_book_call_get_backend_property_finish, NULL, NULL);
+}
+
+static gboolean
+book_client_get_backend_property_finish (EClient *client, GAsyncResult *result, gchar **prop_value, GError **error)
+{
+ return e_client_proxy_call_finish_string (client, result, prop_value, error, book_client_get_backend_property);
+}
+
+static gboolean
+book_client_get_backend_property_sync (EClient *client, const gchar *prop_name, gchar **prop_value, GCancellable *cancellable, GError **error)
+{
+ EBookClient *book_client;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+
+ book_client = E_BOOK_CLIENT (client);
+ g_return_val_if_fail (book_client != NULL, FALSE);
+ g_return_val_if_fail (book_client->priv != NULL, FALSE);
+
+ if (!book_client->priv->gdbus_book) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ return e_client_proxy_call_sync_string__string (client, prop_name, prop_value, cancellable, error, e_gdbus_book_call_get_backend_property_sync);
+}
+
+static void
+book_client_set_backend_property (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar **prop_name_value;
+
+ prop_name_value = e_gdbus_book_encode_set_backend_property (prop_name, prop_value);
+
+ e_client_proxy_call_strv (client, (const gchar * const *) prop_name_value, cancellable, callback, user_data, book_client_set_backend_property,
+ e_gdbus_book_call_set_backend_property,
+ e_gdbus_book_call_set_backend_property_finish, NULL, NULL, NULL, NULL);
+
+ g_strfreev (prop_name_value);
+}
+
+static gboolean
+book_client_set_backend_property_finish (EClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (client, result, error, book_client_set_backend_property);
+}
+
+static gboolean
+book_client_set_backend_property_sync (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GError **error)
+{
+ EBookClient *book_client;
+ gboolean res;
+ gchar **prop_name_value;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+
+ book_client = E_BOOK_CLIENT (client);
+ g_return_val_if_fail (book_client != NULL, FALSE);
+ g_return_val_if_fail (book_client->priv != NULL, FALSE);
+
+ if (!book_client->priv->gdbus_book) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ prop_name_value = e_gdbus_book_encode_set_backend_property (prop_name, prop_value);
+ res = e_client_proxy_call_sync_strv__void (client, (const gchar * const *) prop_name_value, cancellable, error, e_gdbus_book_call_set_backend_property_sync);
+ g_strfreev (prop_name_value);
+
+ return res;
+}
+
+static void
+book_client_open (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_client_proxy_call_boolean (client, only_if_exists, cancellable, callback, user_data, book_client_open,
+ e_gdbus_book_call_open,
+ e_gdbus_book_call_open_finish, NULL, NULL, NULL, NULL);
+}
+
+static gboolean
+book_client_open_finish (EClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (client, result, error, book_client_open);
+}
+
+static gboolean
+book_client_open_sync (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error)
+{
+ EBookClient *book_client;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+
+ book_client = E_BOOK_CLIENT (client);
+ g_return_val_if_fail (book_client != NULL, FALSE);
+ g_return_val_if_fail (book_client->priv != NULL, FALSE);
+
+ if (!book_client->priv->gdbus_book) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ return e_client_proxy_call_sync_boolean__void (client, only_if_exists, cancellable, error, e_gdbus_book_call_open_sync);
+}
+
+static void
+book_client_remove (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_client_proxy_call_void (client, cancellable, callback, user_data, book_client_remove,
+ e_gdbus_book_call_remove,
+ e_gdbus_book_call_remove_finish, NULL, NULL, NULL, NULL);
+}
+
+static gboolean
+book_client_remove_finish (EClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (client, result, error, book_client_remove);
+}
+
+static gboolean
+book_client_remove_sync (EClient *client, GCancellable *cancellable, GError **error)
+{
+ EBookClient *book_client;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+
+ book_client = E_BOOK_CLIENT (client);
+ g_return_val_if_fail (book_client != NULL, FALSE);
+ g_return_val_if_fail (book_client->priv != NULL, FALSE);
+
+ if (!book_client->priv->gdbus_book) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ return e_client_proxy_call_sync_void__void (client, cancellable, error, e_gdbus_book_call_remove_sync);
+}
+
+static void
+book_client_refresh (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_client_proxy_call_void (client, cancellable, callback, user_data, book_client_refresh,
+ e_gdbus_book_call_refresh,
+ e_gdbus_book_call_refresh_finish, NULL, NULL, NULL, NULL);
+}
+
+static gboolean
+book_client_refresh_finish (EClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (client, result, error, book_client_refresh);
+}
+
+static gboolean
+book_client_refresh_sync (EClient *client, GCancellable *cancellable, GError **error)
+{
+ EBookClient *book_client;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+
+ book_client = E_BOOK_CLIENT (client);
+ g_return_val_if_fail (book_client != NULL, FALSE);
+ g_return_val_if_fail (book_client->priv != NULL, FALSE);
+
+ if (!book_client->priv->gdbus_book) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ return e_client_proxy_call_sync_void__void (client, cancellable, error, e_gdbus_book_call_refresh_sync);
+}
+
+/**
+ * e_book_client_add_contact:
+ * @client: an #EBookClient
+ * @contact: an #EContact
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Adds @contact to @client.
+ * The call is finished by e_book_client_add_contact_finish()
+ * from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_book_client_add_contact (EBookClient *client, /* const */ EContact *contact, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *vcard, *gdbus_vcard = NULL;
+
+ g_return_if_fail (contact != NULL);
+ g_return_if_fail (E_IS_CONTACT (contact));
+
+ vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+
+ e_client_proxy_call_string (E_CLIENT (client), e_util_ensure_gdbus_string (vcard, &gdbus_vcard), cancellable, callback, user_data, e_book_client_add_contact,
+ e_gdbus_book_call_add_contact,
+ NULL, NULL, e_gdbus_book_call_add_contact_finish, NULL, NULL);
+
+ g_free (vcard);
+ g_free (gdbus_vcard);
+}
+
+/**
+ * e_book_client_add_contact_finish:
+ * @client: an #EBookClient
+ * @result: a #GAsyncResult
+ * @added_uid: (out): UID of a newly added contact; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_book_client_add_contact() and
+ * sets @added_uid to a UID of a newly added contact.
+ * This string should be freed with g_free().
+ *
+ * Note: This is not modifying original #EContact.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_add_contact_finish (EBookClient *client, GAsyncResult *result, gchar **added_uid, GError **error)
+{
+ gboolean res;
+ gchar *out_uid = NULL;
+
+ res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &out_uid, error, e_book_client_add_contact);
+
+ if (res && out_uid && added_uid) {
+ *added_uid = out_uid;
+ } else {
+ g_free (out_uid);
+ if (added_uid)
+ *added_uid = NULL;
+ }
+
+ return res;
+}
+
+/**
+ * e_book_client_add_contact_sync:
+ * @client: an #EBookClient
+ * @contact: an #EContact
+ * @added_uid: (out): UID of a newly added contact; can be %NULL
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Adds @contact to @client and
+ * sets @added_uid to a UID of a newly added contact.
+ * This string should be freed with g_free().
+ *
+ * Note: This is not modifying original @contact, thus if it's needed,
+ * then use e_contact_set (contact, E_CONTACT_UID, new_uid).
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_add_contact_sync (EBookClient *client, /* const */ EContact *contact, gchar **added_uid, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *vcard, *gdbus_vcard = NULL, *out_uid = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+
+ if (!client->priv->gdbus_book) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+
+ res = e_client_proxy_call_sync_string__string (E_CLIENT (client), e_util_ensure_gdbus_string (vcard, &gdbus_vcard), &out_uid, cancellable, error, e_gdbus_book_call_add_contact_sync);
+
+ if (res && out_uid && added_uid) {
+ *added_uid = out_uid;
+ } else {
+ g_free (out_uid);
+ if (added_uid)
+ *added_uid = NULL;
+ }
+
+ g_free (vcard);
+ g_free (gdbus_vcard);
+
+ return res;
+}
+
+/**
+ * e_book_client_modify_contact:
+ * @client: an #EBookClient
+ * @contact: an #EContact
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Applies the changes made to @contact to the stored version in @client.
+ * The call is finished by e_book_client_modify_contact_finish()
+ * from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_book_client_modify_contact (EBookClient *client, /* const */ EContact *contact, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *vcard, *gdbus_vcard = NULL;
+
+ g_return_if_fail (contact != NULL);
+ g_return_if_fail (E_IS_CONTACT (contact));
+
+ vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+
+ e_client_proxy_call_string (E_CLIENT (client), e_util_ensure_gdbus_string (vcard, &gdbus_vcard), cancellable, callback, user_data, e_book_client_modify_contact,
+ e_gdbus_book_call_modify_contact,
+ e_gdbus_book_call_modify_contact_finish, NULL, NULL, NULL, NULL);
+
+ g_free (vcard);
+ g_free (gdbus_vcard);
+}
+
+/**
+ * e_book_client_modify_contact_finish:
+ * @client: an #EBookClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_book_client_modify_contact().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_modify_contact_finish (EBookClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_book_client_modify_contact);
+}
+
+/**
+ * e_book_client_modify_contact_sync:
+ * @client: an #EBookClient
+ * @contact: an #EContact
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Applies the changes made to @contact to the stored version in @client.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_modify_contact_sync (EBookClient *client, /* const */ EContact *contact, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *vcard, *gdbus_vcard = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+
+ if (!client->priv->gdbus_book) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+
+ res = e_client_proxy_call_sync_string__void (E_CLIENT (client), e_util_ensure_gdbus_string (vcard, &gdbus_vcard), cancellable, error, e_gdbus_book_call_modify_contact_sync);
+
+ g_free (vcard);
+ g_free (gdbus_vcard);
+
+ return res;
+}
+
+/**
+ * e_book_client_remove_contact:
+ * @client: an #EBookClient
+ * @contact: an #EContact
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Removes @contact from the @client.
+ * The call is finished by e_book_client_remove_contact_finish()
+ * from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_book_client_remove_contact (EBookClient *client, /* const */ EContact *contact, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *uid;
+ const gchar *lst[2];
+
+ g_return_if_fail (contact != NULL);
+ g_return_if_fail (E_IS_CONTACT (contact));
+
+ uid = e_util_utf8_make_valid (e_contact_get_const ((EContact *) contact, E_CONTACT_UID));
+ g_return_if_fail (uid != NULL);
+
+ lst[0] = uid;
+ lst[1] = NULL;
+
+ e_client_proxy_call_strv (E_CLIENT (client), lst, cancellable, callback, user_data, e_book_client_remove_contact,
+ e_gdbus_book_call_remove_contacts,
+ e_gdbus_book_call_remove_contacts_finish, NULL, NULL, NULL, NULL);
+
+ g_free (uid);
+}
+
+/**
+ * e_book_client_remove_contact_finish:
+ * @client: an #EBookClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_book_client_remove_contact().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_remove_contact_finish (EBookClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_book_client_remove_contact);
+}
+
+/**
+ * e_book_client_remove_contact_sync:
+ * @client: an #EBookClient
+ * @contact: an #EContact
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Removes @contact from the @client.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_remove_contact_sync (EBookClient *client, /* const */ EContact *contact, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *uid;
+ const gchar *lst[2];
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (contact != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
+
+ if (!client->priv->gdbus_book) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ uid = e_util_utf8_make_valid (e_contact_get_const ((EContact *) contact, E_CONTACT_UID));
+ g_return_val_if_fail (uid != NULL, 0);
+
+ lst[0] = uid;
+ lst[1] = NULL;
+
+ res = e_client_proxy_call_sync_strv__void (E_CLIENT (client), lst, cancellable, error, e_gdbus_book_call_remove_contacts_sync);
+
+ g_free (uid);
+
+ return res;
+}
+
+/**
+ * e_book_client_remove_contact_by_uid:
+ * @client: an #EBookClient
+ * @uid: a UID of a contact to remove
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Removes contact with @uid from the @client.
+ * The call is finished by e_book_client_remove_contact_by_uid_finish()
+ * from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_book_client_remove_contact_by_uid (EBookClient *client, const gchar *uid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *safe_uid;
+ const gchar *lst[2];
+
+ g_return_if_fail (uid != NULL);
+
+ safe_uid = e_util_utf8_make_valid (uid);
+ g_return_if_fail (safe_uid != NULL);
+
+ lst[0] = safe_uid;
+ lst[1] = NULL;
+
+ e_client_proxy_call_strv (E_CLIENT (client), lst, cancellable, callback, user_data, e_book_client_remove_contact_by_uid,
+ e_gdbus_book_call_remove_contacts,
+ e_gdbus_book_call_remove_contacts_finish, NULL, NULL, NULL, NULL);
+
+ g_free (safe_uid);
+}
+
+/**
+ * e_book_client_remove_contact_by_uid_finish:
+ * @client: an #EBookClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_book_client_remove_contact_by_uid().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_remove_contact_by_uid_finish (EBookClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_book_client_remove_contact_by_uid);
+}
+
+/**
+ * e_book_client_remove_contact_by_uid_sync:
+ * @client: an #EBookClient
+ * @uid: a UID of a contact to remove
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Removes contact with @uid from the @client.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_remove_contact_by_uid_sync (EBookClient *client, const gchar *uid, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *safe_uid;
+ const gchar *lst[2];
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+
+ if (!client->priv->gdbus_book) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ safe_uid = e_util_utf8_make_valid (uid);
+ g_return_val_if_fail (safe_uid != NULL, FALSE);
+
+ lst[0] = safe_uid;
+ lst[1] = NULL;
+
+ res = e_client_proxy_call_sync_strv__void (E_CLIENT (client), lst, cancellable, error, e_gdbus_book_call_remove_contacts_sync);
+
+ g_free (safe_uid);
+
+ return res;
+}
+
+/**
+ * e_book_client_remove_contacts:
+ * @client: an #EBookClient
+ * @uids: a #GSList of UIDs to remove
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Removes the contacts with uids from the list @uids from @client. This is
+ * always more efficient than calling e_book_client_remove_contact() if you
+ * have more than one uid to remove, as some backends can implement it
+ * as a batch request.
+ * The call is finished by e_book_client_remove_contacts_finish()
+ * from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_book_client_remove_contacts (EBookClient *client, const GSList *uids, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar **lst;
+
+ g_return_if_fail (uids != NULL);
+
+ lst = e_client_util_slist_to_strv (uids);
+ g_return_if_fail (lst != NULL);
+
+ e_client_proxy_call_strv (E_CLIENT (client), (const gchar * const *) lst, cancellable, callback, user_data, e_book_client_remove_contacts,
+ e_gdbus_book_call_remove_contacts,
+ e_gdbus_book_call_remove_contacts_finish, NULL, NULL, NULL, NULL);
+
+ g_strfreev (lst);
+}
+
+/**
+ * e_book_client_remove_contacts_finish:
+ * @client: an #EBookClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_book_client_remove_contacts().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_remove_contacts_finish (EBookClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_book_client_remove_contacts);
+}
+
+/**
+ * e_book_client_remove_contacts_sync:
+ * @client: an #EBookClient
+ * @uids: a #GSList of UIDs to remove
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Removes the contacts with uids from the list @uids from @client. This is
+ * always more efficient than calling e_book_client_remove_contact() if you
+ * have more than one uid to remove, as some backends can implement it
+ * as a batch request.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_remove_contacts_sync (EBookClient *client, const GSList *uids, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar **lst;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (uids != NULL, FALSE);
+
+ if (!client->priv->gdbus_book) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ lst = e_client_util_slist_to_strv (uids);
+ g_return_val_if_fail (lst != NULL, FALSE);
+
+ res = e_client_proxy_call_sync_strv__void (E_CLIENT (client), (const gchar * const *) lst, cancellable, error, e_gdbus_book_call_remove_contacts_sync);
+
+ g_strfreev (lst);
+
+ return res;
+}
+
+/**
+ * e_book_client_get_contact:
+ * @client: an #EBookClient
+ * @uid: a unique string ID specifying the contact
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Receive #EContact from the @client for the gived @uid.
+ * The call is finished by e_book_client_get_contact_finish()
+ * from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_book_client_get_contact (EBookClient *client, const gchar *uid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *safe_uid;
+
+ g_return_if_fail (uid != NULL);
+
+ safe_uid = e_util_utf8_make_valid (uid);
+ g_return_if_fail (safe_uid != NULL);
+
+ e_client_proxy_call_string (E_CLIENT (client), safe_uid, cancellable, callback, user_data, e_book_client_get_contact,
+ e_gdbus_book_call_get_contact,
+ NULL, NULL, e_gdbus_book_call_get_contact_finish, NULL, NULL);
+
+ g_free (safe_uid);
+}
+
+/**
+ * e_book_client_get_contact_finish:
+ * @client: an #EBookClient
+ * @result: a #GAsyncResult
+ * @contact: (out) an #EContact for previously given uid
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_book_client_get_contact().
+ * If successful, then the @contact is set to newly allocated
+ * #EContact, which should be freed with g_object_unref().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_get_contact_finish (EBookClient *client, GAsyncResult *result, EContact **contact, GError **error)
+{
+ gboolean res;
+ gchar *vcard = NULL;
+
+ g_return_val_if_fail (contact != NULL, FALSE);
+
+ res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &vcard, error, e_book_client_get_contact);
+
+ if (vcard && res)
+ *contact = e_contact_new_from_vcard (vcard);
+ else
+ *contact = NULL;
+
+ g_free (vcard);
+
+ return res;
+}
+
+/**
+ * e_book_client_get_contact_sync:
+ * @client: an #EBookClient
+ * @uid: a unique string ID specifying the contact
+ * @contact: (out) an #EContact for given @uid
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Receive #EContact from the @client for the gived @uid.
+ * If successful, then the @contact is set to newly allocated
+ * #EContact, which should be freed with g_object_unref().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_get_contact_sync (EBookClient *client, const gchar *uid, EContact **contact, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *vcard = NULL, *safe_uid;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+ g_return_val_if_fail (contact != NULL, FALSE);
+
+ if (!client->priv->gdbus_book) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ safe_uid = e_util_utf8_make_valid (uid);
+ g_return_val_if_fail (safe_uid != NULL, FALSE);
+
+ res = e_client_proxy_call_sync_string__string (E_CLIENT (client), safe_uid, &vcard, cancellable, error, e_gdbus_book_call_get_contact_sync);
+
+ if (vcard && res)
+ *contact = e_contact_new_from_vcard (vcard);
+ else
+ *contact = NULL;
+
+ g_free (safe_uid);
+ g_free (vcard);
+
+ return res;
+}
+
+/**
+ * e_book_client_get_contacts:
+ * @client: an #EBookClient
+ * @sexp: an S-expression representing the query
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Query @client with @sexp, receiving a list of contacts which
+ * matched. The call is finished by e_book_client_get_contacts_finish()
+ * from the @callback.
+ *
+ * Note: @sexp can be obtained through #EBookQuery, by converting it
+ * to a string with e_book_query_to_string().
+ *
+ * Since: 3.2
+ **/
+void
+e_book_client_get_contacts (EBookClient *client, const gchar *sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *gdbus_sexp = NULL;
+
+ g_return_if_fail (sexp != NULL);
+
+ e_client_proxy_call_string (E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), cancellable, callback, user_data, e_book_client_get_contacts,
+ e_gdbus_book_call_get_contact_list,
+ NULL, NULL, NULL, e_gdbus_book_call_get_contact_list_finish, NULL);
+
+ g_free (gdbus_sexp);
+}
+
+/**
+ * e_book_client_get_contacts_finish:
+ * @client: an #EBookClient
+ * @result: a #GAsyncResult
+ * @contacts: (out) a #GSList of matched #EContact-s
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_book_client_get_contacts().
+ * If successful, then the @contacts is set to newly allocated list of #EContact-s,
+ * which should be freed with e_client_util_free_object_slist().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_get_contacts_finish (EBookClient *client, GAsyncResult *result, GSList **contacts, GError **error)
+{
+ gboolean res;
+ gchar **vcards = NULL;
+
+ g_return_val_if_fail (contacts != NULL, FALSE);
+
+ res = e_client_proxy_call_finish_strv (E_CLIENT (client), result, &vcards, error, e_book_client_get_contacts);
+
+ if (vcards && res) {
+ gint ii;
+ GSList *slist = NULL;
+
+ for (ii = 0; vcards[ii]; ii++) {
+ slist = g_slist_prepend (slist, e_contact_new_from_vcard (vcards[ii]));
+ }
+
+ *contacts = g_slist_reverse (slist);
+ } else {
+ *contacts = NULL;
+ }
+
+ g_strfreev (vcards);
+
+ return res;
+}
+
+/**
+ * e_book_client_get_contacts_sync:
+ * @client: an #EBookClient
+ * @sexp: an S-expression representing the query
+ * @contacts: (out) a #GSList of matched #EContact-s
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Query @client with @sexp, receiving a list of contacts which matched.
+ * If successful, then the @contacts is set to newly allocated #GSList of
+ * #EContact-s, which should be freed with e_client_util_free_object_slist().
+ *
+ * Note: @sexp can be obtained through #EBookQuery, by converting it
+ * to a string with e_book_query_to_string().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_get_contacts_sync (EBookClient *client, const gchar *sexp, GSList **contacts, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *gdbus_sexp = NULL;
+ gchar **vcards = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (sexp != NULL, FALSE);
+ g_return_val_if_fail (contacts != NULL, FALSE);
+
+ if (!client->priv->gdbus_book) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ res = e_client_proxy_call_sync_string__strv (E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &vcards, cancellable, error, e_gdbus_book_call_get_contact_list_sync);
+
+ if (vcards && res) {
+ gint ii;
+ GSList *slist = NULL;
+
+ for (ii = 0; vcards[ii]; ii++) {
+ slist = g_slist_prepend (slist, e_contact_new_from_vcard (vcards[ii]));
+ }
+
+ *contacts = g_slist_reverse (slist);
+ } else {
+ *contacts = NULL;
+ }
+
+ g_free (gdbus_sexp);
+ g_strfreev (vcards);
+
+ return res;
+}
+
+/**
+ * e_book_client_get_view:
+ * @client: an #EBookClient
+ * @sexp: an S-expression representing the query
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Query @client with @sexp, creating an #EBookClientView.
+ * The call is finished by e_book_client_get_view_finish()
+ * from the @callback.
+ *
+ * Note: @sexp can be obtained through #EBookQuery, by converting it
+ * to a string with e_book_query_to_string().
+ *
+ * Since: 3.2
+ **/
+void
+e_book_client_get_view (EBookClient *client, const gchar *sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *gdbus_sexp = NULL;
+
+ g_return_if_fail (sexp != NULL);
+
+ e_client_proxy_call_string (E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), cancellable, callback, user_data, e_book_client_get_view,
+ e_gdbus_book_call_get_view,
+ NULL, NULL, e_gdbus_book_call_get_view_finish, NULL, NULL);
+
+ g_free (gdbus_sexp);
+}
+
+static gboolean
+complete_get_view (EBookClient *client, gboolean res, gchar *view_path, EBookClientView **view, GError **error)
+{
+ g_return_val_if_fail (view != NULL, FALSE);
+
+ if (view_path && res && book_factory_proxy) {
+ GError *local_error = NULL;
+ EGdbusBookView *gdbus_bookview;
+
+ gdbus_bookview = e_gdbus_book_view_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy)),
+ G_DBUS_PROXY_FLAGS_NONE,
+ ADDRESS_BOOK_DBUS_SERVICE_NAME,
+ view_path,
+ NULL,
+ &local_error);
+
+ if (gdbus_bookview) {
+ *view = _e_book_client_view_new (client, gdbus_bookview);
+ g_object_unref (gdbus_bookview);
+ } else {
+ *view = NULL;
+ res = FALSE;
+ }
+
+ if (local_error)
+ unwrap_dbus_error (local_error, error);
+ } else {
+ *view = NULL;
+ res = FALSE;
+ }
+
+ if (!*view && error && !*error)
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_DBUS_ERROR, _("Cannot get connection to view"));
+
+ g_free (view_path);
+
+ return res;
+}
+
+/**
+ * e_book_client_get_view_finish:
+ * @client: an #EBookClient
+ * @result: a #GAsyncResult
+ * @view: (out) an #EBookClientView
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_book_client_get_view().
+ * If successful, then the @view is set to newly allocated #EBookClientView,
+ * which should be freed with g_object_unref().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_get_view_finish (EBookClient *client, GAsyncResult *result, EBookClientView **view, GError **error)
+{
+ gboolean res;
+ gchar *view_path = NULL;
+
+ g_return_val_if_fail (view != NULL, FALSE);
+
+ res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &view_path, error, e_book_client_get_view);
+
+ return complete_get_view (client, res, view_path, view, error);
+}
+
+/**
+ * e_book_client_get_view_sync:
+ * @client: an #EBookClient
+ * @sexp: an S-expression representing the query
+ * @view: (out) an #EBookClientView
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Query @client with @sexp, creating an #EBookClientView.
+ * If successful, then the @view is set to newly allocated #EBookClientView,
+ * which should be freed with g_object_unref().
+ *
+ * Note: @sexp can be obtained through #EBookQuery, by converting it
+ * to a string with e_book_query_to_string().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_client_get_view_sync (EBookClient *client, const gchar *sexp, EBookClientView **view, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *gdbus_sexp = NULL;
+ gchar *view_path = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (sexp != NULL, FALSE);
+ g_return_val_if_fail (view != NULL, FALSE);
+
+ if (!client->priv->gdbus_book) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ res = e_client_proxy_call_sync_string__string (E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &view_path, cancellable, error, e_gdbus_book_call_get_view_sync);
+
+ g_free (gdbus_sexp);
+
+ return complete_get_view (client, res, view_path, view, error);
+}
+
+static GDBusProxy *
+book_client_get_dbus_proxy (EClient *client)
+{
+ EBookClient *book_client;
+
+ g_return_val_if_fail (client != NULL, NULL);
+
+ book_client = E_BOOK_CLIENT (client);
+ g_return_val_if_fail (book_client != NULL, NULL);
+ g_return_val_if_fail (book_client->priv != NULL, NULL);
+
+ return book_client->priv->gdbus_book;
+}
+
+static void
+book_client_unwrap_dbus_error (EClient *client, GError *dbus_error, GError **out_error)
+{
+ unwrap_dbus_error (dbus_error, out_error);
+}
+
+static void
+book_client_handle_authentication (EClient *client, const ECredentials *credentials)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+ gchar **strv;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (credentials != NULL);
+
+ book_client = E_BOOK_CLIENT (client);
+ g_return_if_fail (book_client != NULL);
+ g_return_if_fail (book_client->priv != NULL);
+
+ if (!book_client->priv->gdbus_book)
+ return;
+
+ strv = e_credentials_to_strv (credentials);
+ g_return_if_fail (strv != NULL);
+
+ e_gdbus_book_call_authenticate_user_sync (book_client->priv->gdbus_book, (const gchar * const *) strv, NULL, &error);
+
+ g_strfreev (strv);
+
+ if (error) {
+ g_debug ("%s: Failed to authenticate user: %s", G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+}
+
+static gchar *
+book_client_retrieve_capabilities (EClient *client)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+ gchar *capabilities = NULL;
+
+ g_return_val_if_fail (client != NULL, NULL);
+
+ book_client = E_BOOK_CLIENT (client);
+ g_return_val_if_fail (book_client != NULL, NULL);
+ g_return_val_if_fail (book_client->priv != NULL, NULL);
+
+ if (!book_client->priv->gdbus_book)
+ return NULL;
+
+ e_gdbus_book_call_get_backend_property_sync (book_client->priv->gdbus_book, CLIENT_BACKEND_PROPERTY_CAPABILITIES, &capabilities, NULL, &error);
+
+ if (error) {
+ g_debug ("%s: Failed to retrieve capabilitites: %s", G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+
+ return capabilities;
+}
+
+static void
+e_book_client_init (EBookClient *client)
+{
+ LOCK_FACTORY ();
+ active_book_clients++;
+ UNLOCK_FACTORY ();
+
+ client->priv = G_TYPE_INSTANCE_GET_PRIVATE (client, E_TYPE_BOOK_CLIENT, EBookClientPrivate);
+}
+
+static void
+book_client_dispose (GObject *object)
+{
+ EClient *client;
+
+ client = E_CLIENT (object);
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (client->priv != NULL);
+
+ e_client_cancel_all (client);
+
+ gdbus_book_client_disconnect (E_BOOK_CLIENT (client));
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_book_client_parent_class)->dispose (object);
+}
+
+static void
+book_client_finalize (GObject *object)
+{
+ EBookClient *client;
+
+ client = E_BOOK_CLIENT (object);
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (client->priv != NULL);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_book_client_parent_class)->finalize (object);
+
+ LOCK_FACTORY ();
+ active_book_clients--;
+ if (!active_book_clients)
+ gdbus_book_factory_proxy_disconnect (NULL);
+ UNLOCK_FACTORY ();
+}
+
+static void
+e_book_client_class_init (EBookClientClass *klass)
+{
+ GObjectClass *object_class;
+ EClientClass *client_class;
+
+ g_type_class_add_private (klass, sizeof (EBookClientPrivate));
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = book_client_dispose;
+ object_class->finalize = book_client_finalize;
+
+ client_class = E_CLIENT_CLASS (klass);
+ client_class->get_dbus_proxy = book_client_get_dbus_proxy;
+ client_class->unwrap_dbus_error = book_client_unwrap_dbus_error;
+ client_class->handle_authentication = book_client_handle_authentication;
+ client_class->retrieve_capabilities = book_client_retrieve_capabilities;
+ client_class->get_backend_property = book_client_get_backend_property;
+ client_class->get_backend_property_finish = book_client_get_backend_property_finish;
+ client_class->get_backend_property_sync = book_client_get_backend_property_sync;
+ client_class->set_backend_property = book_client_set_backend_property;
+ client_class->set_backend_property_finish = book_client_set_backend_property_finish;
+ client_class->set_backend_property_sync = book_client_set_backend_property_sync;
+ client_class->open = book_client_open;
+ client_class->open_finish = book_client_open_finish;
+ client_class->open_sync = book_client_open_sync;
+ client_class->remove = book_client_remove;
+ client_class->remove_finish = book_client_remove_finish;
+ client_class->remove_sync = book_client_remove_sync;
+ client_class->refresh = book_client_refresh;
+ client_class->refresh_finish = book_client_refresh_finish;
+ client_class->refresh_sync = book_client_refresh_sync;
+}
diff --git a/addressbook/libebook/e-book-client.h b/addressbook/libebook/e-book-client.h
new file mode 100644
index 0000000..2bd74f5
--- /dev/null
+++ b/addressbook/libebook/e-book-client.h
@@ -0,0 +1,131 @@
+/*
+ * e-book-client.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_BOOK_CLIENT_H
+#define E_BOOK_CLIENT_H
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <libedataserver/e-client.h>
+#include <libedataserver/e-source-list.h>
+#include <libebook/e-book-client-view.h>
+#include <libebook/e-contact.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_BOOK_CLIENT (e_book_client_get_type ())
+#define E_BOOK_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_BOOK_CLIENT, EBookClient))
+#define E_BOOK_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), E_TYPE_BOOK_CLIENT, EBookClientClass))
+#define E_IS_BOOK_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_BOOK_CLIENT))
+#define E_IS_BOOK_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_BOOK_CLIENT))
+#define E_BOOK_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_BOOK_CLIENT, EBookClientClass))
+
+#define BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS "required-fields"
+#define BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS "supported-fields"
+#define BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS "supported-auth-methods"
+
+#define E_BOOK_CLIENT_ERROR e_book_client_error_quark ()
+
+GQuark e_book_client_error_quark (void) G_GNUC_CONST;
+
+typedef enum {
+ E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK,
+ E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND,
+ E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS,
+ E_BOOK_CLIENT_ERROR_TLS_NOT_AVAILABLE,
+ E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE,
+ E_BOOK_CLIENT_ERROR_OFFLINE_UNAVAILABLE,
+ E_BOOK_CLIENT_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD,
+ E_BOOK_CLIENT_ERROR_NO_SPACE
+} EBookClientError;
+
+const gchar *e_book_client_error_to_string (EBookClientError code);
+
+typedef struct _EBookClient EBookClient;
+typedef struct _EBookClientClass EBookClientClass;
+typedef struct _EBookClientPrivate EBookClientPrivate;
+
+struct _EBookClient {
+ EClient parent;
+
+ /*< private >*/
+ EBookClientPrivate *priv;
+};
+
+struct _EBookClientClass {
+ EClientClass parent;
+};
+
+GType e_book_client_get_type (void);
+
+/* Creating a new addressbook */
+EBookClient * e_book_client_new (ESource *source, GError **error);
+EBookClient * e_book_client_new_from_uri (const gchar *uri, GError **error);
+EBookClient * e_book_client_new_system (GError **error);
+EBookClient * e_book_client_new_default (GError **error);
+
+/* Addressbook discovery */
+gboolean e_book_client_set_default (EBookClient *client, GError **error);
+gboolean e_book_client_set_default_source (ESource *source, GError **error);
+gboolean e_book_client_get_sources (ESourceList **sources, GError **error);
+
+/* Identity */
+gboolean e_book_client_get_self (EContact **contact, EBookClient **client, GError **error);
+gboolean e_book_client_set_self (EBookClient *client, EContact *contact, GError **error);
+gboolean e_book_client_is_self (EContact *contact);
+
+/* Addressbook methods */
+void e_book_client_add_contact (EBookClient *client, /* const */ EContact *contact, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_book_client_add_contact_finish (EBookClient *client, GAsyncResult *result, gchar **added_uid, GError **error);
+gboolean e_book_client_add_contact_sync (EBookClient *client, /* const */ EContact *contact, gchar **added_uid, GCancellable *cancellable, GError **error);
+
+void e_book_client_modify_contact (EBookClient *client, /* const */ EContact *contact, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_book_client_modify_contact_finish (EBookClient *client, GAsyncResult *result, GError **error);
+gboolean e_book_client_modify_contact_sync (EBookClient *client, /* const */ EContact *contact, GCancellable *cancellable, GError **error);
+
+void e_book_client_remove_contact (EBookClient *client, /* const */ EContact *contact, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_book_client_remove_contact_finish (EBookClient *client, GAsyncResult *result, GError **error);
+gboolean e_book_client_remove_contact_sync (EBookClient *client, /* const */ EContact *contact, GCancellable *cancellable, GError **error);
+
+void e_book_client_remove_contact_by_uid (EBookClient *client, const gchar *uid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_book_client_remove_contact_by_uid_finish (EBookClient *client, GAsyncResult *result, GError **error);
+gboolean e_book_client_remove_contact_by_uid_sync (EBookClient *client, const gchar *uid, GCancellable *cancellable, GError **error);
+
+void e_book_client_remove_contacts (EBookClient *client, const GSList *uids, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_book_client_remove_contacts_finish (EBookClient *client, GAsyncResult *result, GError **error);
+gboolean e_book_client_remove_contacts_sync (EBookClient *client, const GSList *uids, GCancellable *cancellable, GError **error);
+
+void e_book_client_get_contact (EBookClient *client, const gchar *uid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_book_client_get_contact_finish (EBookClient *client, GAsyncResult *result, EContact **contact, GError **error);
+gboolean e_book_client_get_contact_sync (EBookClient *client, const gchar *uid, EContact **contact, GCancellable *cancellable, GError **error);
+
+void e_book_client_get_contacts (EBookClient *client, const gchar *sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_book_client_get_contacts_finish (EBookClient *client, GAsyncResult *result, GSList **contacts, GError **error);
+gboolean e_book_client_get_contacts_sync (EBookClient *client, const gchar *sexp, GSList **contacts, GCancellable *cancellable, GError **error);
+
+void e_book_client_get_view (EBookClient *client, const gchar *sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_book_client_get_view_finish (EBookClient *client, GAsyncResult *result, EBookClientView **view, GError **error);
+gboolean e_book_client_get_view_sync (EBookClient *client, const gchar *sexp, EBookClientView **view, GCancellable *cancellable, GError **error);
+
+G_END_DECLS
+
+#endif /* E_BOOK_CLIENT_H */
diff --git a/addressbook/libebook/e-book-view-private.h b/addressbook/libebook/e-book-view-private.h
index 16a6461..1b49f60 100644
--- a/addressbook/libebook/e-book-view-private.h
+++ b/addressbook/libebook/e-book-view-private.h
@@ -23,6 +23,7 @@
#define __E_BOOK_VIEW_PRIVATE_H__
#include "e-book.h"
+#include "e-book-client.h"
#include "e-book-view.h"
struct _EGdbusBookView;
diff --git a/addressbook/libebook/e-book-view.c b/addressbook/libebook/e-book-view.c
index ff48ea8..47288f1 100644
--- a/addressbook/libebook/e-book-view.c
+++ b/addressbook/libebook/e-book-view.c
@@ -21,12 +21,13 @@
*/
#include <glib-object.h>
+
#include "e-book.h"
#include "e-book-view.h"
#include "e-book-view-private.h"
#include "e-book-marshal.h"
#include "libedata-book/e-data-book-types.h"
-#include "e-gdbus-egdbusbookview.h"
+#include "e-gdbus-book-view.h"
G_DEFINE_TYPE (EBookView, e_book_view, G_TYPE_OBJECT);
@@ -51,7 +52,7 @@ enum {
static guint signals[LAST_SIGNAL];
static void
-contacts_added_cb (EGdbusBookView *object, const gchar * const *vcards, EBookView *book_view)
+objects_added_cb (EGdbusBookView *object, const gchar * const *vcards, EBookView *book_view)
{
const gchar * const *p;
GList *contacts = NULL;
@@ -72,7 +73,7 @@ contacts_added_cb (EGdbusBookView *object, const gchar * const *vcards, EBookVie
}
static void
-contacts_changed_cb (EGdbusBookView *object, const gchar * const *vcards, EBookView *book_view)
+objects_modified_cb (EGdbusBookView *object, const gchar * const *vcards, EBookView *book_view)
{
const gchar * const *p;
GList *contacts = NULL;
@@ -92,7 +93,7 @@ contacts_changed_cb (EGdbusBookView *object, const gchar * const *vcards, EBookV
}
static void
-contacts_removed_cb (EGdbusBookView *object, const gchar * const *ids, EBookView *book_view)
+objects_removed_cb (EGdbusBookView *object, const gchar * const *ids, EBookView *book_view)
{
const gchar * const *p;
GList *list = NULL;
@@ -112,7 +113,7 @@ contacts_removed_cb (EGdbusBookView *object, const gchar * const *ids, EBookView
}
static void
-status_message_cb (EGdbusBookView *object, const gchar *message, EBookView *book_view)
+progress_cb (EGdbusBookView *object, guint percent, const gchar *message, EBookView *book_view)
{
if (!book_view->priv->running)
return;
@@ -121,14 +122,17 @@ status_message_cb (EGdbusBookView *object, const gchar *message, EBookView *book
}
static void
-complete_cb (EGdbusBookView *object, /* EDataBookStatus */ guint status, const gchar *message, EBookView *book_view)
+complete_cb (EGdbusBookView *object, const gchar * const *in_error_strv, EBookView *book_view)
{
+ GError *error = NULL;
EBookViewStatus bv_status = E_BOOK_VIEW_ERROR_OTHER_ERROR;
if (!book_view->priv->running)
return;
- switch (status) {
+ g_return_if_fail (e_gdbus_templates_decode_error (in_error_strv, &error));
+
+ switch (error ? error->code : E_DATA_BOOK_STATUS_SUCCESS) {
case E_DATA_BOOK_STATUS_SUCCESS:
bv_status = E_BOOK_VIEW_STATUS_OK;
break;
@@ -151,20 +155,12 @@ complete_cb (EGdbusBookView *object, /* EDataBookStatus */ guint status, const g
#ifndef E_BOOK_DISABLE_DEPRECATED
g_signal_emit (book_view, signals[SEQUENCE_COMPLETE], 0, bv_status);
#endif
- g_signal_emit (book_view, signals[VIEW_COMPLETE], 0, bv_status, message);
+ g_signal_emit (book_view, signals[VIEW_COMPLETE], 0, bv_status, error ? error->message : "");
+
+ if (error)
+ g_error_free (error);
}
-/*
- * e_book_view_new:
- * @book: an #EBook
- * @gdbus_bookview: The #EGdbusBookView to get signals from
- *
- * Creates a new #EBookView based on #EBook and listening to @gdbus_bookview. This
- * is a private function, applications should call #e_book_get_book_view or
- * #e_book_async_get_book_view.
- *
- * Returns: A new #EBookView.
- **/
EBookView *
_e_book_view_new (EBook *book, EGdbusBookView *gdbus_bookview)
{
@@ -180,10 +176,10 @@ _e_book_view_new (EBook *book, EGdbusBookView *gdbus_bookview)
priv->gdbus_bookview = gdbus_bookview;
g_object_add_weak_pointer (G_OBJECT (gdbus_bookview), (gpointer) &priv->gdbus_bookview);
- g_signal_connect (priv->gdbus_bookview, "contacts-added", G_CALLBACK (contacts_added_cb), view);
- g_signal_connect (priv->gdbus_bookview, "contacts-changed", G_CALLBACK (contacts_changed_cb), view);
- g_signal_connect (priv->gdbus_bookview, "contacts-removed", G_CALLBACK (contacts_removed_cb), view);
- g_signal_connect (priv->gdbus_bookview, "status-message", G_CALLBACK (status_message_cb), view);
+ g_signal_connect (priv->gdbus_bookview, "objects-added", G_CALLBACK (objects_added_cb), view);
+ g_signal_connect (priv->gdbus_bookview, "objects-modified", G_CALLBACK (objects_modified_cb), view);
+ g_signal_connect (priv->gdbus_bookview, "objects-removed", G_CALLBACK (objects_removed_cb), view);
+ g_signal_connect (priv->gdbus_bookview, "progress", G_CALLBACK (progress_cb), view);
g_signal_connect (priv->gdbus_bookview, "complete", G_CALLBACK (complete_cb), view);
return view;
@@ -223,7 +219,7 @@ e_book_view_start (EBookView *book_view)
book_view->priv->running = TRUE;
if (book_view->priv->gdbus_bookview) {
- e_gdbus_book_view_call_start_sync (book_view->priv->gdbus_bookview, NULL, &error);
+ e_gdbus_book_view_call_start_sync (G_DBUS_PROXY (book_view->priv->gdbus_bookview), NULL, &error);
if (error) {
g_warning ("Cannot start book view: %s\n", error->message);
@@ -255,7 +251,7 @@ e_book_view_stop (EBookView *book_view)
book_view->priv->running = FALSE;
if (book_view->priv->gdbus_bookview) {
- e_gdbus_book_view_call_stop_sync (book_view->priv->gdbus_bookview, NULL, &error);
+ e_gdbus_book_view_call_stop_sync (G_DBUS_PROXY (book_view->priv->gdbus_bookview), NULL, &error);
if (error) {
g_warning ("Cannot stop book view: %s\n", error->message);
g_error_free (error);
@@ -269,6 +265,7 @@ e_book_view_init (EBookView *book_view)
book_view->priv = G_TYPE_INSTANCE_GET_PRIVATE (
book_view, E_TYPE_BOOK_VIEW, EBookViewPrivate);
book_view->priv->gdbus_bookview = NULL;
+
book_view->priv->book = NULL;
book_view->priv->running = FALSE;
}
@@ -282,7 +279,7 @@ e_book_view_dispose (GObject *object)
GError *error = NULL;
g_signal_handlers_disconnect_matched (book_view->priv->gdbus_bookview, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, book_view);
- e_gdbus_book_view_call_dispose_sync (book_view->priv->gdbus_bookview, NULL, &error);
+ e_gdbus_book_view_call_dispose_sync (G_DBUS_PROXY (book_view->priv->gdbus_bookview), NULL, &error);
g_object_unref (book_view->priv->gdbus_bookview);
book_view->priv->gdbus_bookview = NULL;
diff --git a/addressbook/libebook/e-book-view.h b/addressbook/libebook/e-book-view.h
index 2148f74..36d6620 100644
--- a/addressbook/libebook/e-book-view.h
+++ b/addressbook/libebook/e-book-view.h
@@ -11,6 +11,8 @@
#ifndef __E_BOOK_VIEW_H__
#define __E_BOOK_VIEW_H__
+#ifndef E_BOOK_DISABLE_DEPRECATED
+
#include <glib.h>
#include <glib-object.h>
#include "e-book-types.h"
@@ -59,13 +61,15 @@ struct _EBookViewClass {
void (*_ebook_reserved4) (void);
};
-GType e_book_view_get_type (void);
+GType e_book_view_get_type (void);
-void e_book_view_start (EBookView *book_view);
-void e_book_view_stop (EBookView *book_view);
+void e_book_view_start (EBookView *book_view);
+void e_book_view_stop (EBookView *book_view);
-struct _EBook *e_book_view_get_book (EBookView *book_view);
+struct _EBook * e_book_view_get_book (EBookView *book_view);
G_END_DECLS
+#endif /* E_BOOK_DISABLE_DEPRECATED */
+
#endif /* __E_BOOK_VIEW_H__ */
diff --git a/addressbook/libebook/e-book.c b/addressbook/libebook/e-book.c
index 0b82efa..009e406 100644
--- a/addressbook/libebook/e-book.c
+++ b/addressbook/libebook/e-book.c
@@ -20,6 +20,9 @@
* Author: Ross Burton <ross linux intel com>
*/
+/* e-book deprecated since 3.2, use e-book-client instead */
+#ifndef E_BOOK_DISABLE_DEPRECATED
+
/**
* SECTION:e-book
*
@@ -28,6 +31,8 @@
* structure in the asynchronous callback, instead of a status code only.
*
* As an example, e_book_async_open() is replaced by e_book_open_async().
+ *
+ * Deprecated: 3.2: Use #EBookClient instead.
*/
#include <config.h>
@@ -43,9 +48,14 @@
#include "e-book-view-private.h"
#include "e-book-marshal.h"
-#include "e-gdbus-egdbusbookfactory.h"
-#include "e-gdbus-egdbusbook.h"
-#include "e-gdbus-egdbusbookview.h"
+#include "e-gdbus-book.h"
+#include "e-gdbus-book-factory.h"
+#include "e-gdbus-book-view.h"
+
+#define CLIENT_BACKEND_PROPERTY_CAPABILITIES "capabilities"
+#define BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS "required-fields"
+#define BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS "supported-fields"
+#define BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS "supported-auth-methods"
static gchar ** flatten_stringlist (GList *list);
static GList *array_to_stringlist (gchar **list);
@@ -65,7 +75,7 @@ enum {
static guint e_book_signals[LAST_SIGNAL];
struct _EBookPrivate {
- EGdbusBook *gdbus_book;
+ GDBusProxy *gdbus_book;
guint gone_signal_id;
ESource *source;
@@ -347,27 +357,27 @@ e_book_activate (GError **error)
}
static void
-writable_cb (EGdbusBook *object, gboolean writable, EBook *book)
+readonly_cb (EGdbusBook *object, gboolean readonly, EBook *book)
{
g_return_if_fail (E_IS_BOOK (book));
- book->priv->writable = writable;
+ book->priv->writable = !readonly;
- g_signal_emit (G_OBJECT (book), e_book_signals[WRITABLE_STATUS], 0, writable);
+ g_signal_emit (G_OBJECT (book), e_book_signals[WRITABLE_STATUS], 0, book->priv->writable);
}
static void
-connection_cb (EGdbusBook *object, gboolean connected, EBook *book)
+online_cb (EGdbusBook *object, gboolean is_online, EBook *book)
{
g_return_if_fail (E_IS_BOOK (book));
- book->priv->connected = connected;
+ book->priv->connected = is_online;
- g_signal_emit (G_OBJECT (book), e_book_signals[CONNECTION_STATUS], 0, connected);
+ g_signal_emit (G_OBJECT (book), e_book_signals[CONNECTION_STATUS], 0, is_online);
}
static void
-auth_required_cb (EGdbusBook *object, EBook *book)
+auth_required_cb (EGdbusBook *object, const ECredentials *credentials, EBook *book)
{
g_return_if_fail (E_IS_BOOK (book));
@@ -383,6 +393,8 @@ auth_required_cb (EGdbusBook *object, EBook *book)
* Adds @contact to @book.
*
* Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_book_client_add_contact_sync() instead.
**/
gboolean
e_book_add_contact (EBook *book,
@@ -422,7 +434,7 @@ add_contact_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
EBookIdCallback cb = data->callback;
#endif
- e_gdbus_book_call_add_contact_finish (E_GDBUS_BOOK (gdbus_book), &uid, res, &error);
+ e_gdbus_book_call_add_contact_finish (G_DBUS_PROXY (gdbus_book), res, &uid, &error);
unwrap_gerror (error, &err);
@@ -505,6 +517,8 @@ e_book_async_add_contact (EBook *book,
* Returns: %TRUE if the operation was started, %FALSE otherwise.
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use e_book_client_add_contact() and e_book_client_add_contact_finish() instead.
**/
gboolean
e_book_add_contact_async (EBook *book,
@@ -546,6 +560,8 @@ e_book_add_contact_async (EBook *book,
* @book.
*
* Returns: %TRUE if successful, %FALSE otherwise
+ *
+ * Deprecated: 3.2: Use e_book_client_modify_contact_sync() instead.
**/
gboolean
e_book_commit_contact (EBook *book,
@@ -579,7 +595,7 @@ modify_contact_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data
EBookCallback cb = data->callback;
#endif
- e_gdbus_book_call_modify_contact_finish (E_GDBUS_BOOK (gdbus_book), res, &error);
+ e_gdbus_book_call_modify_contact_finish (G_DBUS_PROXY (gdbus_book), res, &error);
unwrap_gerror (error, &err);
@@ -657,6 +673,8 @@ e_book_async_commit_contact (EBook *book,
* Returns: %TRUE if the operation was started, %FALSE otherwise.
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use e_book_client_modify_contact() and e_book_client_modify_contact_finish() instead.
**/
gboolean
e_book_commit_contact_async (EBook *book,
@@ -700,6 +718,9 @@ e_book_commit_contact_async (EBook *book,
* must be freed by the caller.
*
* Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_client_get_backend_property_sync() on
+ * an #EBookClient object with #BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS instead.
**/
gboolean
e_book_get_required_fields (EBook *book,
@@ -707,14 +728,17 @@ e_book_get_required_fields (EBook *book,
GError **error)
{
GError *err = NULL;
- gchar **list = NULL;
+ gchar **list = NULL, *list_str = NULL;
g_return_val_if_fail (E_IS_BOOK (book), FALSE);
e_return_error_if_fail (
book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- e_gdbus_book_call_get_required_fields_sync (book->priv->gdbus_book, &list, NULL, &err);
+ e_gdbus_book_call_get_backend_property_sync (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS, &list_str, NULL, &err);
+
+ list = g_strsplit (list_str, ",", -1);
+ g_free (list_str);
if (list) {
*fields = array_to_stringlist (list);
@@ -728,7 +752,7 @@ e_book_get_required_fields (EBook *book,
static void
get_required_fields_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
{
- gchar **fields = NULL;
+ gchar **fields = NULL, *fields_str = NULL;
GError *err = NULL, *error = NULL;
AsyncData *data = user_data;
EBookEListAsyncCallback excb = data->excallback;
@@ -737,7 +761,10 @@ get_required_fields_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user
#endif
EList *efields = NULL;
- e_gdbus_book_call_get_required_fields_finish (E_GDBUS_BOOK (gdbus_book), &fields, res, &error);
+ e_gdbus_book_call_get_backend_property_finish (G_DBUS_PROXY (gdbus_book), res, &fields_str, &error);
+
+ fields = g_strsplit (fields_str, ",", -1);
+ g_free (fields_str);
efields = array_to_elist (fields);
@@ -790,7 +817,7 @@ e_book_async_get_required_fields (EBook *book,
data->callback = cb;
data->closure = closure;
- e_gdbus_book_call_get_required_fields (book->priv->gdbus_book, NULL, get_required_fields_reply, data);
+ e_gdbus_book_call_get_backend_property (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS, NULL, get_required_fields_reply, data);
return TRUE;
}
@@ -808,6 +835,9 @@ e_book_async_get_required_fields (EBook *book,
* Returns: %TRUE if the operation was started, %FALSE otherwise.
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use e_client_get_backend_property() and e_client_get_backend_property_finish()
+ * on an #EBookClient object with #BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS instead.
**/
gboolean
e_book_get_required_fields_async (EBook *book,
@@ -826,7 +856,7 @@ e_book_get_required_fields_async (EBook *book,
data->excallback = cb;
data->closure = closure;
- e_gdbus_book_call_get_required_fields (book->priv->gdbus_book, NULL, get_required_fields_reply, data);
+ e_gdbus_book_call_get_backend_property (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS, NULL, get_required_fields_reply, data);
return TRUE;
}
@@ -843,6 +873,9 @@ e_book_get_required_fields_async (EBook *book,
* #GList and the strings must be freed by the caller.
*
* Returns: %TRUE if successful, %FALSE otherwise
+ *
+ * Deprecated: 3.2: Use e_client_get_backend_property_sync() on
+ * an #EBookClient object with #BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS instead.
**/
gboolean
e_book_get_supported_fields (EBook *book,
@@ -850,15 +883,17 @@ e_book_get_supported_fields (EBook *book,
GError **error)
{
GError *err = NULL;
- gchar **list = NULL;
+ gchar **list = NULL, *list_str = NULL;
g_return_val_if_fail (E_IS_BOOK (book), FALSE);
e_return_error_if_fail (
book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- e_gdbus_book_call_get_supported_fields_sync (book->priv->gdbus_book, &list, NULL, &err);
+ e_gdbus_book_call_get_backend_property_sync (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS, &list_str, NULL, &err);
+ list = g_strsplit (list_str, ",", -1);
+ g_free (list_str);
if (list) {
*fields = array_to_stringlist (list);
g_strfreev (list);
@@ -871,7 +906,7 @@ e_book_get_supported_fields (EBook *book,
static void
get_supported_fields_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
{
- gchar **fields = NULL;
+ gchar **fields = NULL, *fields_str = NULL;
GError *err = NULL, *error = NULL;
AsyncData *data = user_data;
EBookEListAsyncCallback excb = data->excallback;
@@ -880,7 +915,10 @@ get_supported_fields_reply (GObject *gdbus_book, GAsyncResult *res, gpointer use
#endif
EList *efields;
- e_gdbus_book_call_get_supported_fields_finish (E_GDBUS_BOOK (gdbus_book), &fields, res, &error);
+ e_gdbus_book_call_get_backend_property_finish (G_DBUS_PROXY (gdbus_book), res, &fields_str, &error);
+
+ fields = g_strsplit (fields_str, ",", -1);
+ g_free (fields_str);
efields = array_to_elist (fields);
@@ -934,7 +972,7 @@ e_book_async_get_supported_fields (EBook *book,
data->callback = cb;
data->closure = closure;
- e_gdbus_book_call_get_supported_fields (book->priv->gdbus_book, NULL, get_supported_fields_reply, data);
+ e_gdbus_book_call_get_backend_property (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS, NULL, get_supported_fields_reply, data);
return TRUE;
}
@@ -953,6 +991,9 @@ e_book_async_get_supported_fields (EBook *book,
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use e_client_get_backend_property() and e_client_get_backend_property_finish()
+ * on an #EBookClient object with #BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS instead.
**/
gboolean
e_book_get_supported_fields_async (EBook *book,
@@ -971,7 +1012,7 @@ e_book_get_supported_fields_async (EBook *book,
data->excallback = cb;
data->closure = closure;
- e_gdbus_book_call_get_supported_fields (book->priv->gdbus_book, NULL, get_supported_fields_reply, data);
+ e_gdbus_book_call_get_backend_property (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS, NULL, get_supported_fields_reply, data);
return TRUE;
}
@@ -987,6 +1028,9 @@ e_book_get_supported_fields_async (EBook *book,
* #GList and the strings must be freed by the caller.
*
* Returns: %TRUE if successful, %FALSE otherwise
+ *
+ * Deprecated: 3.2: Use e_client_get_backend_property_sync() on
+ * an #EBookClient object with #BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS instead.
**/
gboolean
e_book_get_supported_auth_methods (EBook *book,
@@ -994,6 +1038,7 @@ e_book_get_supported_auth_methods (EBook *book,
GError **error)
{
GError *err = NULL;
+ gchar *list_str = NULL;
gchar **list = NULL;
g_return_val_if_fail (E_IS_BOOK (book), FALSE);
@@ -1001,7 +1046,10 @@ e_book_get_supported_auth_methods (EBook *book,
e_return_error_if_fail (
book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- e_gdbus_book_call_get_supported_auth_methods_sync (book->priv->gdbus_book, &list, NULL, &err);
+ e_gdbus_book_call_get_backend_property_sync (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS, &list_str, NULL, &err);
+
+ list = g_strsplit (list_str, ",", -1);
+ g_free (list_str);
if (list) {
*auth_methods = array_to_stringlist (list);
@@ -1015,7 +1063,7 @@ e_book_get_supported_auth_methods (EBook *book,
static void
get_supported_auth_methods_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
{
- gchar **methods = NULL;
+ gchar **methods = NULL, *methods_str = NULL;
GError *err = NULL, *error = NULL;
AsyncData *data = user_data;
EBookEListAsyncCallback excb = data->excallback;
@@ -1024,7 +1072,10 @@ get_supported_auth_methods_reply (GObject *gdbus_book, GAsyncResult *res, gpoint
#endif
EList *emethods;
- e_gdbus_book_call_get_supported_auth_methods_finish (E_GDBUS_BOOK (gdbus_book), &methods, res, &error);
+ e_gdbus_book_call_get_backend_property_finish (G_DBUS_PROXY (gdbus_book), res, &methods_str, &error);
+
+ methods = g_strsplit (methods_str, ",", -1);
+ g_free (methods_str);
emethods = array_to_elist (methods);
@@ -1077,7 +1128,7 @@ e_book_async_get_supported_auth_methods (EBook *book,
data->callback = cb;
data->closure = closure;
- e_gdbus_book_call_get_supported_auth_methods (book->priv->gdbus_book, NULL, get_supported_auth_methods_reply, data);
+ e_gdbus_book_call_get_backend_property (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS, NULL, get_supported_auth_methods_reply, data);
return TRUE;
}
@@ -1095,6 +1146,9 @@ e_book_async_get_supported_auth_methods (EBook *book,
* Returns: %TRUE if successful, %FALSE otherwise.
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use e_client_get_backend_property() and e_client_get_backend_property_finish()
+ * on an #EBookClient object with #BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS instead.
**/
gboolean
e_book_get_supported_auth_methods_async (EBook *book,
@@ -1113,7 +1167,7 @@ e_book_get_supported_auth_methods_async (EBook *book,
data->excallback = cb;
data->closure = closure;
- e_gdbus_book_call_get_supported_auth_methods (book->priv->gdbus_book, NULL, get_supported_auth_methods_reply, data);
+ e_gdbus_book_call_get_backend_property (book->priv->gdbus_book, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS, NULL, get_supported_auth_methods_reply, data);
return TRUE;
}
@@ -1131,6 +1185,8 @@ e_book_get_supported_auth_methods_async (EBook *book,
* methods returned using e_book_get_supported_auth_methods.
*
* Returns: %TRUE if successful, %FALSE otherwise
+ *
+ * Deprecated: 3.2: Connect to EClient::authenticate signal instead.
**/
gboolean
e_book_authenticate_user (EBook *book,
@@ -1140,21 +1196,26 @@ e_book_authenticate_user (EBook *book,
GError **error)
{
GError *err = NULL;
- gchar *gdbus_user = NULL, *gdbus_passwd = NULL, *gdbus_auth_method = NULL;
+ ECredentials *credentials;
+ gchar **credentials_strv;
g_return_val_if_fail (E_IS_BOOK (book), FALSE);
e_return_error_if_fail (
book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- e_gdbus_book_call_authenticate_user_sync (book->priv->gdbus_book,
- e_util_ensure_gdbus_string (user, &gdbus_user),
- e_util_ensure_gdbus_string (passwd, &gdbus_passwd),
- e_util_ensure_gdbus_string (auth_method, &gdbus_auth_method), NULL, &err);
+ credentials = e_credentials_new_args (
+ E_CREDENTIALS_KEY_USERNAME, user,
+ E_CREDENTIALS_KEY_PASSWORD, passwd,
+ E_CREDENTIALS_KEY_AUTH_METHOD, auth_method,
+ NULL);
+
+ credentials_strv = e_credentials_to_strv (credentials);
- g_free (gdbus_user);
- g_free (gdbus_passwd);
- g_free (gdbus_auth_method);
+ e_gdbus_book_call_authenticate_user_sync (book->priv->gdbus_book, (const gchar * const *) credentials_strv, NULL, &err);
+
+ g_strfreev (credentials_strv);
+ e_credentials_free (credentials);
return unwrap_gerror (err, error);
}
@@ -1169,7 +1230,7 @@ authenticate_user_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_d
EBookCallback cb = data->callback;
#endif
- e_gdbus_book_call_authenticate_user_finish (E_GDBUS_BOOK (gdbus_book), res, &error);
+ e_gdbus_book_call_authenticate_user_finish (G_DBUS_PROXY (gdbus_book), res, &error);
unwrap_gerror (error, &err);
@@ -1215,7 +1276,8 @@ e_book_async_authenticate_user (EBook *book,
gpointer closure)
{
AsyncData *data;
- gchar *gdbus_user = NULL, *gdbus_passwd = NULL, *gdbus_auth_method = NULL;
+ ECredentials *credentials;
+ gchar **credentials_strv;
g_return_val_if_fail (E_IS_BOOK (book), FALSE);
g_return_val_if_fail (user != NULL, FALSE);
@@ -1230,14 +1292,18 @@ e_book_async_authenticate_user (EBook *book,
data->callback = cb;
data->closure = closure;
- e_gdbus_book_call_authenticate_user (book->priv->gdbus_book,
- e_util_ensure_gdbus_string (user, &gdbus_user),
- e_util_ensure_gdbus_string (passwd, &gdbus_passwd),
- e_util_ensure_gdbus_string (auth_method, &gdbus_auth_method), NULL, authenticate_user_reply, data);
+ credentials = e_credentials_new_args (
+ E_CREDENTIALS_KEY_USERNAME, user,
+ E_CREDENTIALS_KEY_PASSWORD, passwd,
+ E_CREDENTIALS_KEY_AUTH_METHOD, auth_method,
+ NULL);
+
+ credentials_strv = e_credentials_to_strv (credentials);
- g_free (gdbus_user);
- g_free (gdbus_passwd);
- g_free (gdbus_auth_method);
+ e_gdbus_book_call_authenticate_user (book->priv->gdbus_book, (const gchar * const *) credentials_strv, NULL, authenticate_user_reply, data);
+
+ g_strfreev (credentials_strv);
+ e_credentials_free (credentials);
return TRUE;
}
@@ -1260,6 +1326,8 @@ e_book_async_authenticate_user (EBook *book,
* Returns: %FALSE if successful, %TRUE otherwise.
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Connect to EClient::authenticate signal instead.
**/
gboolean
e_book_authenticate_user_async (EBook *book,
@@ -1270,7 +1338,8 @@ e_book_authenticate_user_async (EBook *book,
gpointer closure)
{
AsyncData *data;
- gchar *gdbus_user = NULL, *gdbus_passwd = NULL, *gdbus_auth_method = NULL;
+ ECredentials *credentials;
+ gchar **credentials_strv;
g_return_val_if_fail (E_IS_BOOK (book), FALSE);
g_return_val_if_fail (user != NULL, FALSE);
@@ -1285,14 +1354,18 @@ e_book_authenticate_user_async (EBook *book,
data->excallback = cb;
data->closure = closure;
- e_gdbus_book_call_authenticate_user (book->priv->gdbus_book,
- e_util_ensure_gdbus_string (user, &gdbus_user),
- e_util_ensure_gdbus_string (passwd, &gdbus_passwd),
- e_util_ensure_gdbus_string (auth_method, &gdbus_auth_method), NULL, authenticate_user_reply, data);
+ credentials = e_credentials_new_args (
+ E_CREDENTIALS_KEY_USERNAME, user,
+ E_CREDENTIALS_KEY_PASSWORD, passwd,
+ E_CREDENTIALS_KEY_AUTH_METHOD, auth_method,
+ NULL);
- g_free (gdbus_user);
- g_free (gdbus_passwd);
- g_free (gdbus_auth_method);
+ credentials_strv = e_credentials_to_strv (credentials);
+
+ e_gdbus_book_call_authenticate_user (book->priv->gdbus_book, (const gchar * const *) credentials_strv, NULL, authenticate_user_reply, data);
+
+ g_strfreev (credentials_strv);
+ e_credentials_free (credentials);
return TRUE;
}
@@ -1308,6 +1381,8 @@ e_book_authenticate_user_async (EBook *book,
* corresponding to @id.
*
* Returns: %TRUE if successful, %FALSE otherwise
+ *
+ * Deprecated: 3.2: Use e_book_client_get_contact_sync() instead.
**/
gboolean
e_book_get_contact (EBook *book,
@@ -1346,7 +1421,7 @@ get_contact_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
EBookContactCallback cb = data->callback;
#endif
- e_gdbus_book_call_get_contact_finish (E_GDBUS_BOOK (gdbus_book), &vcard, res, &error);
+ e_gdbus_book_call_get_contact_finish (G_DBUS_PROXY (gdbus_book), res, &vcard, &error);
unwrap_gerror (error, &err);
@@ -1423,6 +1498,8 @@ e_book_async_get_contact (EBook *book,
* Returns: %FALSE if successful, %TRUE otherwise
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use e_book_client_get_contact() and e_book_client_get_contact_finish() instead.
**/
gboolean
e_book_get_contact_async (EBook *book,
@@ -1460,6 +1537,8 @@ e_book_get_contact_async (EBook *book,
* Removes the contact with id @id from @book.
*
* Returns: %TRUE if successful, %FALSE otherwise
+ *
+ * Deprecated: 3.2: Use e_book_client_remove_contact_by_uid_sync() or e_book_client_remove_contact_sync() instead.
**/
gboolean
e_book_remove_contact (EBook *book,
@@ -1495,7 +1574,7 @@ remove_contact_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data
EBookCallback cb = data->callback;
#endif
- e_gdbus_book_call_remove_contacts_finish (E_GDBUS_BOOK (gdbus_book), res, &error);
+ e_gdbus_book_call_remove_contacts_finish (G_DBUS_PROXY (gdbus_book), res, &error);
unwrap_gerror (error, &err);
@@ -1525,6 +1604,8 @@ remove_contact_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data
* as a batch request.
*
* Returns: %TRUE if successful, %FALSE otherwise
+ *
+ * Deprecated: 3.2: Use e_book_client_remove_contacts_sync() instead.
**/
gboolean
e_book_remove_contacts (EBook *book,
@@ -1606,6 +1687,8 @@ e_book_async_remove_contact (EBook *book,
* Returns: %TRUE if successful, %FALSE otherwise
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use e_book_client_remove_contact() and e_book_client_remove_contact_finish() instead.
**/
gboolean
e_book_remove_contact_async (EBook *book,
@@ -1647,7 +1730,7 @@ remove_contact_by_id_reply (GObject *gdbus_book, GAsyncResult *res, gpointer use
EBookCallback cb = data->callback;
#endif
- e_gdbus_book_call_remove_contacts_finish (E_GDBUS_BOOK (gdbus_book), res, &error);
+ e_gdbus_book_call_remove_contacts_finish (G_DBUS_PROXY (gdbus_book), res, &error);
unwrap_gerror (error, &err);
@@ -1722,6 +1805,8 @@ e_book_async_remove_contact_by_id (EBook *book,
* Returns: %TRUE if successful, %FALSE otherwise
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use e_book_client_remove_contact_by_uid() and e_book_client_remove_contact_by_uid_finish() instead.
**/
gboolean
e_book_remove_contact_by_id_async (EBook *book,
@@ -1763,7 +1848,7 @@ remove_contacts_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_dat
EBookCallback cb = data->callback;
#endif
- e_gdbus_book_call_remove_contacts_finish (E_GDBUS_BOOK (gdbus_book), res, &error);
+ e_gdbus_book_call_remove_contacts_finish (G_DBUS_PROXY (gdbus_book), res, &error);
unwrap_gerror (error, &err);
@@ -1848,6 +1933,8 @@ e_book_async_remove_contacts (EBook *book,
* Returns: %TRUE if successful, %FALSE otherwise
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use e_book_client_remove_contacts() and e_book_client_remove_contacts_finish() instead.
**/
gboolean
e_book_remove_contacts_async (EBook *book,
@@ -1898,6 +1985,8 @@ e_book_remove_contacts_async (EBook *book,
* error, @error is set and %FALSE returned.
*
* Returns: %TRUE if successful, %FALSE otherwise
+ *
+ * Deprecated: 3.2: Use e_book_client_get_view_sync() instead.
**/
gboolean
e_book_get_book_view (EBook *book,
@@ -1919,7 +2008,7 @@ e_book_get_book_view (EBook *book,
sexp = e_book_query_to_string (query);
- if (!e_gdbus_book_call_get_book_view_sync (book->priv->gdbus_book, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), max_results, &view_path, NULL, &err)) {
+ if (!e_gdbus_book_call_get_view_sync (book->priv->gdbus_book, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &view_path, NULL, &err)) {
*book_view = NULL;
g_free (sexp);
g_free (gdbus_sexp);
@@ -1963,7 +2052,7 @@ get_book_view_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
#endif
EGdbusBookView *gdbus_bookview;
- e_gdbus_book_call_get_book_view_finish (E_GDBUS_BOOK (gdbus_book), &view_path, res, &error);
+ e_gdbus_book_call_get_view_finish (G_DBUS_PROXY (gdbus_book), res, &view_path, &error);
if (view_path) {
gdbus_bookview = e_gdbus_book_view_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy)),
@@ -2034,7 +2123,7 @@ e_book_async_get_book_view (EBook *book,
sexp = e_book_query_to_string (query);
- e_gdbus_book_call_get_book_view (book->priv->gdbus_book, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), max_results, NULL, get_book_view_reply, data);
+ e_gdbus_book_call_get_view (book->priv->gdbus_book, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), NULL, get_book_view_reply, data);
g_free (sexp);
g_free (gdbus_sexp);
@@ -2059,6 +2148,8 @@ e_book_async_get_book_view (EBook *book,
* Returns: %FALSE if successful, %TRUE otherwise
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use e_book_client_get_view() and e_book_client_get_view_finish() instead.
**/
gboolean
e_book_get_book_view_async (EBook *book,
@@ -2084,7 +2175,7 @@ e_book_get_book_view_async (EBook *book,
sexp = e_book_query_to_string (query);
- e_gdbus_book_call_get_book_view (book->priv->gdbus_book, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), max_results, NULL, get_book_view_reply, data);
+ e_gdbus_book_call_get_view (book->priv->gdbus_book, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), NULL, get_book_view_reply, data);
g_free (sexp);
g_free (gdbus_sexp);
@@ -2103,6 +2194,8 @@ e_book_get_book_view_async (EBook *book,
* matched. On failed, @error will be set and %FALSE returned.
*
* Returns: %TRUE on success, %FALSE otherwise
+ *
+ * Deprecated: 3.2: Use e_book_client_get_contacts_sync() instead.
**/
gboolean
e_book_get_contacts (EBook *book,
@@ -2152,7 +2245,7 @@ get_contacts_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
EBookListCallback cb = data->callback;
#endif
- e_gdbus_book_call_get_contact_list_finish (E_GDBUS_BOOK (gdbus_book), &vcards, res, &error);
+ e_gdbus_book_call_get_contact_list_finish (G_DBUS_PROXY (gdbus_book), res, &vcards, &error);
unwrap_gerror (error, &err);
@@ -2240,6 +2333,8 @@ e_book_async_get_contacts (EBook *book,
* Returns: %FALSE on success, %TRUE otherwise
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use e_book_client_get_contacts() and e_book_client_get_contacts_finish() instead.
**/
gboolean
e_book_get_contacts_async (EBook *book,
@@ -2313,6 +2408,8 @@ parse_changes_array (GVariant *var_changes)
* for a given change ID.
*
* Returns: %TRUE on success, %FALSE otherwise
+ *
+ * Deprecated: 3.2: This function has been dropped completely.
*/
gboolean
e_book_get_changes (EBook *book,
@@ -2329,7 +2426,7 @@ e_book_get_changes (EBook *book,
e_return_error_if_fail (
book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- e_gdbus_book_call_get_changes_sync (book->priv->gdbus_book, e_util_ensure_gdbus_string (changeid, &gdbus_changeid), &var_changes, NULL, &err);
+ /*e_gdbus_book_call_get_changes_sync (book->priv->gdbus_book, e_util_ensure_gdbus_string (changeid, &gdbus_changeid), &var_changes, NULL, &err);*/
g_free (gdbus_changeid);
@@ -2344,42 +2441,6 @@ e_book_get_changes (EBook *book,
}
}
-static void
-get_changes_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
-{
- GVariant *var_changes = NULL;
- GError *err = NULL, *error = NULL;
- AsyncData *data = user_data;
- EBookListAsyncCallback excb = data->excallback;
- #ifndef E_BOOK_DISABLE_DEPRECATED
- EBookListCallback cb = data->callback;
- #endif
- GList *list = NULL;
-
- e_gdbus_book_call_get_changes_finish (E_GDBUS_BOOK (gdbus_book), &var_changes, res, &error);
-
- unwrap_gerror (error, &err);
-
- if (var_changes) {
- list = parse_changes_array (var_changes);
- g_variant_unref (var_changes);
- }
-
- #ifndef E_BOOK_DISABLE_DEPRECATED
- if (cb)
- cb (data->book, err ? err->code : E_BOOK_ERROR_OK, list, data->closure);
- #endif
-
- if (excb)
- excb (data->book, err, list, data->closure);
-
- if (err)
- g_error_free (err);
-
- g_object_unref (data->book);
- g_slice_free (AsyncData, data);
-}
-
#ifndef E_BOOK_DISABLE_DEPRECATED
/**
* e_book_async_get_changes:
@@ -2401,22 +2462,12 @@ e_book_async_get_changes (EBook *book,
EBookListCallback cb,
gpointer closure)
{
- AsyncData *data;
- gchar *gdbus_changeid = NULL;
-
g_return_val_if_fail (E_IS_BOOK (book), FALSE);
e_return_async_error_val_if_fail (
book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- data = g_slice_new0 (AsyncData);
- data->book = g_object_ref (book);
- data->callback = cb;
- data->closure = closure;
-
- e_gdbus_book_call_get_changes (book->priv->gdbus_book, e_util_ensure_gdbus_string (changeid, &gdbus_changeid), NULL, get_changes_reply, data);
-
- g_free (gdbus_changeid);
+ cb (book, E_BOOK_ERROR_NOT_SUPPORTED, NULL, closure);
return TRUE;
}
@@ -2435,6 +2486,8 @@ e_book_async_get_changes (EBook *book,
* Returns: %TRUE on success, %FALSE otherwise
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: This function has been dropped completely.
*/
gboolean
e_book_get_changes_async (EBook *book,
@@ -2442,22 +2495,16 @@ e_book_get_changes_async (EBook *book,
EBookListAsyncCallback cb,
gpointer closure)
{
- AsyncData *data;
- gchar *gdbus_changeid = NULL;
+ GError *error;
g_return_val_if_fail (E_IS_BOOK (book), FALSE);
e_return_ex_async_error_val_if_fail (
book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- data = g_slice_new0 (AsyncData);
- data->book = g_object_ref (book);
- data->excallback = cb;
- data->closure = closure;
-
- e_gdbus_book_call_get_changes (book->priv->gdbus_book, e_util_ensure_gdbus_string (changeid, &gdbus_changeid), NULL, get_changes_reply, data);
-
- g_free (gdbus_changeid);
+ error = g_error_new (E_BOOK_ERROR, E_BOOK_ERROR_NOT_SUPPORTED, "Not supported");
+ cb (book, error, NULL, closure);
+ g_error_free (error);
return TRUE;
}
@@ -2467,6 +2514,8 @@ e_book_get_changes_async (EBook *book,
* @change_list: a #GList of #EBookChange items
*
* Free the contents of #change_list, and the list itself.
+ *
+ * Deprecated: 3.2: Related function has been dropped completely.
*/
void
e_book_free_change_list (GList *change_list)
@@ -2498,6 +2547,8 @@ e_book_free_change_list (GList *change_list)
* return with a status of E_BOOK_STATUS_CANCELLED.
*
* Returns: %TRUE on success, %FALSE otherwise
+ *
+ * Deprecated: 3.2: Use e_client_cancel_all() or e_client_cancel_op() on an #EBookClient object instead.
**/
gboolean
e_book_cancel (EBook *book,
@@ -2508,7 +2559,7 @@ e_book_cancel (EBook *book,
e_return_error_if_fail (
book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- return e_gdbus_book_call_cancel_operation_sync (book->priv->gdbus_book, NULL, error);
+ return e_gdbus_book_call_cancel_all_sync (book->priv->gdbus_book, NULL, error);
}
/**
@@ -2518,6 +2569,8 @@ e_book_cancel (EBook *book,
* asynchronous operation.
*
* Since: 2.24
+ *
+ * Deprecated: 3.2: Use e_client_cancel_all() or e_client_cancel_op() on an #EBookClient object instead.
**/
gboolean
e_book_cancel_async_op (EBook *book, GError **error)
@@ -2527,7 +2580,7 @@ e_book_cancel_async_op (EBook *book, GError **error)
e_return_error_if_fail (
book->priv->gdbus_book, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- return e_gdbus_book_call_cancel_operation_sync (book->priv->gdbus_book, NULL, error);
+ return e_gdbus_book_call_cancel_all_sync (book->priv->gdbus_book, NULL, error);
}
/**
@@ -2539,6 +2592,8 @@ e_book_cancel_async_op (EBook *book, GError **error)
* Opens the addressbook, making it ready for queries and other operations.
*
* Returns: %TRUE if the book was successfully opened, %FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_client_open_sync() on an #EBookClient object instead.
*/
gboolean
e_book_open (EBook *book,
@@ -2575,7 +2630,7 @@ open_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
EBookCallback cb = data->callback;
#endif
- e_gdbus_book_call_open_finish (E_GDBUS_BOOK (gdbus_book), res, &error);
+ e_gdbus_book_call_open_finish (G_DBUS_PROXY (gdbus_book), res, &error);
unwrap_gerror (error, &err);
@@ -2647,6 +2702,8 @@ e_book_async_open (EBook *book,
* Returns: %FALSE if successful, %TRUE otherwise.
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use e_client_open() and e_client_open_finish() on an #EBookClient object instead.
**/
gboolean
e_book_open_async (EBook *book,
@@ -2680,6 +2737,8 @@ e_book_open_async (EBook *book,
* deletes the database file. You cannot get it back!
*
* Returns: %TRUE on success, %FALSE on failure.
+ *
+ * Deprecated: 3.2: Use e_client_remove_sync() on an #EBookClient object instead.
*/
gboolean
e_book_remove (EBook *book,
@@ -2707,7 +2766,7 @@ remove_reply (GObject *gdbus_book, GAsyncResult *res, gpointer user_data)
EBookCallback cb = data->callback;
#endif
- e_gdbus_book_call_remove_finish (E_GDBUS_BOOK (gdbus_book), res, &error);
+ e_gdbus_book_call_remove_finish (G_DBUS_PROXY (gdbus_book), res, &error);
unwrap_gerror (error, &err);
@@ -2774,6 +2833,8 @@ e_book_async_remove (EBook *book,
* Returns: %FALSE if successful, %TRUE otherwise.
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use e_client_remove() and e_client_remove_finish() on an #EBookClient object instead.
**/
gboolean
e_book_remove_async (EBook *book,
@@ -2804,6 +2865,8 @@ e_book_remove_async (EBook *book,
* Get the URI that this book has loaded. This string should not be freed.
*
* Returns: The URI.
+ *
+ * Deprecated: 3.2: Use e_client_get_uri() on an #EBookClient object instead.
*/
const gchar *
e_book_get_uri (EBook *book)
@@ -2820,6 +2883,8 @@ e_book_get_uri (EBook *book)
* Get the #ESource that this book has loaded.
*
* Returns: (transfer none): The source.
+ *
+ * Deprecated: 3.2: Use e_client_get_source() on an #EBookClient object instead.
*/
ESource *
e_book_get_source (EBook *book)
@@ -2838,6 +2903,8 @@ e_book_get_source (EBook *book)
* supports. This string should not be freed.
*
* Returns: The capabilities list
+ *
+ * Deprecated: 3.2: Use e_client_get_capabilities() on an #EBookClient object.
*/
const gchar *
e_book_get_static_capabilities (EBook *book,
@@ -2851,7 +2918,7 @@ e_book_get_static_capabilities (EBook *book,
if (!book->priv->cap_queried) {
gchar *cap = NULL;
- if (!e_gdbus_book_call_get_static_capabilities_sync (book->priv->gdbus_book, &cap, NULL, error)) {
+ if (!e_gdbus_book_call_get_backend_property_sync (book->priv->gdbus_book, CLIENT_BACKEND_PROPERTY_CAPABILITIES, &cap, NULL, error)) {
return NULL;
}
@@ -2871,6 +2938,8 @@ e_book_get_static_capabilities (EBook *book,
* @cap.
*
* Returns: %TRUE if the backend supports @cap, %FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_client_check_capability() on an #EBookClient object instead.
*/
gboolean
e_book_check_static_capability (EBook *book,
@@ -2896,6 +2965,8 @@ e_book_check_static_capability (EBook *book,
* Check if this book has been opened.
*
* Returns: %TRUE if this book has been opened, otherwise %FALSE.
+ *
+ * Deprecated: 3.2: Use e_client_is_opened() on an #EBookClient object instead.
*/
gboolean
e_book_is_opened (EBook *book)
@@ -2912,6 +2983,8 @@ e_book_is_opened (EBook *book)
* Check if this book is writable.
*
* Returns: %TRUE if this book is writable, otherwise %FALSE.
+ *
+ * Deprecated: 3.2: Use e_client_is_readonly() on an #EBookClient object instead.
*/
gboolean
e_book_is_writable (EBook *book)
@@ -2928,6 +3001,8 @@ e_book_is_writable (EBook *book)
* Check if this book is connected.
*
* Returns: %TRUE if this book is connected, otherwise %FALSE.
+ *
+ * Deprecated: 3.2: Use e_client_is_online() on an #EBookClient object instead.
**/
gboolean
e_book_is_online (EBook *book)
@@ -2986,6 +3061,8 @@ make_me_card (void)
* and set it in @contact and @book.
*
* Returns: %TRUE if successful, otherwise %FALSE.
+ *
+ * Deprecated: 3.2: Use e_book_client_get_self() instead.
**/
gboolean
e_book_get_self (EContact **contact, EBook **book, GError **error)
@@ -3053,6 +3130,8 @@ e_book_get_self (EContact **contact, EBook **book, GError **error)
* refers to the user of the address book.
*
* Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_book_client_set_self() instead.
**/
gboolean
e_book_set_self (EBook *book, EContact *contact, GError **error)
@@ -3076,6 +3155,8 @@ e_book_set_self (EBook *book, EContact *contact, GError **error)
* Check if @contact is the user of the address book.
*
* Returns: %TRUE if @contact is the user, %FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_book_client_is_self() instead.
**/
gboolean
e_book_is_self (EContact *contact)
@@ -3108,6 +3189,8 @@ e_book_is_self (EContact *contact)
* that will be loaded in the e_book_get_default_addressbook call.
*
* Returns: %TRUE if the setting was stored in libebook's ESourceList, otherwise %FALSE.
+ *
+ * Deprecated: 3.2: Use e_book_client_set_default_addressbook() instead.
*/
gboolean
e_book_set_default_addressbook (EBook *book, GError **error)
@@ -3134,6 +3217,8 @@ e_book_set_default_addressbook (EBook *book, GError **error)
* will be loaded in the e_book_get_default_addressbook call.
*
* Returns: %TRUE if the setting was stored in libebook's ESourceList, otherwise %FALSE.
+ *
+ * Deprecated: 3.2: Use e_book_client_set_default_source() instead.
*/
gboolean
e_book_set_default_source (ESource *source, GError **error)
@@ -3199,6 +3284,8 @@ e_book_set_default_source (ESource *source, GError **error)
* added to Evolution.
*
* Returns: %TRUE if @addressbook_sources was set, otherwise %FALSE.
+ *
+ * Deprecated: 3.2: Use e_book_client_get_sources() instead.
*/
gboolean
e_book_get_addressbooks (ESourceList **addressbook_sources, GError **error)
@@ -3224,6 +3311,8 @@ e_book_get_addressbooks (ESourceList **addressbook_sources, GError **error)
* e_book_open(), and e_book_remove().
*
* Returns: a new but unopened #EBook.
+ *
+ * Deprecated: 3.2: Use e_book_client_new() instead.
*/
EBook *
e_book_new (ESource *source, GError **error)
@@ -3250,7 +3339,7 @@ e_book_new (ESource *source, GError **error)
xml = e_source_to_standalone_xml (source);
- if (!e_gdbus_book_factory_call_get_book_sync (book_factory_proxy, e_util_ensure_gdbus_string (xml, &gdbus_xml), &path, NULL, &err)) {
+ if (!e_gdbus_book_factory_call_get_book_sync (G_DBUS_PROXY (book_factory_proxy), e_util_ensure_gdbus_string (xml, &gdbus_xml), &path, NULL, &err)) {
unwrap_gerror (err, &err);
g_free (xml);
g_free (gdbus_xml);
@@ -3264,12 +3353,12 @@ e_book_new (ESource *source, GError **error)
g_free (xml);
g_free (gdbus_xml);
- book->priv->gdbus_book = e_gdbus_book_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy)),
+ book->priv->gdbus_book = G_DBUS_PROXY (e_gdbus_book_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory_proxy)),
G_DBUS_PROXY_FLAGS_NONE,
ADDRESS_BOOK_DBUS_SERVICE_NAME,
path,
NULL,
- &err);
+ &err));
if (!book->priv->gdbus_book) {
g_free (path);
@@ -3294,8 +3383,8 @@ e_book_new (ESource *source, GError **error)
gdbus_book_connection_gone_cb, book, NULL);
g_signal_connect (connection, "closed", G_CALLBACK (gdbus_book_closed_cb), book);
- g_signal_connect (book->priv->gdbus_book, "writable", G_CALLBACK (writable_cb), book);
- g_signal_connect (book->priv->gdbus_book, "connection", G_CALLBACK (connection_cb), book);
+ g_signal_connect (book->priv->gdbus_book, "readonly", G_CALLBACK (readonly_cb), book);
+ g_signal_connect (book->priv->gdbus_book, "online", G_CALLBACK (online_cb), book);
g_signal_connect (book->priv->gdbus_book, "auth-required", G_CALLBACK (auth_required_cb), book);
return book;
@@ -3378,6 +3467,8 @@ check_uri (ESource *source, gpointer uri)
* documentation for e_book_new for further information.
*
* Returns: a new but unopened #EBook.
+ *
+ * Deprecated: 3.2: Use e_book_client_new_from_uri() instead.
*/
EBook *
e_book_new_from_uri (const gchar *uri, GError **error)
@@ -3447,6 +3538,8 @@ check_system (ESource *source, gpointer data)
* information.
*
* Returns: a new but unopened #EBook.
+ *
+ * Deprecated: 3.2: Use e_book_client_new_system() instead.
*/
EBook *
e_book_new_system_addressbook (GError **error)
@@ -3500,6 +3593,8 @@ e_book_new_system_addressbook (GError **error)
* further information.
*
* Returns: a new but unopened #EBook
+ *
+ * Deprecated: 3.2: Use e_book_client_new_default() instead.
*/
EBook *
e_book_new_default_addressbook (GError **error)
@@ -3539,6 +3634,7 @@ get_status_from_error (GError *error)
EBookStatus err_code;
} errors[] = {
{ err ("Success", E_BOOK_ERROR_OK) },
+ { err ("Busy", E_BOOK_ERROR_BUSY) },
{ err ("RepositoryOffline", E_BOOK_ERROR_REPOSITORY_OFFLINE) },
{ err ("PermissionDenied", E_BOOK_ERROR_PERMISSION_DENIED) },
{ err ("ContactNotFound", E_BOOK_ERROR_CONTACT_NOT_FOUND) },
@@ -3670,3 +3766,5 @@ array_to_elist (gchar **list)
return elst;
}
+
+#endif /* E_BOOK_DISABLE_DEPRECATED */
diff --git a/addressbook/libebook/e-book.h b/addressbook/libebook/e-book.h
index 17a10a2..4bdfc0e 100644
--- a/addressbook/libebook/e-book.h
+++ b/addressbook/libebook/e-book.h
@@ -11,6 +11,9 @@
#ifndef __E_BOOK_H__
#define __E_BOOK_H__
+/* e-book deprecated since 3.2, use e-book-client instead */
+#ifndef E_BOOK_DISABLE_DEPRECATED
+
#include <glib.h>
#include <glib-object.h>
@@ -411,4 +414,6 @@ GType e_book_get_type (void);
G_END_DECLS
+#endif /* E_BOOK_DISABLE_DEPRECATED */
+
#endif /* __E_BOOK_H__ */
diff --git a/addressbook/libedata-book/Makefile.am b/addressbook/libedata-book/Makefile.am
index 5975f8d..584151c 100644
--- a/addressbook/libedata-book/Makefile.am
+++ b/addressbook/libedata-book/Makefile.am
@@ -31,7 +31,6 @@ libedata_book_1_2_la_SOURCES = \
e-data-book-view.c \
e-data-book.c \
ximian-vcard.h \
- opid.c opid.h \
$(ENUM_GENERATED)
libedata_book_1_2_la_LIBADD = \
diff --git a/addressbook/libedata-book/e-book-backend-sync.c b/addressbook/libedata-book/e-book-backend-sync.c
index 1f0a134..a944554 100644
--- a/addressbook/libedata-book/e-book-backend-sync.c
+++ b/addressbook/libedata-book/e-book-backend-sync.c
@@ -15,7 +15,7 @@
G_DEFINE_TYPE (EBookBackendSync, e_book_backend_sync, E_TYPE_BOOK_BACKEND)
struct _EBookBackendSyncPrivate {
- gint mumble;
+ gint mumble;
};
static GObjectClass *parent_class;
@@ -35,10 +35,34 @@ e_book_backend_sync_construct (EBookBackendSync *backend)
}
/**
+ * e_book_backend_sync_open:
+ * @backend: an #EBookBackendSync
+ * @book: an #EDataBook
+ * @cancellable: a #GCancellable for the operation
+ * @only_if_exists: whether open only if exists
+ * @error: #GError to set, when something fails
+ *
+ * Opens @backend, which can involve connecting it to a remote server.
+ **/
+void
+e_book_backend_sync_open (EBookBackendSync *backend,
+ EDataBook *book,
+ GCancellable *cancellable,
+ gboolean only_if_exists,
+ GError **error)
+{
+ e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->open_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
+
+ (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->open_sync) (backend, book, cancellable, only_if_exists, error);
+}
+
+/**
* e_book_backend_sync_create_contact:
* @backend: an #EBookBackendSync
* @book: an #EDataBook
- * @opid: the unique ID of the operation
+ * @cancellable: a #GCancellable for the operation
* @vcard: a VCard representation of a contact
* @contact: a pointer to a location to store the resulting #EContact
* @error: #GError to set, when something fails
@@ -48,7 +72,7 @@ e_book_backend_sync_construct (EBookBackendSync *backend)
void
e_book_backend_sync_create_contact (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
const gchar *vcard,
EContact **contact,
GError **error)
@@ -57,17 +81,16 @@ e_book_backend_sync_create_contact (EBookBackendSync *backend,
e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (vcard, E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (contact, E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->create_contact_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
- g_assert (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->create_contact_sync);
-
- (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->create_contact_sync) (backend, book, opid, vcard, contact, error);
+ (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->create_contact_sync) (backend, book, cancellable, vcard, contact, error);
}
/**
* e_book_backend_sync_remove:
* @backend: an #EBookBackendSync
* @book: an #EDataBook
- * @opid: the unique ID of the operation
+ * @cancellable: a #GCancellable for the operation
* @error: #GError to set, when something fails
*
* Remove @book's database and storage overhead from the storage
@@ -76,23 +99,101 @@ e_book_backend_sync_create_contact (EBookBackendSync *backend,
void
e_book_backend_sync_remove (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
GError **error)
{
e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->remove_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
- g_assert (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->remove_sync);
+ (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->remove_sync) (backend, book, cancellable, error);
+}
- (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->remove_sync) (backend, book, opid, error);
+/**
+ * e_book_backend_sync_refresh:
+ * @backend: An EBookBackendSync object.
+ * @book: An EDataBook object.
+ * @cancellable: a #GCancellable for the operation
+ * @error: Out parameter for a #GError.
+ *
+ * Calls the refresh_sync method on the given backend.
+ *
+ * Since: 3.2
+ */
+void
+e_book_backend_sync_refresh (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, GError **error)
+{
+ e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->refresh_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
+
+ (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->refresh_sync) (backend, book, cancellable, error);
+}
+
+/**
+ * e_book_backend_sync_get_backend_property:
+ * @backend: an #EBookBackendSync
+ * @book: an #EDataBook
+ * @cancellable: a #GCancellable for the operation
+ * @prop_name: Property name whose value to retrieve.
+ * @prop_value: Return value of the @prop_name.
+ * @error: #GError to set, when something fails
+ *
+ * Calls the get_backend_property_sync method on the given backend.
+ *
+ * Returns whether processed this property. Returning FALSE means to pass
+ * the call to the EBookBackend parent class, thus neither @error should be
+ * set in this case.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_backend_sync_get_backend_property (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error)
+{
+ e_return_data_book_error_val_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_val_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_val_if_fail (prop_name, E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_val_if_fail (prop_value, E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_val_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_backend_property_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
+
+ return (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_backend_property_sync) (backend, book, cancellable, prop_name, prop_value, error);
+}
+
+/**
+ * e_book_backend_sync_set_backend_property:
+ * @backend: an #EBookBackendSync
+ * @book: an #EDataBook
+ * @cancellable: a #GCancellable for the operation
+ * @prop_name: Property name to set.
+ * @prop_value: New value of the @prop_name.
+ * @error: #GError to set, when something fails
+ *
+ * Calls the set_backend_property_sync method on the given backend.
+ *
+ * Returns whether processed this property. Returning FALSE means to pass
+ * the call to the EBookBackend parent class, thus neither @error should be
+ * set in this case.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_backend_sync_set_backend_property (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error)
+{
+ e_return_data_book_error_val_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_val_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_val_if_fail (prop_name, E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_val_if_fail (prop_value, E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_val_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->set_backend_property_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
+
+ return (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->set_backend_property_sync) (backend, book, cancellable, prop_name, prop_value, error);
}
/**
* e_book_backend_sync_remove_contacts:
* @backend: an #EBookBackendSync
* @book: an #EDataBook
- * @opid: the unique ID of the operation
- * @id_list: a #GList of pointers to unique contact ID strings
+ * @cancellable: a #GCancellable for the operation
+ * @id_list: a #GSList of pointers to unique contact ID strings
* @removed_ids: a pointer to a location to store a list of the contacts actually removed
* @error: #GError to set, when something fails
*
@@ -103,26 +204,25 @@ e_book_backend_sync_remove (EBookBackendSync *backend,
void
e_book_backend_sync_remove_contacts (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
- GList *id_list,
- GList **removed_ids,
+ GCancellable *cancellable,
+ const GSList *id_list,
+ GSList **removed_ids,
GError **error)
{
e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (id_list, E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (removed_ids, E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->remove_contacts_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
- g_assert (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->remove_contacts_sync);
-
- (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->remove_contacts_sync) (backend, book, opid, id_list, removed_ids, error);
+ (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->remove_contacts_sync) (backend, book, cancellable, id_list, removed_ids, error);
}
/**
* e_book_backend_sync_modify_contact:
* @backend: an #EBookBackendSync
* @book: an #EDataBook
- * @opid: the unique ID of the operation
+ * @cancellable: a #GCancellable for the operation
* @vcard: the string representation of a contact
* @contact: a pointer to a location to store the resulting #EContact
* @error: #GError to set, when something fails
@@ -133,7 +233,7 @@ e_book_backend_sync_remove_contacts (EBookBackendSync *backend,
void
e_book_backend_sync_modify_contact (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
const gchar *vcard,
EContact **contact,
GError **error)
@@ -142,17 +242,16 @@ e_book_backend_sync_modify_contact (EBookBackendSync *backend,
e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (vcard, E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (contact, E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->modify_contact_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
- g_assert (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->modify_contact_sync);
-
- (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->modify_contact_sync) (backend, book, opid, vcard, contact, error);
+ (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->modify_contact_sync) (backend, book, cancellable, vcard, contact, error);
}
/**
* e_book_backend_sync_get_contact:
* @backend: an #EBookBackendSync
* @book: an #EDataBook
- * @opid: the unique ID of the operation
+ * @cancellable: a #GCancellable for the operation
* @id: a unique contact ID
* @vcard: a pointer to a location to store the resulting VCard string
*
@@ -161,7 +260,7 @@ e_book_backend_sync_modify_contact (EBookBackendSync *backend,
void
e_book_backend_sync_get_contact (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
const gchar *id,
gchar **vcard,
GError **error)
@@ -170,17 +269,16 @@ e_book_backend_sync_get_contact (EBookBackendSync *backend,
e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (id, E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (vcard, E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_contact_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
- g_assert (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_contact_sync);
-
- (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_contact_sync) (backend, book, opid, id, vcard, error);
+ (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_contact_sync) (backend, book, cancellable, id, vcard, error);
}
/**
* e_book_backend_sync_get_contact_list:
* @backend: an #EBookBackendSync
* @book: an #EDataBook
- * @opid: the unique ID of the operation
+ * @cancellable: a #GCancellable for the operation
* @query: an s-expression of the query to perform
* @contacts: a pointer to a location to store the resulting list of VCard strings
* @error: #GError to set, when something fails
@@ -191,188 +289,115 @@ e_book_backend_sync_get_contact (EBookBackendSync *backend,
void
e_book_backend_sync_get_contact_list (EBookBackendSync *backend,
EDataBook *book,
- guint32 opid,
+ GCancellable *cancellable,
const gchar *query,
- GList **contacts,
+ GSList **contacts,
GError **error)
{
e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (query, E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (contacts, E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_contact_list_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
- g_assert (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_contact_list_sync);
-
- (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_contact_list_sync) (backend, book, opid, query, contacts, error);
+ (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_contact_list_sync) (backend, book, cancellable, query, contacts, error);
}
/**
- * e_book_backend_sync_get_changes:
+ * e_book_backend_sync_authenticate_user:
* @backend: an #EBookBackendSync
- * @book: an #EDataBook
- * @opid: the unique ID of the operation
- * @change_id: a unique changes ID
- * @changes: a pointer to a location to store the resulting list of changes
+ * @cancellable: a #GCancellable for the operation
+ * @credentials: an #ECredentials to authenticate with
* @error: #GError to set, when something fails
*
- * Gets the changes made to @book since the last call to this function.
- * The returned list will contain items of CORBA type
- * #EDataBookChange.
+ * Authenticates @backend with given @credentials.
**/
void
-e_book_backend_sync_get_changes (EBookBackendSync *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *change_id,
- GList **changes,
- GError **error)
+e_book_backend_sync_authenticate_user (EBookBackendSync *backend,
+ GCancellable *cancellable,
+ ECredentials *credentials,
+ GError **error)
{
e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (change_id, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (changes, E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_if_fail (credentials, E_DATA_BOOK_STATUS_INVALID_ARG);
+ e_return_data_book_error_if_fail (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->authenticate_user_sync, E_DATA_BOOK_STATUS_NOT_SUPPORTED);
- g_assert (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_changes_sync);
-
- (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_changes_sync) (backend, book, opid, change_id, changes, error);
+ (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->authenticate_user_sync) (backend, cancellable, credentials, error);
}
-/**
- * e_book_backend_sync_authenticate_user:
- * @backend: an #EBookBackendSync
- * @book: an #EDataBook
- * @opid: the unique ID of the operation
- * @user: the user's name
- * @passwd: the user's password
- * @auth_method: the authentication method desired
- * @error: #GError to set, when something fails
- *
- * Authenticates @user against @book.
- **/
-void
-e_book_backend_sync_authenticate_user (EBookBackendSync *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *user,
- const gchar *passwd,
- const gchar *auth_method,
- GError **error)
+static void
+book_backend_open (EBookBackend *backend,
+ EDataBook *book,
+ guint32 opid,
+ GCancellable *cancellable,
+ gboolean only_if_exists)
{
- e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (user && passwd && auth_method, E_DATA_BOOK_STATUS_INVALID_ARG);
+ GError *error = NULL;
- g_assert (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->authenticate_user_sync);
+ e_book_backend_sync_open (E_BOOK_BACKEND_SYNC (backend), book, cancellable, only_if_exists, &error);
- (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->authenticate_user_sync) (backend, book, opid, user, passwd, auth_method, error);
+ e_data_book_respond_open (book, opid, error);
}
-/**
- * e_book_backend_sync_get_required_fields:
- * @backend: an #EBookBackendSync
- * @book: an #EDataBook
- * @opid: the unique ID of the operation
- * @fields: a pointer to a location to store the fields
- * @error: #GError to set, when something fails
- *
- * Gets a list of the fields required for all contacts in @book. The
- * fields are represented by strings from #e_contact_field_name. The list
- * and its contents must be freed by the caller.
- **/
-void
-e_book_backend_sync_get_required_fields (EBookBackendSync *backend,
- EDataBook *book,
- guint32 opid,
- GList **fields,
- GError **error)
+static void
+book_backend_remove (EBookBackend *backend,
+ EDataBook *book,
+ guint32 opid,
+ GCancellable *cancellable)
{
- e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (fields, E_DATA_BOOK_STATUS_INVALID_ARG);
+ GError *error = NULL;
- g_assert (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_required_fields_sync);
+ e_book_backend_sync_remove (E_BOOK_BACKEND_SYNC (backend), book, cancellable, &error);
- (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_required_fields_sync) (backend, book, opid, fields, error);
+ e_data_book_respond_remove (book, opid, error);
}
-/**
- * e_book_backend_sync_get_supported_fields:
- * @backend: an #EBookBackendSync
- * @book: an #EDataBook
- * @opid: the unique ID of the operation
- * @fields: a pointer to a location to store the fields
- * @error: #GError to set, when something fails
- *
- * Gets a list of the fields supported for contacts in @book. Other fields
- * may not be stored. The fields are represented by strings from #e_contact_field_name.
- * The list and its contents must be freed by the caller.
- **/
-void
-e_book_backend_sync_get_supported_fields (EBookBackendSync *backend,
- EDataBook *book,
- guint32 opid,
- GList **fields,
- GError **error)
+static void
+book_backend_refresh (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
{
- e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (fields, E_DATA_BOOK_STATUS_INVALID_ARG);
+ GError *error = NULL;
- g_assert (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_supported_fields_sync);
+ e_book_backend_sync_refresh (E_BOOK_BACKEND_SYNC (backend), book, cancellable, &error);
- (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_supported_fields_sync) (backend, book, opid, fields, error);
+ e_data_book_respond_refresh (book, opid, error);
}
-/**
- * e_book_backend_sync_get_supported_auth_methods:
- * @backend: an #EBookBackendSync
- * @book: an #EDataBook
- * @opid: the unique ID of the operation
- * @methods: a pointer to a location to store the methods
- * @error: #GError to set, when something fails
- *
- * Gets a list of the authentication methods supported by @book. The
- * methods are represented by strings. The list and its contents must
- * be freed by the caller.
- **/
-void
-e_book_backend_sync_get_supported_auth_methods (EBookBackendSync *backend,
- EDataBook *book,
- guint32 opid,
- GList **methods,
- GError **error)
+static void
+book_backend_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
{
- e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_SYNC (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (methods, E_DATA_BOOK_STATUS_INVALID_ARG);
+ GError *error = NULL;
+ gchar *prop_value = NULL;
- g_assert (E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_supported_auth_methods_sync);
+ if (e_book_backend_sync_get_backend_property (E_BOOK_BACKEND_SYNC (backend), book, cancellable, prop_name, &prop_value, &error))
+ e_data_book_respond_get_backend_property (book, opid, error, prop_value);
+ else
+ (* E_BOOK_BACKEND_CLASS (e_book_backend_sync_parent_class)->get_backend_property) (backend, book, opid, cancellable, prop_name);
- (* E_BOOK_BACKEND_SYNC_GET_CLASS (backend)->get_supported_auth_methods_sync) (backend, book, opid, methods, error);
+ g_free (prop_value);
}
static void
-_e_book_backend_remove (EBookBackend *backend,
- EDataBook *book,
- guint32 opid)
+book_backend_set_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value)
{
- GError *error = NULL;;
-
- e_book_backend_sync_remove (E_BOOK_BACKEND_SYNC (backend), book, opid, &error);
+ GError *error = NULL;
- e_data_book_respond_remove (book, opid, error);
+ if (e_book_backend_sync_set_backend_property (E_BOOK_BACKEND_SYNC (backend), book, cancellable, prop_name, prop_value, &error))
+ e_data_book_respond_set_backend_property (book, opid, error);
+ else
+ (* E_BOOK_BACKEND_CLASS (e_book_backend_sync_parent_class)->set_backend_property) (backend, book, opid, cancellable, prop_name, prop_value);
}
static void
-_e_book_backend_create_contact (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *vcard)
+book_backend_create_contact (EBookBackend *backend,
+ EDataBook *book,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *vcard)
{
GError *error = NULL;
EContact *contact = NULL;
- e_book_backend_sync_create_contact (E_BOOK_BACKEND_SYNC (backend), book, opid, vcard, &contact, &error);
+ e_book_backend_sync_create_contact (E_BOOK_BACKEND_SYNC (backend), book, cancellable, vcard, &contact, &error);
e_data_book_respond_create (book, opid, error, contact);
@@ -381,32 +406,36 @@ _e_book_backend_create_contact (EBookBackend *backend,
}
static void
-_e_book_backend_remove_contacts (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- GList *id_list)
+book_backend_remove_contacts (EBookBackend *backend,
+ EDataBook *book,
+ guint32 opid,
+ GCancellable *cancellable,
+ const GSList *id_list)
{
GError *error = NULL;
- GList *ids = NULL;
+ GSList *ids = NULL;
- e_book_backend_sync_remove_contacts (E_BOOK_BACKEND_SYNC (backend), book, opid, id_list, &ids, &error);
+ e_book_backend_sync_remove_contacts (E_BOOK_BACKEND_SYNC (backend), book, cancellable, id_list, &ids, &error);
e_data_book_respond_remove_contacts (book, opid, error, ids);
- if (ids)
- g_list_free (ids);
+ if (ids) {
+ g_slist_foreach (ids, (GFunc) g_free, NULL);
+ g_slist_free (ids);
+ }
}
static void
-_e_book_backend_modify_contact (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *vcard)
+book_backend_modify_contact (EBookBackend *backend,
+ EDataBook *book,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *vcard)
{
GError *error = NULL;
EContact *contact = NULL;
- e_book_backend_sync_modify_contact (E_BOOK_BACKEND_SYNC (backend), book, opid, vcard, &contact, &error);
+ e_book_backend_sync_modify_contact (E_BOOK_BACKEND_SYNC (backend), book, cancellable, vcard, &contact, &error);
e_data_book_respond_modify (book, opid, error, contact);
@@ -415,15 +444,16 @@ _e_book_backend_modify_contact (EBookBackend *backend,
}
static void
-_e_book_backend_get_contact (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *id)
+book_backend_get_contact (EBookBackend *backend,
+ EDataBook *book,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *id)
{
GError *error = NULL;
gchar *vcard = NULL;
- e_book_backend_sync_get_contact (E_BOOK_BACKEND_SYNC (backend), book, opid, id, &vcard, &error);
+ e_book_backend_sync_get_contact (E_BOOK_BACKEND_SYNC (backend), book, cancellable, id, &vcard, &error);
e_data_book_respond_get_contact (book, opid, error, vcard);
@@ -432,100 +462,47 @@ _e_book_backend_get_contact (EBookBackend *backend,
}
static void
-_e_book_backend_get_contact_list (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *query)
+book_backend_get_contact_list (EBookBackend *backend,
+ EDataBook *book,
+ guint32 opid,
+ GCancellable *cancellable,
+ const gchar *query)
{
GError *error = NULL;
- GList *cards = NULL;
+ GSList *cards = NULL;
- e_book_backend_sync_get_contact_list (E_BOOK_BACKEND_SYNC (backend), book, opid, query, &cards, &error);
+ e_book_backend_sync_get_contact_list (E_BOOK_BACKEND_SYNC (backend), book, cancellable, query, &cards, &error);
e_data_book_respond_get_contact_list (book, opid, error, cards);
-}
-
-static void
-_e_book_backend_get_changes (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *change_id)
-{
- GError *error = NULL;
- GList *changes = NULL;
-
- e_book_backend_sync_get_changes (E_BOOK_BACKEND_SYNC (backend), book, opid, change_id, &changes, &error);
-
- e_data_book_respond_get_changes (book, opid, error, changes);
-}
-
-static void
-_e_book_backend_authenticate_user (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *user,
- const gchar *passwd,
- const gchar *auth_method)
-{
- GError *error = NULL;
-
- e_book_backend_sync_authenticate_user (E_BOOK_BACKEND_SYNC (backend), book, opid, user, passwd, auth_method, &error);
- e_data_book_respond_authenticate_user (book, opid, error);
+ g_slist_foreach (cards, (GFunc) g_free, NULL);
+ g_slist_free (cards);
}
static void
-_e_book_backend_get_required_fields (EBookBackend *backend,
- EDataBook *book,
- guint32 opid)
+book_backend_authenticate_user (EBookBackend *backend,
+ GCancellable *cancellable,
+ ECredentials *credentials)
{
GError *error = NULL;
- GList *fields = NULL;
-
- e_book_backend_sync_get_required_fields (E_BOOK_BACKEND_SYNC (backend), book, opid, &fields, &error);
- e_data_book_respond_get_required_fields (book, opid, error, fields);
+ e_book_backend_sync_authenticate_user (E_BOOK_BACKEND_SYNC (backend), cancellable, credentials, &error);
- if (fields) {
- g_list_foreach (fields, (GFunc) g_free, NULL);
- g_list_free (fields);
- }
+ e_book_backend_notify_opened (backend, error);
}
-static void
-_e_book_backend_get_supported_fields (EBookBackend *backend,
- EDataBook *book,
- guint32 opid)
+static gboolean
+book_backend_sync_get_backend_property (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error)
{
- GError *error = NULL;
- GList *fields = NULL;
-
- e_book_backend_sync_get_supported_fields (E_BOOK_BACKEND_SYNC (backend), book, opid, &fields, &error);
-
- e_data_book_respond_get_supported_fields (book, opid, error, fields);
-
- if (fields) {
- g_list_foreach (fields, (GFunc) g_free, NULL);
- g_list_free (fields);
- }
+ /* to indicate to pass to the EBookBackend parent class */
+ return FALSE;
}
-static void
-_e_book_backend_get_supported_auth_methods (EBookBackend *backend,
- EDataBook *book,
- guint32 opid)
+static gboolean
+book_backend_sync_set_backend_property (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error)
{
- GError *error = NULL;
- GList *methods = NULL;
-
- e_book_backend_sync_get_supported_auth_methods (E_BOOK_BACKEND_SYNC (backend), book, opid, &methods, &error);
-
- e_data_book_respond_get_supported_auth_methods (book, opid, error, methods);
-
- if (methods) {
- g_list_foreach (methods, (GFunc) g_free, NULL);
- g_list_free (methods);
- }
+ /* to indicate to pass to the EBookBackend parent class */
+ return FALSE;
}
static void
@@ -563,18 +540,20 @@ e_book_backend_sync_class_init (EBookBackendSyncClass *klass)
parent_class = g_type_class_peek_parent (klass);
object_class = (GObjectClass *) klass;
-
- backend_class->remove = _e_book_backend_remove;
- backend_class->create_contact = _e_book_backend_create_contact;
- backend_class->remove_contacts = _e_book_backend_remove_contacts;
- backend_class->modify_contact = _e_book_backend_modify_contact;
- backend_class->get_contact = _e_book_backend_get_contact;
- backend_class->get_contact_list = _e_book_backend_get_contact_list;
- backend_class->get_changes = _e_book_backend_get_changes;
- backend_class->authenticate_user = _e_book_backend_authenticate_user;
- backend_class->get_required_fields = _e_book_backend_get_required_fields;
- backend_class->get_supported_fields = _e_book_backend_get_supported_fields;
- backend_class->get_supported_auth_methods = _e_book_backend_get_supported_auth_methods;
-
object_class->dispose = e_book_backend_sync_dispose;
+
+ backend_class->open = book_backend_open;
+ backend_class->authenticate_user = book_backend_authenticate_user;
+ backend_class->remove = book_backend_remove;
+ backend_class->refresh = book_backend_refresh;
+ backend_class->get_backend_property = book_backend_get_backend_property;
+ backend_class->set_backend_property = book_backend_set_backend_property;
+ backend_class->create_contact = book_backend_create_contact;
+ backend_class->remove_contacts = book_backend_remove_contacts;
+ backend_class->modify_contact = book_backend_modify_contact;
+ backend_class->get_contact = book_backend_get_contact;
+ backend_class->get_contact_list = book_backend_get_contact_list;
+
+ klass->get_backend_property_sync = book_backend_sync_get_backend_property;
+ klass->set_backend_property_sync = book_backend_sync_set_backend_property;
}
diff --git a/addressbook/libedata-book/e-book-backend-sync.h b/addressbook/libedata-book/e-book-backend-sync.h
index 16fb4fb..7f37d04 100644
--- a/addressbook/libedata-book/e-book-backend-sync.h
+++ b/addressbook/libedata-book/e-book-backend-sync.h
@@ -29,67 +29,36 @@ struct _EBookBackendSyncClass {
EBookBackendClass parent_class;
/* Virtual methods */
- void (*remove_sync) (EBookBackendSync *backend, EDataBook *book, guint32 opid, GError **perror);
- void (*create_contact_sync) (EBookBackendSync *backend, EDataBook *book,
- guint32 opid,
- const gchar *vcard, EContact **contact, GError **perror);
- void (*remove_contacts_sync) (EBookBackendSync *backend, EDataBook *book,
- guint32 opid,
- GList *id_list, GList **removed_ids, GError **perror);
- void (*modify_contact_sync) (EBookBackendSync *backend, EDataBook *book,
- guint32 opid,
- const gchar *vcard, EContact **contact, GError **perror);
- void (*get_contact_sync) (EBookBackendSync *backend, EDataBook *book,
- guint32 opid,
- const gchar *id, gchar **vcard, GError **perror);
- void (*get_contact_list_sync) (EBookBackendSync *backend, EDataBook *book,
- guint32 opid,
- const gchar *query, GList **contacts, GError **perror);
- void (*get_changes_sync) (EBookBackendSync *backend, EDataBook *book,
- guint32 opid,
- const gchar *change_id, GList **changes, GError **perror);
- void (*authenticate_user_sync) (EBookBackendSync *backend, EDataBook *book,
- guint32 opid,
- const gchar *user,
- const gchar *passwd,
- const gchar *auth_method, GError **perror);
-
- void (*get_required_fields_sync) (EBookBackendSync *backend, EDataBook *book,
- guint32 opid,
- GList **fields, GError **perror);
-
- void (*get_supported_fields_sync) (EBookBackendSync *backend, EDataBook *book,
- guint32 opid,
- GList **fields, GError **perror);
- void (*get_supported_auth_methods_sync) (EBookBackendSync *backend, EDataBook *book,
- guint32 opid,
- GList **methods, GError **perror);
-
- /* Padding for future expansion */
- void (*_pas_reserved0) (void);
- void (*_pas_reserved1) (void);
- void (*_pas_reserved2) (void);
- void (*_pas_reserved3) (void);
- void (*_pas_reserved4) (void);
-
+ void (*open_sync) (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, gboolean only_if_exists, GError **error);
+ void (*remove_sync) (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, GError **error);
+ void (* refresh_sync) (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, GError **error);
+ gboolean (*get_backend_property_sync) (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error);
+ gboolean (*set_backend_property_sync) (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error);
+ void (*create_contact_sync) (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *vcard, EContact **contact, GError **error);
+ void (*remove_contacts_sync) (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const GSList *id_list, GSList **removed_ids, GError **error);
+ void (*modify_contact_sync) (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *vcard, EContact **contact, GError **error);
+ void (*get_contact_sync) (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *id, gchar **vcard, GError **error);
+ void (*get_contact_list_sync) (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *query, GSList **contacts, GError **error);
+
+ void (*authenticate_user_sync) (EBookBackendSync *backend, GCancellable *cancellable, ECredentials *credentials, GError **error);
};
-gboolean e_book_backend_sync_construct (EBookBackendSync *backend);
+GType e_book_backend_sync_get_type (void);
-GType e_book_backend_sync_get_type (void);
+gboolean e_book_backend_sync_construct (EBookBackendSync *backend);
-void e_book_backend_sync_remove (EBookBackendSync *backend, EDataBook *book, guint32 opid, GError **perror);
-void e_book_backend_sync_create_contact (EBookBackendSync *backend, EDataBook *book, guint32 opid, const gchar *vcard, EContact **contact, GError **perror);
-void e_book_backend_sync_remove_contacts (EBookBackendSync *backend, EDataBook *book, guint32 opid, GList *id_list, GList **removed_ids, GError **perror);
-void e_book_backend_sync_modify_contact (EBookBackendSync *backend, EDataBook *book, guint32 opid, const gchar *vcard, EContact **contact, GError **perror);
-void e_book_backend_sync_get_contact (EBookBackendSync *backend, EDataBook *book, guint32 opid, const gchar *id, gchar **vcard, GError **perror);
-void e_book_backend_sync_get_contact_list (EBookBackendSync *backend, EDataBook *book, guint32 opid, const gchar *query, GList **contacts, GError **perror);
-void e_book_backend_sync_get_changes (EBookBackendSync *backend, EDataBook *book, guint32 opid, const gchar *change_id, GList **changes, GError **perror);
-void e_book_backend_sync_authenticate_user (EBookBackendSync *backend, EDataBook *book, guint32 opid, const gchar *user, const gchar *passwd, const gchar *auth_method, GError **perror);
+void e_book_backend_sync_open (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, gboolean only_if_exists, GError **error);
+void e_book_backend_sync_remove (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, GError **error);
+void e_book_backend_sync_refresh (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, GError **error);
+gboolean e_book_backend_sync_get_backend_property(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error);
+gboolean e_book_backend_sync_set_backend_property(EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error);
+void e_book_backend_sync_create_contact (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *vcard, EContact **contact, GError **error);
+void e_book_backend_sync_remove_contacts (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const GSList *id_list, GSList **removed_ids, GError **error);
+void e_book_backend_sync_modify_contact (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *vcard, EContact **contact, GError **error);
+void e_book_backend_sync_get_contact (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *id, gchar **vcard, GError **error);
+void e_book_backend_sync_get_contact_list (EBookBackendSync *backend, EDataBook *book, GCancellable *cancellable, const gchar *query, GSList **contacts, GError **error);
-void e_book_backend_sync_get_required_fields (EBookBackendSync *backend, EDataBook *book, guint32 opid, GList **fields, GError **perror);
-void e_book_backend_sync_get_supported_fields (EBookBackendSync *backend, EDataBook *book, guint32 opid, GList **fields, GError **perror);
-void e_book_backend_sync_get_supported_auth_methods (EBookBackendSync *backend, EDataBook *book, guint32 opid, GList **methods, GError **perror);
+void e_book_backend_sync_authenticate_user (EBookBackendSync *backend, GCancellable *cancellable, ECredentials *credentials, GError **error);
G_END_DECLS
diff --git a/addressbook/libedata-book/e-book-backend.c b/addressbook/libedata-book/e-book-backend.c
index ad0492b..204e53a 100644
--- a/addressbook/libedata-book/e-book-backend.c
+++ b/addressbook/libedata-book/e-book-backend.c
@@ -8,23 +8,25 @@
#include <config.h>
+#include <glib/gi18n-lib.h>
+
#include <libedataserver/e-data-server-util.h>
#include "e-data-book-view.h"
#include "e-data-book.h"
#include "e-book-backend.h"
-struct _EBookBackendPrivate {
- GMutex *open_mutex;
+#define EDB_OPENING_ERROR e_data_book_create_error (E_DATA_BOOK_STATUS_BUSY, _("Cannot process, book backend is opening"))
+struct _EBookBackendPrivate {
GMutex *clients_mutex;
- GList *clients;
+ GSList *clients;
ESource *source;
- gboolean loaded, writable, removed, online;
+ gboolean opening, opened, readonly, removed, online;
GMutex *views_mutex;
- EList *views;
+ GSList *views;
gchar *cache_dir;
};
@@ -70,6 +72,40 @@ book_backend_set_default_cache_dir (EBookBackend *backend)
}
static void
+book_backend_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_BOOK_BACKEND (backend));
+ g_return_if_fail (book != NULL);
+ g_return_if_fail (prop_name != NULL);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_OPENED)) {
+ e_data_book_respond_get_backend_property (book, opid, NULL, e_book_backend_is_opened (backend) ? "TRUE" : "FALSE");
+ } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_OPENING)) {
+ e_data_book_respond_get_backend_property (book, opid, NULL, e_book_backend_is_opening (backend) ? "TRUE" : "FALSE");
+ } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_ONLINE)) {
+ e_data_book_respond_get_backend_property (book, opid, NULL, e_book_backend_is_online (backend) ? "TRUE" : "FALSE");
+ } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_READONLY)) {
+ e_data_book_respond_get_backend_property (book, opid, NULL, e_book_backend_is_readonly (backend) ? "TRUE" : "FALSE");
+ } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CACHE_DIR)) {
+ e_data_book_respond_get_backend_property (book, opid, NULL, e_book_backend_get_cache_dir (backend));
+ } else {
+ e_data_book_respond_get_backend_property (book, opid, e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_NOT_SUPPORTED, _("Unknown book property '%s'"), prop_name), NULL);
+ }
+}
+
+static void
+book_backend_set_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_BOOK_BACKEND (backend));
+ g_return_if_fail (book != NULL);
+ g_return_if_fail (prop_name != NULL);
+
+ e_data_book_respond_set_backend_property (book, opid, e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_NOT_SUPPORTED, _("Cannot change value of book property '%s'"), prop_name));
+}
+
+static void
book_backend_set_property (GObject *object,
guint property_id,
const GValue *value,
@@ -111,7 +147,7 @@ book_backend_dispose (GObject *object)
priv = E_BOOK_BACKEND (object)->priv;
if (priv->views != NULL) {
- g_object_unref (priv->views);
+ g_slist_free (priv->views);
priv->views = NULL;
}
@@ -131,9 +167,8 @@ book_backend_finalize (GObject *object)
priv = E_BOOK_BACKEND (object)->priv;
- g_list_free (priv->clients);
+ g_slist_free (priv->clients);
- g_mutex_free (priv->open_mutex);
g_mutex_free (priv->clients_mutex);
g_mutex_free (priv->views_mutex);
@@ -144,18 +179,21 @@ book_backend_finalize (GObject *object)
}
static void
-e_book_backend_class_init (EBookBackendClass *class)
+e_book_backend_class_init (EBookBackendClass *klass)
{
GObjectClass *object_class;
- g_type_class_add_private (class, sizeof (EBookBackendPrivate));
+ g_type_class_add_private (klass, sizeof (EBookBackendPrivate));
- object_class = G_OBJECT_CLASS (class);
+ object_class = G_OBJECT_CLASS (klass);
object_class->set_property = book_backend_set_property;
object_class->get_property = book_backend_get_property;
object_class->dispose = book_backend_dispose;
object_class->finalize = book_backend_finalize;
+ klass->get_backend_property = book_backend_get_backend_property;
+ klass->set_backend_property = book_backend_set_backend_property;
+
g_object_class_install_property (
object_class,
PROP_CACHE_DIR,
@@ -182,11 +220,10 @@ e_book_backend_init (EBookBackend *backend)
backend->priv = G_TYPE_INSTANCE_GET_PRIVATE (
backend, E_TYPE_BOOK_BACKEND, EBookBackendPrivate);
- backend->priv->views = e_list_new (
- (EListCopyFunc) NULL, (EListFreeFunc) NULL, NULL);
-
- backend->priv->open_mutex = g_mutex_new ();
+ backend->priv->clients = NULL;
backend->priv->clients_mutex = g_mutex_new ();
+
+ backend->priv->views = NULL;
backend->priv->views_mutex = g_mutex_new ();
}
@@ -216,7 +253,7 @@ e_book_backend_get_cache_dir (EBookBackend *backend)
* Sets the cache directory for the given backend.
*
* Note that #EBookBackend is initialized with a usable default based on
- * the #ESource given to e_book_backend_load_source(). Backends should
+ * the #ESource given to e_book_backend_open(). Backends should
* not override the default without good reason.
*
* Since: 2.32
@@ -235,48 +272,6 @@ e_book_backend_set_cache_dir (EBookBackend *backend,
}
/**
- * e_book_backend_load_source:
- * @backend: an #EBookBackend
- * @source: an #ESource to load
- * @only_if_exists: %TRUE to prevent the creation of a new book
- * @error: #GError to set, when something fails
- *
- * Loads @source into @backend.
- **/
-void
-e_book_backend_load_source (EBookBackend *backend,
- ESource *source,
- gboolean only_if_exists,
- GError **error)
-{
- GError *local_error = NULL;
-
- e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (source, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (backend->priv->loaded == FALSE, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- /* Subclasses may need to call e_book_backend_get_cache_dir() in
- * their load_source() methods, so get the "cache-dir" property
- * initialized before we call the method. */
- backend->priv->source = g_object_ref (source);
- book_backend_set_default_cache_dir (backend);
-
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->load_source);
-
- g_object_ref (backend);
-
- (* E_BOOK_BACKEND_GET_CLASS (backend)->load_source) (backend, source, only_if_exists, &local_error);
-
- g_object_unref (backend);
-
- if (g_error_matches (local_error, E_DATA_BOOK_ERROR,
- E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION))
- g_error_free (local_error);
- else if (local_error != NULL)
- g_propagate_error (error, local_error);
-}
-
-/**
* e_book_backend_get_source:
* @backend: An addressbook backend.
*
@@ -297,67 +292,154 @@ e_book_backend_get_source (EBookBackend *backend)
* @backend: an #EBookBackend
* @book: an #EDataBook
* @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @only_if_exists: %TRUE to prevent the creation of a new book
*
* Executes an 'open' request specified by @opid on @book
- * using @backend.
+ * using @backend. This call might be finished
+ * with e_data_book_respond_open() or e_book_backend_respond_opened(),
+ * though the overall opening phase finishes only after call
+ * of e_book_backend_notify_opened() after which call the backend
+ * is either fully opened (including authentication against (remote)
+ * server/storage) or an error was encountered during this opening phase.
+ * 'opened' and 'opening' properties are updated automatically.
+ * The backend refuses all other operations until the opening phase is finished.
+ *
+ * The e_book_backend_notify_opened() is called either from this function
+ * or from e_book_backend_authenticate_user(), or after necessary steps
+ * initiated by these two functions.
+ *
+ * The opening phase usually works like this:
+ * 1) client requests open for the backend
+ * 2) server receives this request and calls e_book_backend_open() - the opening phase begun
+ * 3) either the backend is opened during this call, and notifies client
+ * with e_book_backend_notify_opened() about that. This is usually
+ * for local backends; their opening phase is finished
+ * 4) or the backend requires authentication, thus it notifies client
+ * about that with e_book_backend_notify_auth_required() and is
+ * waiting for credentials, which will be received from client
+ * by e_book_backend_authenticate_user() call. Backend's opening
+ * phase is still running in this case, thus it doesn't call
+ * e_book_backend_notify_opened() within e_book_backend_open() call.
+ * 5) when backend receives credentials in e_book_backend_authenticate_user()
+ * then it tries to authenticate against a server/storage with them
+ * and only after it knows result of the authentication, whether user
+ * was or wasn't authenticated, it notifies client with the result
+ * by e_book_backend_notify_opened() and it's opening phase is
+ * finished now. If there was no error returned then the backend is
+ * considered opened, otherwise it's considered closed. Use AuthenticationFailed
+ * error when the given credentials were rejected by the server/store, which
+ * will result in a re-prompt on the client side, otherwise use AuthenticationRequired
+ * if there was anything wrong with the given credentials. Set error's
+ * message to a reason for a re-prompt, it'll be shown to a user.
+ * 6) client checks error returned from e_book_backend_notify_opened() and
+ * reprompts for a password if it was AuthenticationFailed. Otherwise
+ * considers backend opened based on the error presence (no error means success).
+ *
+ * In any case, the call of e_book_backend_open() should be always finished
+ * with e_data_book_respond_open(), which has no influence on the opening phase,
+ * or alternatively with e_book_backend_respond_opened(). Never use authentication
+ * errors in e_data_book_respond_open() to notify the client the authentication is
+ * required, there is e_book_backend_notify_auth_required() for this.
**/
void
e_book_backend_open (EBookBackend *backend,
EDataBook *book,
guint32 opid,
+ GCancellable *cancellable,
gboolean only_if_exists)
{
g_return_if_fail (E_IS_BOOK_BACKEND (backend));
g_return_if_fail (E_IS_DATA_BOOK (book));
- g_mutex_lock (backend->priv->open_mutex);
+ g_mutex_lock (backend->priv->clients_mutex);
- if (backend->priv->loaded) {
- e_data_book_report_writable (book, backend->priv->writable);
- e_data_book_report_connection_status (book, backend->priv->online);
+ if (e_book_backend_is_opened (backend)) {
+ g_mutex_unlock (backend->priv->clients_mutex);
- e_data_book_respond_open (book, opid, NULL);
+ e_data_book_report_readonly (book, backend->priv->readonly);
+ e_data_book_report_online (book, backend->priv->online);
+
+ e_book_backend_respond_opened (backend, book, opid, NULL);
+ } else if (e_book_backend_is_opening (backend)) {
+ g_mutex_unlock (backend->priv->clients_mutex);
+
+ e_data_book_respond_open (book, opid, EDB_OPENING_ERROR);
} else {
- GError *error = NULL;
+ ESource *source = e_data_book_get_source (book);
- e_book_backend_load_source (backend, e_data_book_get_source (book), only_if_exists, &error);
+ backend->priv->opening = TRUE;
+ g_mutex_unlock (backend->priv->clients_mutex);
- if (!error || g_error_matches (error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION)) {
- e_data_book_report_writable (book, backend->priv->writable);
- e_data_book_report_connection_status (book, backend->priv->online);
- }
+ g_return_if_fail (source != NULL);
- e_data_book_respond_open (book, opid, error);
- }
+ /* Subclasses may need to call e_book_backend_get_cache_dir() in
+ * their open() methods, so get the "cache-dir" property
+ * initialized before we call the method. */
+ backend->priv->source = g_object_ref (source);
+ book_backend_set_default_cache_dir (backend);
- g_mutex_unlock (backend->priv->open_mutex);
+ g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->open != NULL);
+
+ (* E_BOOK_BACKEND_GET_CLASS (backend)->open) (backend, book, opid, cancellable, only_if_exists);
+ }
}
/**
* e_book_backend_remove:
* @backend: an #EBookBackend
* @book: an #EDataBook
+ * @cancellable: a #GCancellable for the operation
* @opid: the ID to use for this operation
*
* Executes a 'remove' request to remove all of @backend's data,
* specified by @opid on @book.
+ * This might be finished with e_data_book_respond_remove().
**/
void
e_book_backend_remove (EBookBackend *backend,
EDataBook *book,
- guint32 opid)
+ guint32 opid,
+ GCancellable *cancellable)
{
g_return_if_fail (E_IS_BOOK_BACKEND (backend));
g_return_if_fail (E_IS_DATA_BOOK (book));
+ g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->remove);
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->remove);
-
- g_object_ref (backend);
+ if (e_book_backend_is_opening (backend))
+ e_data_book_respond_remove (book, opid, EDB_OPENING_ERROR);
+ else
+ (* E_BOOK_BACKEND_GET_CLASS (backend)->remove) (backend, book, opid, cancellable);
+}
- (* E_BOOK_BACKEND_GET_CLASS (backend)->remove) (backend, book, opid);
+/**
+ * e_book_backend_refresh:
+ * @backend: an #EBookBackend
+ * @book: an #EDataBook
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ *
+ * Refreshes the address book being accessed by the given backend.
+ * This might be finished with e_data_book_respond_refresh(),
+ * and it might be called as soon as possible; it doesn't mean
+ * that the refreshing is done after calling that, the backend
+ * is only notifying client whether it started the refresh process
+ * or not.
+ *
+ * Since: 3.2
+ **/
+void
+e_book_backend_refresh (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_BOOK_BACKEND (backend));
- g_object_unref (backend);
+ if (e_book_backend_is_opening (backend))
+ e_data_book_respond_refresh (book, opid, EDB_OPENING_ERROR);
+ else if (!E_BOOK_BACKEND_GET_CLASS (backend)->refresh)
+ e_data_book_respond_refresh (book, opid, e_data_book_create_error (E_DATA_BOOK_STATUS_NOT_SUPPORTED, NULL));
+ else
+ (* E_BOOK_BACKEND_GET_CLASS (backend)->refresh) (backend, book, opid, cancellable);
}
/**
@@ -365,28 +447,29 @@ e_book_backend_remove (EBookBackend *backend,
* @backend: an #EBookBackend
* @book: an #EDataBook
* @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @vcard: the VCard to add
*
* Executes a 'create contact' request specified by @opid on @book
* using @backend.
+ * This might be finished with e_data_book_respond_create().
**/
void
e_book_backend_create_contact (EBookBackend *backend,
EDataBook *book,
guint32 opid,
+ GCancellable *cancellable,
const gchar *vcard)
{
g_return_if_fail (E_IS_BOOK_BACKEND (backend));
g_return_if_fail (E_IS_DATA_BOOK (book));
g_return_if_fail (vcard);
+ g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->create_contact);
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->create_contact);
-
- g_object_ref (backend);
-
- (* E_BOOK_BACKEND_GET_CLASS (backend)->create_contact) (backend, book, opid, vcard);
-
- g_object_unref (backend);
+ if (e_book_backend_is_opening (backend))
+ e_data_book_respond_create (book, opid, EDB_OPENING_ERROR, NULL);
+ else
+ (* E_BOOK_BACKEND_GET_CLASS (backend)->create_contact) (backend, book, opid, cancellable, vcard);
}
/**
@@ -394,28 +477,29 @@ e_book_backend_create_contact (EBookBackend *backend,
* @backend: an #EBookBackend
* @book: an #EDataBook
* @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @id_list: list of string IDs to remove
*
* Executes a 'remove contacts' request specified by @opid on @book
* using @backend.
+ * This might be finished with e_data_book_respond_remove_contacts().
**/
void
e_book_backend_remove_contacts (EBookBackend *backend,
EDataBook *book,
guint32 opid,
- GList *id_list)
+ GCancellable *cancellable,
+ const GSList *id_list)
{
g_return_if_fail (E_IS_BOOK_BACKEND (backend));
g_return_if_fail (E_IS_DATA_BOOK (book));
g_return_if_fail (id_list);
+ g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->remove_contacts);
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->remove_contacts);
-
- g_object_ref (backend);
-
- (* E_BOOK_BACKEND_GET_CLASS (backend)->remove_contacts) (backend, book, opid, id_list);
-
- g_object_unref (backend);
+ if (e_book_backend_is_opening (backend))
+ e_data_book_respond_remove_contacts (book, opid, EDB_OPENING_ERROR, NULL);
+ else
+ (* E_BOOK_BACKEND_GET_CLASS (backend)->remove_contacts) (backend, book, opid, cancellable, id_list);
}
/**
@@ -423,28 +507,29 @@ e_book_backend_remove_contacts (EBookBackend *backend,
* @backend: an #EBookBackend
* @book: an #EDataBook
* @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @vcard: the VCard to update
*
* Executes a 'modify contact' request specified by @opid on @book
* using @backend.
+ * This might be finished with e_data_book_respond_modify().
**/
void
e_book_backend_modify_contact (EBookBackend *backend,
EDataBook *book,
guint32 opid,
+ GCancellable *cancellable,
const gchar *vcard)
{
g_return_if_fail (E_IS_BOOK_BACKEND (backend));
g_return_if_fail (E_IS_DATA_BOOK (book));
g_return_if_fail (vcard);
+ g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->modify_contact);
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->modify_contact);
-
- g_object_ref (backend);
-
- (* E_BOOK_BACKEND_GET_CLASS (backend)->modify_contact) (backend, book, opid, vcard);
-
- g_object_unref (backend);
+ if (e_book_backend_is_opening (backend))
+ e_data_book_respond_modify (book, opid, EDB_OPENING_ERROR, NULL);
+ else
+ (* E_BOOK_BACKEND_GET_CLASS (backend)->modify_contact) (backend, book, opid, cancellable, vcard);
}
/**
@@ -452,28 +537,29 @@ e_book_backend_modify_contact (EBookBackend *backend,
* @backend: an #EBookBackend
* @book: an #EDataBook
* @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @id: the ID of the contact to get
*
* Executes a 'get contact' request specified by @opid on @book
* using @backend.
+ * This might be finished with e_data_book_respond_get_contact().
**/
void
e_book_backend_get_contact (EBookBackend *backend,
EDataBook *book,
guint32 opid,
+ GCancellable *cancellable,
const gchar *id)
{
g_return_if_fail (E_IS_BOOK_BACKEND (backend));
g_return_if_fail (E_IS_DATA_BOOK (book));
g_return_if_fail (id);
+ g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->get_contact);
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->get_contact);
-
- g_object_ref (backend);
-
- (* E_BOOK_BACKEND_GET_CLASS (backend)->get_contact) (backend, book, opid, id);
-
- g_object_unref (backend);
+ if (e_book_backend_is_opening (backend))
+ e_data_book_respond_get_contact (book, opid, EDB_OPENING_ERROR, NULL);
+ else
+ (* E_BOOK_BACKEND_GET_CLASS (backend)->get_contact) (backend, book, opid, cancellable, id);
}
/**
@@ -481,28 +567,29 @@ e_book_backend_get_contact (EBookBackend *backend,
* @backend: an #EBookBackend
* @book: an #EDataBook
* @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @query: the s-expression to match
*
* Executes a 'get contact list' request specified by @opid on @book
* using @backend.
+ * This might be finished with e_data_book_respond_get_contact_list().
**/
void
e_book_backend_get_contact_list (EBookBackend *backend,
EDataBook *book,
guint32 opid,
+ GCancellable *cancellable,
const gchar *query)
{
g_return_if_fail (E_IS_BOOK_BACKEND (backend));
g_return_if_fail (E_IS_DATA_BOOK (book));
g_return_if_fail (query);
+ g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->get_contact_list);
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->get_contact_list);
-
- g_object_ref (backend);
-
- (* E_BOOK_BACKEND_GET_CLASS (backend)->get_contact_list) (backend, book, opid, query);
-
- g_object_unref (backend);
+ if (e_book_backend_is_opening (backend))
+ e_data_book_respond_get_contact_list (book, opid, EDB_OPENING_ERROR, NULL);
+ else
+ (* E_BOOK_BACKEND_GET_CLASS (backend)->get_contact_list) (backend, book, opid, cancellable, query);
}
/**
@@ -519,14 +606,9 @@ e_book_backend_start_book_view (EBookBackend *backend,
{
g_return_if_fail (E_IS_BOOK_BACKEND (backend));
g_return_if_fail (E_IS_DATA_BOOK_VIEW (book_view));
-
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->start_book_view);
-
- g_object_ref (backend);
+ g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->start_book_view);
(* E_BOOK_BACKEND_GET_CLASS (backend)->start_book_view) (backend, book_view);
-
- g_object_unref (backend);
}
/**
@@ -543,181 +625,40 @@ e_book_backend_stop_book_view (EBookBackend *backend,
{
g_return_if_fail (E_IS_BOOK_BACKEND (backend));
g_return_if_fail (E_IS_DATA_BOOK_VIEW (book_view));
-
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->stop_book_view);
-
- g_object_ref (backend);
+ g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->stop_book_view);
(* E_BOOK_BACKEND_GET_CLASS (backend)->stop_book_view) (backend, book_view);
-
- g_object_unref (backend);
-}
-
-/**
- * e_book_backend_get_changes:
- * @backend: an #EBookBackend
- * @book: an #EDataBook
- * @opid: the ID to use for this operation
- * @change_id: the ID of the changeset
- *
- * Executes a 'get changes' request specified by @opid on @book
- * using @backend.
- **/
-void
-e_book_backend_get_changes (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *change_id)
-{
- g_return_if_fail (E_IS_BOOK_BACKEND (backend));
- g_return_if_fail (E_IS_DATA_BOOK (book));
- g_return_if_fail (change_id);
-
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->get_changes);
-
- g_object_ref (backend);
-
- (* E_BOOK_BACKEND_GET_CLASS (backend)->get_changes) (backend, book, opid, change_id);
-
- g_object_unref (backend);
}
/**
* e_book_backend_authenticate_user:
* @backend: an #EBookBackend
- * @book: an #EDataBook
- * @opid: the ID to use for this operation
- * @user: the name of the user account
- * @passwd: the user's password
- * @auth_method: the authentication method to use
+ * @cancellable: a #GCancellable for the operation
+ * @credentials: #ECredentials to use for authentication
*
- * Executes an 'authenticate' request specified by @opid on @book
- * using @backend.
- **/
-void
-e_book_backend_authenticate_user (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *user,
- const gchar *passwd,
- const gchar *auth_method)
-{
- g_return_if_fail (E_IS_BOOK_BACKEND (backend));
- g_return_if_fail (E_IS_DATA_BOOK (book));
- g_return_if_fail (user && passwd && auth_method);
-
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->authenticate_user);
-
- g_object_ref (backend);
-
- (* E_BOOK_BACKEND_GET_CLASS (backend)->authenticate_user) (backend, book, opid, user, passwd, auth_method);
-
- g_object_unref (backend);
-}
-
-/**
- * e_book_backend_get_required_fields:
- * @backend: an #EBookBackend
- * @book: an #EDataBook
- * @opid: the ID to use for this operation
+ * Notifies @backend about @credentials provided by user to use
+ * for authentication. This notification is usually called during
+ * opening phase as a response to e_book_backend_notify_auth_required()
+ * on the client side and it results in setting property 'opening' to %TRUE
+ * unless the backend is already opened. This function finishes opening
+ * phase, thus it should be finished with e_book_backend_notify_opened().
*
- * Executes a 'get required fields' request specified by @opid on @book
- * using @backend.
+ * See information at e_book_backend_open() for more details
+ * how the opening phase works.
**/
void
-e_book_backend_get_required_fields (EBookBackend *backend,
- EDataBook *book,
- guint32 opid)
-
-{
- g_return_if_fail (E_IS_BOOK_BACKEND (backend));
- g_return_if_fail (E_IS_DATA_BOOK (book));
-
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->get_required_fields);
-
- g_object_ref (backend);
-
- (* E_BOOK_BACKEND_GET_CLASS (backend)->get_required_fields) (backend, book, opid);
-
- g_object_unref (backend);
-}
-
-/**
- * e_book_backend_get_supported_fields:
- * @backend: an #EBookBackend
- * @book: an #EDataBook
- * @opid: the ID to use for this operation
- *
- * Executes a 'get supported fields' request specified by @opid on @book
- * using @backend.
- **/
-void
-e_book_backend_get_supported_fields (EBookBackend *backend,
- EDataBook *book,
- guint32 opid)
-
-{
- g_return_if_fail (E_IS_BOOK_BACKEND (backend));
- g_return_if_fail (E_IS_DATA_BOOK (book));
-
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->get_supported_fields);
-
- g_object_ref (backend);
-
- (* E_BOOK_BACKEND_GET_CLASS (backend)->get_supported_fields) (backend, book, opid);
-
- g_object_unref (backend);
-}
-
-/**
- * e_book_backend_get_supported_auth_methods:
- * @backend: an #EBookBackend
- * @book: an #EDataBook
- * @opid: the ID to use for this operation
- *
- * Executes a 'get supported auth methods' request specified by @opid on @book
- * using @backend.
- **/
-void
-e_book_backend_get_supported_auth_methods (EBookBackend *backend,
- EDataBook *book,
- guint32 opid)
+e_book_backend_authenticate_user (EBookBackend *backend,
+ GCancellable *cancellable,
+ ECredentials *credentials)
{
g_return_if_fail (E_IS_BOOK_BACKEND (backend));
- g_return_if_fail (E_IS_DATA_BOOK (book));
-
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->get_supported_auth_methods);
-
- g_object_ref (backend);
-
- (* E_BOOK_BACKEND_GET_CLASS (backend)->get_supported_auth_methods) (backend, book, opid);
-
- g_object_unref (backend);
-}
-
-/**
- * e_book_backend_cancel_operation:
- * @backend: an #EBookBackend
- * @book: an #EDataBook whose operation should be cancelled
- * @error: #GError to set, when something fails
- *
- * Cancel @book's running operation on @backend.
- **/
-void
-e_book_backend_cancel_operation (EBookBackend *backend,
- EDataBook *book,
- GError **error)
-{
- e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND (backend), E_DATA_BOOK_STATUS_INVALID_ARG);
- e_return_data_book_error_if_fail (E_IS_DATA_BOOK (book), E_DATA_BOOK_STATUS_INVALID_ARG);
-
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->cancel_operation);
-
- g_object_ref (backend);
+ g_return_if_fail (credentials != NULL);
+ g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->authenticate_user);
- (* E_BOOK_BACKEND_GET_CLASS (backend)->cancel_operation) (backend, book, error);
+ if (backend->priv->opened)
+ backend->priv->opening = TRUE;
- g_object_unref (backend);
+ (* E_BOOK_BACKEND_GET_CLASS (backend)->authenticate_user) (backend, cancellable, credentials);
}
static void
@@ -727,22 +668,6 @@ last_client_gone (EBookBackend *backend)
}
/**
- * e_book_backend_get_book_views:
- * @backend: an #EBookBackend
- *
- * Gets the list of #EDataBookView views running on this backend.
- *
- * Returns: An #EList of #EDataBookView objects.
- **/
-EList*
-e_book_backend_get_book_views (EBookBackend *backend)
-{
- g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), NULL);
-
- return g_object_ref (backend->priv->views);
-}
-
-/**
* e_book_backend_add_book_view:
* @backend: an #EBookBackend
* @view: an #EDataBookView
@@ -757,7 +682,7 @@ e_book_backend_add_book_view (EBookBackend *backend,
g_mutex_lock (backend->priv->views_mutex);
- e_list_append (backend->priv->views, view);
+ backend->priv->views = g_slist_append (backend->priv->views, view);
g_mutex_unlock (backend->priv->views_mutex);
}
@@ -777,7 +702,7 @@ e_book_backend_remove_book_view (EBookBackend *backend,
g_mutex_lock (backend->priv->views_mutex);
- e_list_remove (backend->priv->views, view);
+ backend->priv->views = g_slist_remove (backend->priv->views, view);
g_mutex_unlock (backend->priv->views_mutex);
}
@@ -799,7 +724,7 @@ e_book_backend_add_client (EBookBackend *backend,
g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
g_mutex_lock (backend->priv->clients_mutex);
- backend->priv->clients = g_list_prepend (backend->priv->clients, book);
+ backend->priv->clients = g_slist_prepend (backend->priv->clients, book);
g_mutex_unlock (backend->priv->clients_mutex);
return TRUE;
@@ -826,7 +751,7 @@ e_book_backend_remove_client (EBookBackend *backend,
/* Disconnect */
g_mutex_lock (backend->priv->clients_mutex);
- backend->priv->clients = g_list_remove (backend->priv->clients, book);
+ backend->priv->clients = g_slist_remove (backend->priv->clients, book);
/* When all clients go away, notify the parent factory about it so that
* it may decide whether to kill the backend or not.
@@ -840,108 +765,162 @@ e_book_backend_remove_client (EBookBackend *backend,
}
/**
- * e_book_backend_has_out_of_proc_clients:
+ * e_book_backend_foreach_view:
* @backend: an #EBookBackend
+ * @callback: callback to call
+ * @user_data: user_data passed into the @callback
*
- * Checks if @backend has clients running in other system processes.
- *
- * Returns: %TRUE if there are clients in other processes, %FALSE otherwise.
+ * Calls @callback for each known book view of this @backend.
+ * @callback returns %FALSE to stop further processing.
**/
-gboolean
-e_book_backend_has_out_of_proc_clients (EBookBackend *backend)
+void
+e_book_backend_foreach_view (EBookBackend *backend, gboolean (* callback) (EDataBookView *view, gpointer user_data), gpointer user_data)
{
- return TRUE;
+ const GSList *views;
+ EDataBookView *view;
+ gboolean stop = FALSE;
+
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (callback != NULL);
+
+ g_mutex_lock (backend->priv->views_mutex);
+
+ for (views = backend->priv->views; views && !stop; views = views->next) {
+ view = E_DATA_BOOK_VIEW (views->data);
+
+ e_data_book_view_ref (view);
+ stop = !callback (view, user_data);
+ e_data_book_view_unref (view);
+ }
+
+ g_mutex_unlock (backend->priv->views_mutex);
}
/**
- * e_book_backend_get_static_capabilities:
+ * e_book_backend_get_book_backend_property:
* @backend: an #EBookBackend
+ * @book: an #EDataBook
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @prop_name: property name to get value of; cannot be NULL
*
- * Gets the capabilities offered by this @backend.
+ * Calls the get_backend_property method on the given backend.
+ * This might be finished with e_data_book_respond_get_backend_property().
+ * Default implementation takes care of common properties and returns
+ * an 'unsupported' error for any unknown properties. The subclass may
+ * always call this default implementation for properties which fetching
+ * it doesn't overwrite.
*
- * Returns: A string listing the capabilities.
+ * Since: 3.2
**/
-gchar *
-e_book_backend_get_static_capabilities (EBookBackend *backend)
+void
+e_book_backend_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
{
- gchar *capabilities;
-
- g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), NULL);
-
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->get_static_capabilities);
-
- g_object_ref (backend);
+ g_return_if_fail (E_IS_BOOK_BACKEND (backend));
+ g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->get_backend_property);
- capabilities = E_BOOK_BACKEND_GET_CLASS (backend)->get_static_capabilities (backend);
+ E_BOOK_BACKEND_GET_CLASS (backend)->get_backend_property (backend, book, opid, cancellable, prop_name);
+}
- g_object_unref (backend);
+/**
+ * e_book_backend_set_backend_property:
+ * @backend: an #EBookBackend
+ * @book: an #EDataBook
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @prop_name: property name to change; cannot be NULL
+ * @prop_value: value to set to @prop_name; cannot be NULL
+ *
+ * Calls the set_backend_property method on the given backend.
+ * This might be finished with e_data_book_respond_set_backend_property().
+ * Default implementation simply returns an 'unsupported' error.
+ * The subclass may always call this default implementation for properties
+ * which fetching it doesn't overwrite.
+ *
+ * Since: 3.2
+ **/
+void
+e_book_backend_set_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_BOOK_BACKEND (backend));
+ g_return_if_fail (prop_name != NULL);
+ g_return_if_fail (prop_value != NULL);
+ g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->set_backend_property != NULL);
- return capabilities;
+ E_BOOK_BACKEND_GET_CLASS (backend)->set_backend_property (backend, book, opid, cancellable, prop_name, prop_value);
}
/**
- * e_book_backend_is_loaded:
+ * e_book_backend_is_online:
* @backend: an #EBookBackend
*
- * Checks if @backend's storage has been opened and the backend
- * itself is ready for accessing.
+ * Checks if @backend's storage is online.
*
- * Returns: %TRUE if loaded, %FALSE otherwise.
+ * Returns: %TRUE if online, %FALSE otherwise.
**/
gboolean
-e_book_backend_is_loaded (EBookBackend *backend)
+e_book_backend_is_online (EBookBackend *backend)
{
g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), FALSE);
- return backend->priv->loaded;
+ return backend->priv->online;
}
/**
- * e_book_backend_set_is_loaded:
+ * e_book_backend_is_opened:
* @backend: an #EBookBackend
- * @is_loaded: A flag indicating whether the backend is loaded
*
- * Sets the flag indicating whether @backend is loaded to @is_loaded.
- * Meant to be used by backend implementations.
+ * Checks if @backend's storage has been opened (and
+ * authenticated, if necessary) and the backend itself
+ * is ready for accessing. This property is changed automatically
+ * within call of e_book_backend_notify_opened().
+ *
+ * Returns: %TRUE if fully opened, %FALSE otherwise.
**/
-void
-e_book_backend_set_is_loaded (EBookBackend *backend, gboolean is_loaded)
+gboolean
+e_book_backend_is_opened (EBookBackend *backend)
{
- g_return_if_fail (E_IS_BOOK_BACKEND (backend));
+ g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), FALSE);
- backend->priv->loaded = is_loaded;
+ return backend->priv->opened;
}
/**
- * e_book_backend_is_writable:
+ * e_book_backend_is_opening:
* @backend: an #EBookBackend
*
- * Checks if we can write to @backend.
+ * Checks if @backend is processing its opening phase, which
+ * includes everything since the e_book_backend_open() call,
+ * through authentication, up to e_book_backend_notify_opened().
+ * This property is managed automatically and the backend deny
+ * every operation except of cancel and authenticate_user while
+ * it is being opening.
*
- * Returns: %TRUE if writeable, %FALSE if not.
+ * Returns: %TRUE if opening phase is in the effect, %FALSE otherwise.
**/
gboolean
-e_book_backend_is_writable (EBookBackend *backend)
+e_book_backend_is_opening (EBookBackend *backend)
{
g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), FALSE);
- return backend->priv->writable;
+ return backend->priv->opening;
}
/**
- * e_book_backend_set_is_writable:
+ * e_book_backend_is_readonly:
* @backend: an #EBookBackend
- * @is_writable: A flag indicating whether the backend is writeable
*
- * Sets the flag indicating whether @backend is writeable to @is_writeable.
- * Meant to be used by backend implementations.
+ * Checks if we can write to @backend.
+ *
+ * Returns: %TRUE if writeable, %FALSE if not.
**/
-void
-e_book_backend_set_is_writable (EBookBackend *backend, gboolean is_writable)
+gboolean
+e_book_backend_is_readonly (EBookBackend *backend)
{
- g_return_if_fail (E_IS_BOOK_BACKEND (backend));
+ g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), FALSE);
- backend->priv->writable = is_writable;
+ return backend->priv->readonly;
}
/**
@@ -977,26 +956,19 @@ e_book_backend_set_is_removed (EBookBackend *backend, gboolean is_removed)
}
/**
- * e_book_backend_set_mode:
+ * e_book_backend_set_online:
* @backend: an #EBookbackend
- * @mode: a mode indicating the online/offline status of the backend
+ * @is_online: a mode indicating the online/offline status of the backend
*
- * Sets @backend's online/offline mode to @mode. Mode can be 1 for offline
- * or 2 indicating that it is connected and online.
+ * Sets @backend's online/offline mode to @is_online.
**/
void
-e_book_backend_set_mode (EBookBackend *backend,
- EDataBookMode mode)
+e_book_backend_set_online (EBookBackend *backend, gboolean is_online)
{
g_return_if_fail (E_IS_BOOK_BACKEND (backend));
+ g_return_if_fail (E_BOOK_BACKEND_GET_CLASS (backend)->set_online);
- g_assert (E_BOOK_BACKEND_GET_CLASS (backend)->set_mode);
-
- g_object_ref (backend);
-
- (* E_BOOK_BACKEND_GET_CLASS (backend)->set_mode) (backend, mode);
-
- g_object_unref (backend);
+ (* E_BOOK_BACKEND_GET_CLASS (backend)->set_online) (backend, is_online);
}
/**
@@ -1022,98 +994,14 @@ e_book_backend_sync (EBookBackend *backend)
g_object_unref (backend);
}
-/**
- * e_book_backend_change_add_new:
- * @vcard: a VCard string
- *
- * Creates a new change item indicating @vcard was added.
- * Meant to be used by backend implementations.
- *
- * Returns: A new #EDataBookChange.
- **/
-EDataBookChange *
-e_book_backend_change_add_new (const gchar *vcard)
-{
- EDataBookChange *new_change = g_new (EDataBookChange, 1);
-
- new_change->change_type = E_DATA_BOOK_BACKEND_CHANGE_ADDED;
- new_change->vcard = g_strdup (vcard);
-
- return new_change;
-}
-
-/**
- * e_book_backend_change_modify_new:
- * @vcard: a VCard string
- *
- * Creates a new change item indicating @vcard was modified.
- * Meant to be used by backend implementations.
- *
- * Returns: A new #EDataBookChange.
- **/
-EDataBookChange *
-e_book_backend_change_modify_new (const gchar *vcard)
-{
- EDataBookChange *new_change = g_new (EDataBookChange, 1);
-
- new_change->change_type = E_DATA_BOOK_BACKEND_CHANGE_MODIFIED;
- new_change->vcard = g_strdup (vcard);
-
- return new_change;
-}
-
-/**
- * e_book_backend_change_delete_new:
- * @vcard: a VCard string
- *
- * Creates a new change item indicating @vcard was deleted.
- * Meant to be used by backend implementations.
- *
- * Returns: A new #EDataBookChange.
- **/
-EDataBookChange *
-e_book_backend_change_delete_new (const gchar *vcard)
-{
- EDataBookChange *new_change = g_new (EDataBookChange, 1);
-
- new_change->change_type = E_DATA_BOOK_BACKEND_CHANGE_DELETED;
- new_change->vcard = g_strdup (vcard);
-
- return new_change;
-}
-
-static void
-e_book_backend_foreach_view (EBookBackend *backend,
- void (*callback) (EDataBookView *, gpointer),
- gpointer user_data)
-{
- EList *views;
- EDataBookView *view;
- EIterator *iter;
-
- views = e_book_backend_get_book_views (backend);
- iter = e_list_get_iterator (views);
-
- while (e_iterator_is_valid (iter)) {
- view = (EDataBookView*) e_iterator_get (iter);
-
- e_data_book_view_ref (view);
- callback (view, user_data);
- e_data_book_view_unref (view);
-
- e_iterator_next (iter);
- }
-
- g_object_unref (iter);
- g_object_unref (views);
-}
-
-static void
+static gboolean
view_notify_update (EDataBookView *view, gpointer contact)
{
e_data_book_view_notify_update (view, contact);
+
+ return TRUE;
}
/**
@@ -1129,15 +1017,17 @@ view_notify_update (EDataBookView *view, gpointer contact)
* contacts are created or modified by another (non-PAS-using) client.
**/
void
-e_book_backend_notify_update (EBookBackend *backend, EContact *contact)
+e_book_backend_notify_update (EBookBackend *backend, const EContact *contact)
{
- e_book_backend_foreach_view (backend, view_notify_update, contact);
+ e_book_backend_foreach_view (backend, view_notify_update, (gpointer) contact);
}
-static void
+static gboolean
view_notify_remove (EDataBookView *view, gpointer id)
{
e_data_book_view_notify_remove (view, id);
+
+ return TRUE;
}
/**
@@ -1158,10 +1048,12 @@ e_book_backend_notify_remove (EBookBackend *backend, const gchar *id)
e_book_backend_foreach_view (backend, view_notify_remove, (gpointer) id);
}
-static void
+static gboolean
view_notify_complete (EDataBookView *view, gpointer unused)
{
e_data_book_view_notify_complete (view, NULL /* SUCCESS */);
+
+ return TRUE;
}
/**
@@ -1180,31 +1072,56 @@ e_book_backend_notify_complete (EBookBackend *backend)
/**
- * e_book_backend_notify_writable:
+ * e_book_backend_notify_error:
* @backend: an #EBookBackend
- * @is_writable: flag indicating writable status
+ * @message: an error message
*
- * Notifies all backends clients about the current writable state.
+ * Notifies each backend listener about an error. This is meant to be used
+ * for cases where is no GError return possibility, to notify user about
+ * an issue.
**/
void
-e_book_backend_notify_writable (EBookBackend *backend, gboolean is_writable)
+e_book_backend_notify_error (EBookBackend *backend, const gchar *message)
{
EBookBackendPrivate *priv;
- GList *clients;
+ GSList *clients;
priv = backend->priv;
- priv->writable = is_writable;
+
g_mutex_lock (priv->clients_mutex);
- for (clients = priv->clients; clients != NULL; clients = g_list_next (clients))
- e_data_book_report_writable (E_DATA_BOOK (clients->data), is_writable);
+ for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
+ e_data_book_report_error (E_DATA_BOOK (clients->data), message);
+
+ g_mutex_unlock (priv->clients_mutex);
+}
+
+/**
+ * e_book_backend_notify_readonly:
+ * @backend: an #EBookBackend
+ * @is_readonly: flag indicating readonly status
+ *
+ * Notifies all backend's clients about the current readonly state.
+ **/
+void
+e_book_backend_notify_readonly (EBookBackend *backend, gboolean is_readonly)
+{
+ EBookBackendPrivate *priv;
+ GSList *clients;
+
+ priv = backend->priv;
+ priv->readonly = is_readonly;
+ g_mutex_lock (priv->clients_mutex);
+
+ for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
+ e_data_book_report_readonly (E_DATA_BOOK (clients->data), is_readonly);
g_mutex_unlock (priv->clients_mutex);
}
/**
- * e_book_backend_notify_connection_status:
+ * e_book_backend_notify_online:
* @backend: an #EBookBackend
* @is_online: flag indicating whether @backend is connected and online
*
@@ -1212,17 +1129,17 @@ e_book_backend_notify_writable (EBookBackend *backend, gboolean is_writable)
* Meant to be used by backend implementations.
**/
void
-e_book_backend_notify_connection_status (EBookBackend *backend, gboolean is_online)
+e_book_backend_notify_online (EBookBackend *backend, gboolean is_online)
{
EBookBackendPrivate *priv;
- GList *clients;
+ GSList *clients;
priv = backend->priv;
priv->online = is_online;
g_mutex_lock (priv->clients_mutex);
- for (clients = priv->clients; clients != NULL; clients = g_list_next (clients))
- e_data_book_report_connection_status (E_DATA_BOOK (clients->data), is_online);
+ for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
+ e_data_book_report_online (E_DATA_BOOK (clients->data), is_online);
g_mutex_unlock (priv->clients_mutex);
}
@@ -1230,21 +1147,110 @@ e_book_backend_notify_connection_status (EBookBackend *backend, gboolean is_onli
/**
* e_book_backend_notify_auth_required:
* @backend: an #EBookBackend
+ * @is_self: Use %TRUE to indicate the authentication is required
+ * for the @backend, otheriwse the authentication is for any
+ * other source. Having @credentials %NULL means @is_self
+ * automatically.
+ * @credentials: an #ECredentials that contains extra information for
+ * a source for which authentication is requested.
+ * This parameter can be %NULL to indicate "for this book".
*
* Notifies clients that @backend requires authentication in order to
- * connect. Means to be used by backend implementations.
+ * connect. This function call does not influence 'opening', but
+ * influences 'opened' property, which is set to %FALSE when @is_self
+ * is %TRUE or @credentials is %NULL. Opening phase is finished
+ * by e_book_backend_notify_opened() if this is requested for @backend.
+ *
+ * See e_book_backend_open() for a description how the whole opening
+ * phase works.
+ *
+ * Meant to be used by backend implementations.
+ **/
+void
+e_book_backend_notify_auth_required (EBookBackend *backend, gboolean is_self, const ECredentials *credentials)
+{
+ EBookBackendPrivate *priv;
+ GSList *clients;
+
+ priv = backend->priv;
+ g_mutex_lock (priv->clients_mutex);
+
+ if (is_self || !credentials)
+ priv->opened = FALSE;
+
+ for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
+ e_data_book_report_auth_required (E_DATA_BOOK (clients->data), credentials);
+
+ g_mutex_unlock (priv->clients_mutex);
+}
+
+/**
+ * e_book_backend_notify_opened:
+ * @backend: an #EBookBackend
+ * @error: a #GError corresponding to the error encountered during
+ * the opening phase. Use %NULL for success. The @error is freed
+ * automatically if not %NULL.
+ *
+ * Notifies clients that @backend finished its opening phase.
+ * See e_book_backend_open() for more information how the opening
+ * phase works. Calling this function changes 'opening' property,
+ * same as 'opened'. 'opening' is set to %FALSE and the backend
+ * is considered 'opened' only if the @error is %NULL.
+ *
+ * See also: e_book_backend_respond_opened()
+ *
+ * Note: The @error is freed automatically if not %NULL.
+ *
+ * Meant to be used by backend implementations.
**/
void
-e_book_backend_notify_auth_required (EBookBackend *backend)
+e_book_backend_notify_opened (EBookBackend *backend, GError *error)
{
EBookBackendPrivate *priv;
- GList *clients;
+ GSList *clients;
priv = backend->priv;
g_mutex_lock (priv->clients_mutex);
- for (clients = priv->clients; clients != NULL; clients = g_list_next (clients))
- e_data_book_report_auth_required (E_DATA_BOOK (clients->data));
+ priv->opening = FALSE;
+ priv->opened = error == NULL;
+
+ for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
+ e_data_book_report_opened (E_DATA_BOOK (clients->data), error);
+
g_mutex_unlock (priv->clients_mutex);
+
+ if (error)
+ g_error_free (error);
}
+/**
+ * e_book_backend_respond_opened:
+ * @backend: an #EBookBackend
+ * @book: an #EDataBook
+ * @opid: an operation ID
+ * @error: result error; can be %NULL, if it isn't then it's automatically freed
+ *
+ * This is a replacement for e_data_book_respond_open() for cases where
+ * the finish of 'open' method call also finishes backend opening phase.
+ * This function covers calling of both e_data_book_respond_open() and
+ * e_book_backend_notify_opened() with the same @error.
+ *
+ * See e_book_backend_open() for more details how the opening phase works.
+ **/
+void
+e_book_backend_respond_opened (EBookBackend *backend, EDataBook *book, guint32 opid, GError *error)
+{
+ GError *copy = NULL;
+
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_BOOK_BACKEND (backend));
+ g_return_if_fail (book != NULL);
+ g_return_if_fail (opid != 0);
+
+ if (error)
+ copy = g_error_copy (error);
+
+ e_data_book_respond_open (book, opid, error);
+ e_book_backend_notify_opened (backend, copy);
+}
diff --git a/addressbook/libedata-book/e-book-backend.h b/addressbook/libedata-book/e-book-backend.h
index 6d96b1a..ad8be78 100644
--- a/addressbook/libedata-book/e-book-backend.h
+++ b/addressbook/libedata-book/e-book-backend.h
@@ -24,11 +24,13 @@
#include <glib.h>
#include <glib-object.h>
+#include <gio/gio.h>
+
#include <libebook/e-contact.h>
#include <libedata-book/e-data-book-types.h>
#include <libedata-book/e-data-book.h>
-#include <libedataserver/e-list.h>
#include <libedataserver/e-source.h>
+#include <libedataserver/e-credentials.h>
G_BEGIN_DECLS
@@ -39,6 +41,16 @@ G_BEGIN_DECLS
#define E_IS_BOOK_BACKEND_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_BOOK_BACKEND))
#define E_BOOK_BACKEND_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((k), E_TYPE_BOOK_BACKEND, EBookBackendClass))
+#define CLIENT_BACKEND_PROPERTY_OPENED "opened"
+#define CLIENT_BACKEND_PROPERTY_OPENING "opening"
+#define CLIENT_BACKEND_PROPERTY_ONLINE "online"
+#define CLIENT_BACKEND_PROPERTY_READONLY "readonly"
+#define CLIENT_BACKEND_PROPERTY_CACHE_DIR "cache-dir"
+#define CLIENT_BACKEND_PROPERTY_CAPABILITIES "capabilities"
+#define BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS "required-fields"
+#define BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS "supported-fields"
+#define BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS "supported-auth-methods"
+
typedef struct _EBookBackendPrivate EBookBackendPrivate;
struct _EBookBackend {
@@ -50,153 +62,82 @@ struct _EBookBackendClass {
GObjectClass parent_class;
/* Virtual methods */
- void (*load_source) (EBookBackend *backend, ESource *source, gboolean only_if_exists, GError **error);
- void (*remove) (EBookBackend *backend, EDataBook *book, guint32 opid);
- gchar *(*get_static_capabilities) (EBookBackend *backend);
-
- void (*create_contact) (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *vcard);
- void (*remove_contacts) (EBookBackend *backend, EDataBook *book, guint32 opid, GList *id_list);
- void (*modify_contact) (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *vcard);
- void (*get_contact) (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *id);
- void (*get_contact_list) (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *query);
- void (*start_book_view) (EBookBackend *backend, EDataBookView *book_view);
- void (*stop_book_view) (EBookBackend *backend, EDataBookView *book_view);
- void (*get_changes) (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *change_id);
- void (*authenticate_user) (EBookBackend *backend, EDataBook *book, guint32 opid, const gchar *user, const gchar *passwd, const gchar *auth_method);
- void (*get_required_fields) (EBookBackend *backend, EDataBook *bokk, guint32 opid);
- void (*get_supported_fields) (EBookBackend *backend, EDataBook *book, guint32 opid);
- void (*get_supported_auth_methods) (EBookBackend *backend, EDataBook *book, guint32 opid);
- void (*cancel_operation) (EBookBackend *backend, EDataBook *book, GError **error);
- void (*set_mode) (EBookBackend *backend, EDataBookMode mode);
+ void (* get_backend_property) (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name);
+ void (* set_backend_property) (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value);
- /* Notification signals */
- void (* last_client_gone) (EBookBackend *backend);
+ void (* open) (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, gboolean only_if_exists);
+ void (* remove) (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
+ void (* set_online) (EBookBackend *backend, gboolean is_online);
+ void (* authenticate_user) (EBookBackend *backend, GCancellable *cancellable, ECredentials *credentials);
- void (*sync) (EBookBackend *backend);
+ void (* refresh) (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
+ void (* create_contact) (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *vcard);
+ void (* remove_contacts) (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const GSList *id_list);
+ void (* modify_contact) (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *vcard);
+ void (* get_contact) (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *id);
+ void (* get_contact_list) (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *query);
- /* Padding for future expansion */
- void (*_pas_reserved1) (void);
- void (*_pas_reserved2) (void);
- void (*_pas_reserved3) (void);
- void (*_pas_reserved4) (void);
+ void (* start_book_view) (EBookBackend *backend, EDataBookView *book_view);
+ void (* stop_book_view) (EBookBackend *backend, EDataBookView *book_view);
+
+ /* Notification signals */
+ void (* last_client_gone) (EBookBackend *backend);
+ void (* sync) (EBookBackend *backend);
};
-const gchar *e_book_backend_get_cache_dir (EBookBackend *backend);
-void e_book_backend_set_cache_dir (EBookBackend *backend,
- const gchar *cache_dir);
-
-void e_book_backend_load_source (EBookBackend *backend,
- ESource *source,
- gboolean only_if_exists,
- GError **error);
-ESource *e_book_backend_get_source (EBookBackend *backend);
-
-gboolean e_book_backend_add_client (EBookBackend *backend,
- EDataBook *book);
-void e_book_backend_remove_client (EBookBackend *backend,
- EDataBook *book);
-gboolean e_book_backend_has_out_of_proc_clients (EBookBackend *backend);
-gchar *e_book_backend_get_static_capabilities (EBookBackend *backend);
-
-gboolean e_book_backend_is_loaded (EBookBackend *backend);
-
-gboolean e_book_backend_is_writable (EBookBackend *backend);
-
-gboolean e_book_backend_is_removed (EBookBackend *backend);
-
-void e_book_backend_open (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- gboolean only_if_exists);
-void e_book_backend_remove (EBookBackend *backend,
- EDataBook *book,
- guint32 opid);
-void e_book_backend_create_contact (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *vcard);
-void e_book_backend_remove_contacts (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- GList *id_list);
-void e_book_backend_modify_contact (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *vcard);
-void e_book_backend_get_contact (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *id);
-void e_book_backend_get_contact_list (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *query);
-void e_book_backend_get_changes (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *change_id);
-void e_book_backend_authenticate_user (EBookBackend *backend,
- EDataBook *book,
- guint32 opid,
- const gchar *user,
- const gchar *passwd,
- const gchar *auth_method);
-void e_book_backend_get_supported_fields (EBookBackend *backend,
- EDataBook *book,
- guint32 opid);
-
-void e_book_backend_get_required_fields (EBookBackend *backend,
- EDataBook *book,
- guint32 opid);
-
-void e_book_backend_get_supported_auth_methods (EBookBackend *backend,
- EDataBook *book,
- guint32 opid);
-void e_book_backend_cancel_operation (EBookBackend *backend,
- EDataBook *book,
- GError **error);
-void e_book_backend_set_mode (EBookBackend *backend,
- EDataBookMode mode);
-
-void e_book_backend_start_book_view (EBookBackend *backend,
- EDataBookView *view);
-void e_book_backend_stop_book_view (EBookBackend *backend,
- EDataBookView *view);
-
-void e_book_backend_add_book_view (EBookBackend *backend,
- EDataBookView *view);
-
-void e_book_backend_remove_book_view (EBookBackend *backend,
- EDataBookView *view);
-
-EList *e_book_backend_get_book_views (EBookBackend *backend);
-
-void e_book_backend_notify_update (EBookBackend *backend,
- EContact *contact);
-void e_book_backend_notify_remove (EBookBackend *backend,
- const gchar *id);
-void e_book_backend_notify_complete (EBookBackend *backend);
-void e_book_backend_notify_writable (EBookBackend *backend, gboolean is_writable);
-void e_book_backend_notify_connection_status (EBookBackend *backend, gboolean is_online);
-void e_book_backend_notify_auth_required (EBookBackend *backend);
-void e_book_backend_sync (EBookBackend *backend);
-
-GType e_book_backend_get_type (void);
+GType e_book_backend_get_type (void);
+
+const gchar * e_book_backend_get_cache_dir (EBookBackend *backend);
+void e_book_backend_set_cache_dir (EBookBackend *backend, const gchar *cache_dir);
+
+ESource * e_book_backend_get_source (EBookBackend *backend);
+
+gboolean e_book_backend_add_client (EBookBackend *backend, EDataBook *book);
+void e_book_backend_remove_client (EBookBackend *backend, EDataBook *book);
+
+gboolean e_book_backend_is_online (EBookBackend *backend);
+gboolean e_book_backend_is_opened (EBookBackend *backend);
+gboolean e_book_backend_is_opening (EBookBackend *backend);
+gboolean e_book_backend_is_readonly (EBookBackend *backend);
+gboolean e_book_backend_is_removed (EBookBackend *backend);
+void e_book_backend_set_online (EBookBackend *backend, gboolean is_online);
+void e_book_backend_authenticate_user(EBookBackend *backend, GCancellable *cancellable, ECredentials *credentials);
+
+void e_book_backend_get_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name);
+void e_book_backend_set_backend_property (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value);
+
+void e_book_backend_open (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, gboolean only_if_exists);
+void e_book_backend_remove (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
+void e_book_backend_refresh (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable);
+void e_book_backend_create_contact (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *vcard);
+void e_book_backend_remove_contacts (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const GSList *id_list);
+void e_book_backend_modify_contact (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *vcard);
+void e_book_backend_get_contact (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *id);
+void e_book_backend_get_contact_list (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *query);
+
+void e_book_backend_start_book_view (EBookBackend *backend, EDataBookView *view);
+void e_book_backend_stop_book_view (EBookBackend *backend, EDataBookView *view);
+void e_book_backend_add_book_view (EBookBackend *backend, EDataBookView *view);
+void e_book_backend_remove_book_view (EBookBackend *backend, EDataBookView *view);
+void e_book_backend_foreach_view (EBookBackend *backend, gboolean (* callback) (EDataBookView *view, gpointer user_data), gpointer user_data);
+
+void e_book_backend_notify_update (EBookBackend *backend, const EContact *contact);
+void e_book_backend_notify_remove (EBookBackend *backend, const gchar *id);
+void e_book_backend_notify_complete (EBookBackend *backend);
+
+void e_book_backend_notify_error (EBookBackend *backend, const gchar *message);
+void e_book_backend_notify_readonly (EBookBackend *backend, gboolean is_readonly);
+void e_book_backend_notify_online (EBookBackend *backend, gboolean is_online);
+void e_book_backend_notify_auth_required (EBookBackend *backend, gboolean is_self, const ECredentials *credentials);
+void e_book_backend_notify_opened (EBookBackend *backend, GError *error);
+
+void e_book_backend_sync (EBookBackend *backend);
/* protected functions for subclasses */
-void e_book_backend_set_is_loaded (EBookBackend *backend,
- gboolean is_loaded);
-void e_book_backend_set_is_writable (EBookBackend *backend,
- gboolean is_writable);
-void e_book_backend_set_is_removed (EBookBackend *backend,
- gboolean is_removed);
-
-/* useful for implementing _get_changes in backends */
-EDataBookChange* e_book_backend_change_add_new (const gchar *vcard);
-EDataBookChange* e_book_backend_change_modify_new (const gchar *vcard);
-EDataBookChange* e_book_backend_change_delete_new (const gchar *id);
+void e_book_backend_set_is_removed (EBookBackend *backend, gboolean is_removed);
+
+void e_book_backend_respond_opened (EBookBackend *backend, EDataBook *book, guint32 opid, GError *error);
G_END_DECLS
#endif /* __E_BOOK_BACKEND_H__ */
-
diff --git a/addressbook/libedata-book/e-data-book-factory.c b/addressbook/libedata-book/e-data-book-factory.c
index 4fc5fae..e74a108 100644
--- a/addressbook/libedata-book/e-data-book-factory.c
+++ b/addressbook/libedata-book/e-data-book-factory.c
@@ -39,7 +39,7 @@
#include "e-data-book.h"
#include "e-book-backend.h"
-#include "e-gdbus-egdbusbookfactory.h"
+#include "e-gdbus-book-factory.h"
#ifdef G_OS_WIN32
#include <windows.h>
@@ -90,7 +90,8 @@ struct _EDataBookFactoryPrivate {
guint exit_timeout;
- gint mode;
+ /* whether should be online */
+ gboolean is_online;
};
/* Forward Declarations */
@@ -167,28 +168,27 @@ set_backend_online_status (gpointer key, gpointer value, gpointer data)
g_return_if_fail (backend != NULL);
- e_book_backend_set_mode (backend, GPOINTER_TO_INT (data));
+ e_book_backend_set_online (backend, GPOINTER_TO_INT (data));
}
/**
- * e_data_book_factory_set_backend_mode:
+ * e_data_book_factory_set_backend_online:
* @factory: A bookendar factory.
- * @mode: Online mode to set.
+ * @is_online: Online mode to set.
*
* Sets the online mode for all backends created by the given factory.
*/
void
-e_data_book_factory_set_backend_mode (EDataBookFactory *factory,
- gint mode)
+e_data_book_factory_set_backend_online (EDataBookFactory *factory, gboolean is_online)
{
g_return_if_fail (E_IS_DATA_BOOK_FACTORY (factory));
- factory->priv->mode = mode;
+ factory->priv->is_online = is_online;
g_mutex_lock (factory->priv->backends_lock);
g_hash_table_foreach (
factory->priv->backends,
set_backend_online_status,
- GINT_TO_POINTER (factory->priv->mode));
+ GINT_TO_POINTER (factory->priv->is_online));
g_mutex_unlock (factory->priv->backends_lock);
}
@@ -291,6 +291,14 @@ backend_gone_cb (EDataBookFactory *factory, GObject *dead)
g_mutex_unlock (priv->backends_lock);
}
+static void
+last_client_gone_cb (EBookBackend *backend, EDataBookFactory *factory)
+{
+ backend_gone_cb (factory, (GObject *) backend);
+ g_object_weak_unref (G_OBJECT (backend), (GWeakNotify) backend_gone_cb, factory);
+ g_object_unref (backend);
+}
+
static gboolean
impl_BookFactory_getBook (EGdbusBookFactory *object, GDBusMethodInvocation *invocation, const gchar *in_source, EDataBookFactory *factory)
{
@@ -311,12 +319,6 @@ impl_BookFactory_getBook (EGdbusBookFactory *object, GDBusMethodInvocation *invo
return TRUE;
}
- /* Remove a pending exit */
- if (priv->exit_timeout) {
- g_source_remove (priv->exit_timeout);
- priv->exit_timeout = 0;
- }
-
g_mutex_lock (priv->backends_lock);
source = e_source_new_from_standalone_xml (in_source);
@@ -361,8 +363,8 @@ impl_BookFactory_getBook (EGdbusBookFactory *object, GDBusMethodInvocation *invo
g_hash_table_insert (
priv->backends, uri_key, backend);
g_object_weak_ref (G_OBJECT (backend), (GWeakNotify) backend_gone_cb, factory);
- g_signal_connect (backend, "last-client-gone", G_CALLBACK (g_object_unref), NULL);
- e_book_backend_set_mode (backend, priv->mode);
+ g_signal_connect (backend, "last-client-gone", G_CALLBACK (last_client_gone_cb), factory);
+ e_book_backend_set_online (backend, priv->is_online);
}
}
@@ -380,6 +382,12 @@ impl_BookFactory_getBook (EGdbusBookFactory *object, GDBusMethodInvocation *invo
return TRUE;
}
+ /* Remove a pending exit */
+ if (priv->exit_timeout) {
+ g_source_remove (priv->exit_timeout);
+ priv->exit_timeout = 0;
+ }
+
path = construct_book_factory_path ();
book = e_data_book_new (backend, source);
g_hash_table_insert (priv->books, g_strdup (path), book);
@@ -403,11 +411,10 @@ impl_BookFactory_getBook (EGdbusBookFactory *object, GDBusMethodInvocation *invo
g_object_unref (source);
g_free (uri);
- if (error) {
- g_dbus_method_invocation_return_gerror (invocation, error);
+ e_gdbus_book_factory_complete_get_book (object, invocation, path, error);
+
+ if (error)
g_error_free (error);
- } else
- e_gdbus_book_factory_complete_get_book (object, invocation, path);
g_free (path);
@@ -523,9 +530,7 @@ offline_state_changed_cb (EOfflineListener *eol, EDataBookFactory *factory)
g_return_if_fail (state == EOL_STATE_ONLINE || state == EOL_STATE_OFFLINE);
- e_data_book_factory_set_backend_mode (
- factory, state == EOL_STATE_ONLINE ?
- E_DATA_BOOK_MODE_REMOTE : E_DATA_BOOK_MODE_LOCAL);
+ e_data_book_factory_set_backend_online (factory, state == EOL_STATE_ONLINE);
}
static void
diff --git a/addressbook/libedata-book/e-data-book-factory.h b/addressbook/libedata-book/e-data-book-factory.h
index 636ee53..90c68c6 100644
--- a/addressbook/libedata-book/e-data-book-factory.h
+++ b/addressbook/libedata-book/e-data-book-factory.h
@@ -52,7 +52,7 @@ GQuark e_data_book_factory_error_quark (void);
GType e_data_book_factory_get_type (void);
-void e_data_book_factory_set_backend_mode (EDataBookFactory *factory, gint mode);
+void e_data_book_factory_set_backend_online (EDataBookFactory *factory, gboolean is_online);
G_END_DECLS
diff --git a/addressbook/libedata-book/e-data-book-types.h b/addressbook/libedata-book/e-data-book-types.h
index c6cdfaa..5434815 100644
--- a/addressbook/libedata-book/e-data-book-types.h
+++ b/addressbook/libedata-book/e-data-book-types.h
@@ -46,6 +46,7 @@ typedef struct _EDataBookClass EDataBookClass;
typedef enum {
E_DATA_BOOK_STATUS_SUCCESS,
+ E_DATA_BOOK_STATUS_BUSY,
E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
E_DATA_BOOK_STATUS_PERMISSION_DENIED,
E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND,
@@ -70,23 +71,6 @@ typedef enum {
E_DATA_BOOK_STATUS_NOT_SUPPORTED
} EDataBookStatus;
-typedef enum {
- E_DATA_BOOK_MODE_LOCAL,
- E_DATA_BOOK_MODE_REMOTE,
- E_DATA_BOOK_MODE_ANY,
-} EDataBookMode;
-
-typedef enum {
- E_DATA_BOOK_BACKEND_CHANGE_ADDED,
- E_DATA_BOOK_BACKEND_CHANGE_DELETED,
- E_DATA_BOOK_BACKEND_CHANGE_MODIFIED
-} EDataBookChangeType;
-
-typedef struct {
- EDataBookChangeType change_type;
- gchar *vcard;
-} EDataBookChange;
-
G_END_DECLS
#endif /* __E_DATA_BOOK_TYPES_H__ */
diff --git a/addressbook/libedata-book/e-data-book-view.c b/addressbook/libedata-book/e-data-book-view.c
index 2ecfbc5..6666cb5 100644
--- a/addressbook/libedata-book/e-data-book-view.c
+++ b/addressbook/libedata-book/e-data-book-view.c
@@ -29,7 +29,7 @@
#include "libedataserver/e-data-server-util.h"
#include "e-data-book-view.h"
-#include "e-gdbus-egdbusbookview.h"
+#include "e-gdbus-book-view.h"
static void reset_array (GArray *array);
static void ensure_pending_flush_timeout (EDataBookView *view);
@@ -47,7 +47,6 @@ struct _EDataBookViewPrivate {
gchar * card_query;
EBookBackendSExp *card_sexp;
- gint max_results;
gboolean running;
GMutex *pending_mutex;
@@ -60,6 +59,9 @@ struct _EDataBookViewPrivate {
guint idle_id;
guint flush_id;
+
+ /* which fields is listener interested in */
+ GHashTable *fields_of_interest;
};
static void e_data_book_view_dispose (GObject *object);
@@ -76,6 +78,43 @@ e_data_book_view_class_init (EDataBookViewClass *klass)
object_class->finalize = e_data_book_view_finalize;
}
+static guint
+str_ic_hash (gconstpointer key)
+{
+ guint32 hash = 5381;
+ const gchar *str = key;
+ gint ii;
+
+ if (!str)
+ return hash;
+
+ for (ii = 0; str[ii]; ii++) {
+ hash = hash * 33 + g_ascii_tolower (str[ii]);
+ }
+
+ return hash;
+}
+
+static gboolean
+str_ic_equal (gconstpointer a, gconstpointer b)
+{
+ const gchar *stra = a, *strb = b;
+ gint ii;
+
+ if (!stra && !strb)
+ return TRUE;
+
+ if (!stra || !strb)
+ return FALSE;
+
+ for (ii = 0; stra[ii] && strb[ii]; ii++) {
+ if (g_ascii_tolower (stra[ii]) != g_ascii_tolower (strb[ii]))
+ return FALSE;
+ }
+
+ return stra[ii] == strb[ii];
+}
+
/**
* e_data_book_view_register_gdbus_object:
*
@@ -117,7 +156,7 @@ send_pending_adds (EDataBookView *view)
if (priv->adds->len == 0)
return;
- e_gdbus_book_view_emit_contacts_added (view->priv->gdbus_object, (const gchar * const *) priv->adds->data);
+ e_gdbus_book_view_emit_objects_added (view->priv->gdbus_object, (const gchar * const *) priv->adds->data);
reset_array (priv->adds);
}
@@ -129,7 +168,7 @@ send_pending_changes (EDataBookView *view)
if (priv->changes->len == 0)
return;
- e_gdbus_book_view_emit_contacts_changed (view->priv->gdbus_object, (const gchar * const *) priv->changes->data);
+ e_gdbus_book_view_emit_objects_modified (view->priv->gdbus_object, (const gchar * const *) priv->changes->data);
reset_array (priv->changes);
}
@@ -141,7 +180,7 @@ send_pending_removes (EDataBookView *view)
if (priv->removes->len == 0)
return;
- e_gdbus_book_view_emit_contacts_removed (view->priv->gdbus_object, (const gchar * const *) priv->removes->data);
+ e_gdbus_book_view_emit_objects_removed (view->priv->gdbus_object, (const gchar * const *) priv->removes->data);
reset_array (priv->removes);
}
@@ -244,6 +283,37 @@ notify_add (EDataBookView *view, const gchar *id, const gchar *vcard)
ensure_pending_flush_timeout (view);
}
+static gboolean
+impl_DataBookView_setFieldsOfInterest (EGdbusBookView *object, GDBusMethodInvocation *invocation, const gchar * const *in_fields_of_interest, EDataBookView *view)
+{
+ EDataBookViewPrivate *priv;
+ gint ii;
+
+ g_return_val_if_fail (in_fields_of_interest != NULL, TRUE);
+
+ priv = view->priv;
+
+ if (priv->fields_of_interest)
+ g_hash_table_destroy (priv->fields_of_interest);
+ priv->fields_of_interest = NULL;
+
+ for (ii = 0; in_fields_of_interest[ii]; ii++) {
+ const gchar *field = in_fields_of_interest[ii];
+
+ if (!*field)
+ continue;
+
+ if (!priv->fields_of_interest)
+ priv->fields_of_interest = g_hash_table_new_full (str_ic_hash, str_ic_equal, g_free, NULL);
+
+ g_hash_table_insert (priv->fields_of_interest, g_strdup (field), GINT_TO_POINTER (1));
+ }
+
+ e_gdbus_book_view_complete_set_fields_of_interest (object, invocation, NULL);
+
+ return TRUE;
+}
+
static void
reset_array (GArray *array)
{
@@ -288,8 +358,7 @@ id_is_in_view (EDataBookView *book_view, const gchar *id)
* by @book_view.
**/
void
-e_data_book_view_notify_update (EDataBookView *book_view,
- EContact *contact)
+e_data_book_view_notify_update (EDataBookView *book_view, const EContact *contact)
{
EDataBookViewPrivate *priv = book_view->priv;
gboolean currently_in_view, want_in_view;
@@ -301,11 +370,11 @@ e_data_book_view_notify_update (EDataBookView *book_view,
g_mutex_lock (priv->pending_mutex);
- id = e_contact_get_const (contact, E_CONTACT_UID);
+ id = e_contact_get_const ((EContact *) contact, E_CONTACT_UID);
currently_in_view = id_is_in_view (book_view, id);
want_in_view =
- e_book_backend_sexp_match_contact (priv->card_sexp, contact);
+ e_book_backend_sexp_match_contact (priv->card_sexp, (EContact *) contact);
if (want_in_view) {
vcard = e_vcard_to_string (E_VCARD (contact),
@@ -459,7 +528,7 @@ void
e_data_book_view_notify_complete (EDataBookView *book_view, const GError *error)
{
EDataBookViewPrivate *priv = book_view->priv;
- gchar *gdbus_error_msg = NULL;
+ gchar **strv_error;
if (!priv->running)
return;
@@ -472,17 +541,15 @@ e_data_book_view_notify_complete (EDataBookView *book_view, const GError *error)
g_mutex_unlock (priv->pending_mutex);
- /* We're done now, so tell the backend to stop? TODO: this is a bit different to
- how the CORBA backend works... */
-
- e_gdbus_book_view_emit_complete (priv->gdbus_object, error ? error->code : 0, e_util_ensure_gdbus_string (error ? error->message : "", &gdbus_error_msg));
-
- g_free (gdbus_error_msg);
+ strv_error = e_gdbus_templates_encode_error (error);
+ e_gdbus_book_view_emit_complete (priv->gdbus_object, (const gchar * const *) strv_error);
+ g_strfreev (strv_error);
}
/**
- * e_data_book_view_notify_status_message:
+ * e_data_book_view_notify_progress:
* @book_view: an #EDataBookView
+ * @percent: percent done; use -1 when not available
* @message: a text message
*
* Provides listeners with a human-readable text describing the
@@ -490,7 +557,7 @@ e_data_book_view_notify_complete (EDataBookView *book_view, const GError *error)
* reporting.
**/
void
-e_data_book_view_notify_status_message (EDataBookView *book_view, const gchar *message)
+e_data_book_view_notify_progress (EDataBookView *book_view, guint percent, const gchar *message)
{
EDataBookViewPrivate *priv = book_view->priv;
gchar *gdbus_message = NULL;
@@ -498,7 +565,7 @@ e_data_book_view_notify_status_message (EDataBookView *book_view, const gchar *m
if (!priv->running)
return;
- e_gdbus_book_view_emit_status_message (priv->gdbus_object, e_util_ensure_gdbus_string (message, &gdbus_message));
+ e_gdbus_book_view_emit_progress (priv->gdbus_object, percent, e_util_ensure_gdbus_string (message, &gdbus_message));
g_free (gdbus_message);
}
@@ -508,13 +575,12 @@ e_data_book_view_notify_status_message (EDataBookView *book_view, const gchar *m
* @book: The #EDataBook to search
* @card_query: The query as a string
* @card_sexp: The query as an #EBookBackendSExp
- * @max_results: The maximum number of results to return
*
* Create a new #EDataBookView for the given #EBook, filtering on #card_sexp,
* and place it on DBus at the object path #path.
*/
EDataBookView *
-e_data_book_view_new (EDataBook *book, const gchar *card_query, EBookBackendSExp *card_sexp, gint max_results)
+e_data_book_view_new (EDataBook *book, const gchar *card_query, EBookBackendSExp *card_sexp)
{
EDataBookView *view;
EDataBookViewPrivate *priv;
@@ -528,7 +594,6 @@ e_data_book_view_new (EDataBook *book, const gchar *card_query, EBookBackendSExp
priv->backend = g_object_ref (e_data_book_get_backend (book));
priv->card_query = e_util_utf8_make_valid (card_query);
priv->card_sexp = card_sexp;
- priv->max_results = max_results;
return view;
}
@@ -551,7 +616,7 @@ impl_DataBookView_start (EGdbusBookView *object, GDBusMethodInvocation *invocati
{
book_view->priv->idle_id = g_idle_add (bookview_idle_start, book_view);
- e_gdbus_book_view_complete_start (object, invocation);
+ e_gdbus_book_view_complete_start (object, invocation, NULL);
return TRUE;
}
@@ -577,7 +642,7 @@ impl_DataBookView_stop (EGdbusBookView *object, GDBusMethodInvocation *invocatio
book_view->priv->idle_id = g_idle_add (bookview_idle_stop, book_view);
- e_gdbus_book_view_complete_stop (object, invocation);
+ e_gdbus_book_view_complete_stop (object, invocation, NULL);
return TRUE;
}
@@ -585,7 +650,10 @@ impl_DataBookView_stop (EGdbusBookView *object, GDBusMethodInvocation *invocatio
static gboolean
impl_DataBookView_dispose (EGdbusBookView *object, GDBusMethodInvocation *invocation, EDataBookView *book_view)
{
- e_gdbus_book_view_complete_dispose (object, invocation);
+ e_gdbus_book_view_complete_dispose (object, invocation, NULL);
+
+ e_book_backend_stop_book_view (book_view->priv->backend, book_view);
+ book_view->priv->running = FALSE;
g_object_unref (book_view);
@@ -604,7 +672,9 @@ e_data_book_view_init (EDataBookView *book_view)
g_signal_connect (priv->gdbus_object, "handle-start", G_CALLBACK (impl_DataBookView_start), book_view);
g_signal_connect (priv->gdbus_object, "handle-stop", G_CALLBACK (impl_DataBookView_stop), book_view);
g_signal_connect (priv->gdbus_object, "handle-dispose", G_CALLBACK (impl_DataBookView_dispose), book_view);
+ g_signal_connect (priv->gdbus_object, "handle-set-fields-of-interest", G_CALLBACK (impl_DataBookView_setFieldsOfInterest), book_view);
+ priv->fields_of_interest = NULL;
priv->running = FALSE;
priv->pending_mutex = g_mutex_new ();
@@ -669,9 +739,11 @@ e_data_book_view_finalize (GObject *object)
g_array_free (priv->adds, TRUE);
g_array_free (priv->changes, TRUE);
g_array_free (priv->removes, TRUE);
-
g_free (priv->card_query);
+ if (priv->fields_of_interest)
+ g_hash_table_destroy (priv->fields_of_interest);
+
g_mutex_free (priv->pending_mutex);
g_hash_table_destroy (priv->ids);
@@ -679,16 +751,6 @@ e_data_book_view_finalize (GObject *object)
G_OBJECT_CLASS (e_data_book_view_parent_class)->finalize (object);
}
-void
-e_data_book_view_set_thresholds (EDataBookView *book_view,
- gint minimum_grouping_threshold,
- gint maximum_grouping_threshold)
-{
- g_return_if_fail (E_IS_DATA_BOOK_VIEW (book_view));
-
- g_debug ("e_data_book_view_set_thresholds does nothing in eds-dbus");
-}
-
/**
* e_data_book_view_get_card_query:
* @book_view: an #EDataBookView
@@ -724,36 +786,39 @@ e_data_book_view_get_card_sexp (EDataBookView *book_view)
}
/**
- * e_data_book_view_get_max_results:
+ * e_data_book_view_get_backend:
* @book_view: an #EDataBookView
*
- * Gets the maximum number of results returned by
- * @book_view's query.
+ * Gets the backend that @book_view is querying.
*
- * Returns: The maximum number of results returned.
+ * Returns: The associated #EBookBackend.
**/
-gint
-e_data_book_view_get_max_results (EDataBookView *book_view)
+EBookBackend*
+e_data_book_view_get_backend (EDataBookView *book_view)
{
- g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), 0);
+ g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL);
- return book_view->priv->max_results;
+ return book_view->priv->backend;
}
/**
- * e_data_book_view_get_backend:
- * @book_view: an #EDataBookView
+ * e_data_book_view_get_fields_of_interest:
+ * @view: A view object.
*
- * Gets the backend that @book_view is querying.
+ * Returns: Hash table of field names which the listener is interested in.
+ * Backends can return fully populated objects, but the listener advertised
+ * that it will use only these. Returns %NULL for all available fields.
*
- * Returns: The associated #EBookBackend.
+ * Note: The data pointer in the hash table has no special meaning, it's
+ * only GINT_TO_POINTER(1) for easier checking. Also, field names are
+ * compared case insensitively.
**/
-EBookBackend*
-e_data_book_view_get_backend (EDataBookView *book_view)
+/* const */ GHashTable *
+e_data_book_view_get_fields_of_interest (EDataBookView *view)
{
- g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL);
+ g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (view), NULL);
- return book_view->priv->backend;
+ return view->priv->fields_of_interest;
}
/**
diff --git a/addressbook/libedata-book/e-data-book-view.h b/addressbook/libedata-book/e-data-book-view.h
index 1f856b9..9a19aad 100644
--- a/addressbook/libedata-book/e-data-book-view.h
+++ b/addressbook/libedata-book/e-data-book-view.h
@@ -52,40 +52,25 @@ struct _EDataBookViewClass {
GObjectClass parent;
};
-EDataBookView *e_data_book_view_new (EDataBook *book,
- const gchar *card_query,
- EBookBackendSExp *card_sexp,
- gint max_results);
+GType e_data_book_view_get_type (void);
+EDataBookView * e_data_book_view_new (EDataBook *book, const gchar *card_query, EBookBackendSExp *card_sexp);
+guint e_data_book_view_register_gdbus_object (EDataBookView *query, GDBusConnection *connection, const gchar *object_path, GError **error);
-guint e_data_book_view_register_gdbus_object (EDataBookView *query, GDBusConnection *connection, const gchar *object_path, GError **error);
+const gchar * e_data_book_view_get_card_query (EDataBookView *book_view);
+EBookBackendSExp * e_data_book_view_get_card_sexp (EDataBookView *book_view);
+EBookBackend * e_data_book_view_get_backend (EDataBookView *book_view);
+void e_data_book_view_notify_update (EDataBookView *book_view, const EContact *contact);
-void e_data_book_view_set_thresholds (EDataBookView *book_view,
- gint minimum_grouping_threshold,
- gint maximum_grouping_threshold);
+void e_data_book_view_notify_update_vcard (EDataBookView *book_view, gchar *vcard);
+void e_data_book_view_notify_update_prefiltered_vcard (EDataBookView *book_view, const gchar *id, gchar *vcard);
-const gchar * e_data_book_view_get_card_query (EDataBookView *book_view);
-EBookBackendSExp* e_data_book_view_get_card_sexp (EDataBookView *book_view);
-gint e_data_book_view_get_max_results (EDataBookView *book_view);
-EBookBackend* e_data_book_view_get_backend (EDataBookView *book_view);
-void e_data_book_view_notify_update (EDataBookView *book_view,
- EContact *contact);
+void e_data_book_view_notify_remove (EDataBookView *book_view, const gchar *id);
+void e_data_book_view_notify_complete (EDataBookView *book_view, const GError *error);
+void e_data_book_view_notify_progress (EDataBookView *book_view, guint percent, const gchar *message);
+void e_data_book_view_ref (EDataBookView *book_view);
+void e_data_book_view_unref (EDataBookView *book_view);
-void e_data_book_view_notify_update_vcard (EDataBookView *book_view,
- gchar *vcard);
-void e_data_book_view_notify_update_prefiltered_vcard (EDataBookView *book_view,
- const gchar *id,
- gchar *vcard);
-
-void e_data_book_view_notify_remove (EDataBookView *book_view,
- const gchar *id);
-void e_data_book_view_notify_complete (EDataBookView *book_view,
- const GError *error);
-void e_data_book_view_notify_status_message (EDataBookView *book_view,
- const gchar *message);
-void e_data_book_view_ref (EDataBookView *book_view);
-void e_data_book_view_unref (EDataBookView *book_view);
-
-GType e_data_book_view_get_type (void);
+/* const */ GHashTable *e_data_book_view_get_fields_of_interest (EDataBookView *view);
G_END_DECLS
diff --git a/addressbook/libedata-book/e-data-book.c b/addressbook/libedata-book/e-data-book.c
index 71a98c2..a4ce8d8 100644
--- a/addressbook/libedata-book/e-data-book.c
+++ b/addressbook/libedata-book/e-data-book.c
@@ -26,16 +26,17 @@
#include <glib-object.h>
#include <gio/gio.h>
-#include "libedataserver/e-data-server-util.h"
+#include <libedataserver/e-credentials.h>
+#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-operation-pool.h>
#include "e-data-book-enumtypes.h"
#include "e-data-book-factory.h"
#include "e-data-book.h"
#include "e-data-book-view.h"
#include "e-book-backend-sexp.h"
-#include "opid.h"
-#include "e-gdbus-egdbusbook.h"
+#include "e-gdbus-book.h"
G_DEFINE_TYPE (EDataBook, e_data_book, G_TYPE_OBJECT)
@@ -45,53 +46,87 @@ struct _EDataBookPrivate
EBookBackend *backend;
ESource *source;
-};
-static void return_error_and_list (EGdbusBook *gdbus_object, void (* complete_func) (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar * const *out_array), guint32 opid, GError *error, const gchar *error_fmt, GList *list, gboolean free_data);
-static void data_book_return_error (GDBusMethodInvocation *invocation, const GError *error, const gchar *error_fmt);
+ GStaticRecMutex pending_ops_lock;
+ GHashTable *pending_ops; /* opid to GCancellable for still running operations */
+};
-static GThreadPool *op_pool = NULL;
+static EOperationPool *ops_pool = NULL;
typedef enum {
OP_OPEN,
- OP_AUTHENTICATE,
- OP_ADD_CONTACT,
+ OP_REMOVE,
+ OP_REFRESH,
OP_GET_CONTACT,
OP_GET_CONTACTS,
- OP_MODIFY_CONTACT,
+ OP_AUTHENTICATE,
+ OP_ADD_CONTACT,
OP_REMOVE_CONTACTS,
- OP_GET_CHANGES,
+ OP_MODIFY_CONTACT,
+ OP_GET_BACKEND_PROPERTY,
+ OP_SET_BACKEND_PROPERTY,
+ OP_GET_BOOK_VIEW,
+ OP_CANCEL_OPERATION,
+ OP_CANCEL_ALL,
+ OP_CLOSE
} OperationID;
typedef struct {
OperationID op;
guint32 id; /* operation id */
EDataBook *book; /* book */
+ GCancellable *cancellable;
+
union {
/* OP_OPEN */
gboolean only_if_exists;
+ /* OP_GET_CONTACT */
+ gchar *uid;
/* OP_AUTHENTICATE */
- struct {
- gchar *username;
- gchar *password;
- gchar *method;
- } auth;
+ ECredentials *credentials;
+ /* OP_REMOVE_CONTACTS */
+ GSList *ids;
/* OP_ADD_CONTACT */
/* OP_MODIFY_CONTACT */
gchar *vcard;
- /* OP_GET_CONTACT */
- gchar *uid;
+ /* OP_GET_BOOK_VIEW */
/* OP_GET_CONTACTS */
gchar *query;
- /* OP_MODIFY_CONTACT */
- gchar **vcards;
- /* OP_REMOVE_CONTACTS */
- GList *ids;
- /* OP_GET_CHANGES */
- gchar *change_id;
+ /* OP_CANCEL_OPERATION */
+ guint opid;
+ /* OP_GET_BACKEND_PROPERTY */
+ gchar *prop_name;
+ /* OP_SET_BACKEND_PROPERTY */
+ struct _sbp {
+ gchar *prop_name;
+ gchar *prop_value;
+ } sbp;
+
+ /* OP_REMOVE */
+ /* OP_REFRESH */
+ /* OP_CANCEL_ALL */
+ /* OP_CLOSE */
} d;
} OperationData;
+static gchar *
+construct_bookview_path (void)
+{
+ static volatile guint counter = 1;
+
+ return g_strdup_printf ("/org/gnome/evolution/dataserver/AddressBookView/%d/%d",
+ getpid (),
+ g_atomic_int_exchange_and_add ((int*)&counter, 1));
+}
+
+static void
+cancel_ops_cb (gpointer opid, gpointer cancellable, gpointer user_data)
+{
+ g_return_if_fail (cancellable != NULL);
+
+ g_cancellable_cancel (cancellable);
+}
+
static void
operation_thread (gpointer data, gpointer user_data)
{
@@ -102,61 +137,145 @@ operation_thread (gpointer data, gpointer user_data)
switch (op->op) {
case OP_OPEN:
- e_book_backend_open (backend, op->book, op->id, op->d.only_if_exists);
- break;
- case OP_AUTHENTICATE:
- e_book_backend_authenticate_user (backend, op->book, op->id,
- op->d.auth.username,
- op->d.auth.password,
- op->d.auth.method);
- g_free (op->d.auth.username);
- g_free (op->d.auth.password);
- g_free (op->d.auth.method);
+ e_book_backend_open (backend, op->book, op->id, op->cancellable, op->d.only_if_exists);
break;
case OP_ADD_CONTACT:
- e_book_backend_create_contact (backend, op->book, op->id, op->d.vcard);
+ e_book_backend_create_contact (backend, op->book, op->id, op->cancellable, op->d.vcard);
g_free (op->d.vcard);
break;
case OP_GET_CONTACT:
- e_book_backend_get_contact (backend, op->book, op->id, op->d.uid);
+ e_book_backend_get_contact (backend, op->book, op->id, op->cancellable, op->d.uid);
g_free (op->d.uid);
break;
case OP_GET_CONTACTS:
- e_book_backend_get_contact_list (backend, op->book, op->id, op->d.query);
+ e_book_backend_get_contact_list (backend, op->book, op->id, op->cancellable, op->d.query);
g_free (op->d.query);
break;
case OP_MODIFY_CONTACT:
- e_book_backend_modify_contact (backend, op->book, op->id, op->d.vcard);
+ e_book_backend_modify_contact (backend, op->book, op->id, op->cancellable, op->d.vcard);
g_free (op->d.vcard);
break;
case OP_REMOVE_CONTACTS:
- e_book_backend_remove_contacts (backend, op->book, op->id, op->d.ids);
- g_list_foreach (op->d.ids, (GFunc) g_free, NULL);
- g_list_free (op->d.ids);
+ e_book_backend_remove_contacts (backend, op->book, op->id, op->cancellable, op->d.ids);
+ g_slist_foreach (op->d.ids, (GFunc) g_free, NULL);
+ g_slist_free (op->d.ids);
+ break;
+ case OP_REMOVE:
+ e_book_backend_remove (backend, op->book, op->id, op->cancellable);
+ break;
+ case OP_REFRESH:
+ e_book_backend_refresh (backend, op->book, op->id, op->cancellable);
break;
- case OP_GET_CHANGES:
- e_book_backend_get_changes (backend, op->book, op->id, op->d.change_id);
- g_free (op->d.change_id);
+ case OP_GET_BACKEND_PROPERTY:
+ e_book_backend_get_backend_property (backend, op->book, op->id, op->cancellable, op->d.prop_name);
+ g_free (op->d.prop_name);
+ break;
+ case OP_SET_BACKEND_PROPERTY:
+ e_book_backend_set_backend_property (backend, op->book, op->id, op->cancellable, op->d.sbp.prop_name, op->d.sbp.prop_value);
+ g_free (op->d.sbp.prop_name);
+ g_free (op->d.sbp.prop_value);
+ break;
+ case OP_GET_BOOK_VIEW:
+ if (op->d.query) {
+ EBookBackendSExp *card_sexp;
+ EDataBookView *book_view;
+ gchar *path;
+ GError *error = NULL;
+
+ card_sexp = e_book_backend_sexp_new (op->d.query);
+ if (!card_sexp) {
+ error = e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_QUERY, NULL);
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Invalid query: "));
+ e_gdbus_book_emit_get_view_done (op->book->priv->gdbus_object, op->id, error, NULL);
+ g_error_free (error);
+ break;
+ }
+
+ path = construct_bookview_path ();
+
+ book_view = e_data_book_view_new (op->book, op->d.query, card_sexp);
+ e_data_book_view_register_gdbus_object (book_view, e_gdbus_book_stub_get_connection (op->book->priv->gdbus_object), path, &error);
+
+ if (error) {
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Invalid query: "));
+ e_gdbus_book_emit_get_view_done (op->book->priv->gdbus_object, op->id, error, NULL);
+ g_error_free (error);
+ g_object_unref (book_view);
+ g_free (path);
+
+ break;
+ }
+
+ e_book_backend_add_book_view (backend, book_view);
+
+ e_gdbus_book_emit_get_view_done (op->book->priv->gdbus_object, op->id, NULL, path);
+
+ g_free (path);
+ }
+ g_free (op->d.query);
+ break;
+ case OP_AUTHENTICATE:
+ e_book_backend_authenticate_user (backend, op->cancellable, op->d.credentials);
+ e_credentials_free (op->d.credentials);
+ break;
+ case OP_CANCEL_OPERATION:
+ g_static_rec_mutex_lock (&op->book->priv->pending_ops_lock);
+
+ if (g_hash_table_lookup (op->book->priv->pending_ops, GUINT_TO_POINTER (op->d.opid))) {
+ GCancellable *cancellable = g_hash_table_lookup (op->book->priv->pending_ops, GUINT_TO_POINTER (op->d.opid));
+
+ g_cancellable_cancel (cancellable);
+ }
+
+ g_static_rec_mutex_unlock (&op->book->priv->pending_ops_lock);
+ break;
+ case OP_CLOSE:
+ /* close just cancels all pending ops and frees data book */
+ e_book_backend_remove_client (backend, op->book);
+ case OP_CANCEL_ALL:
+ g_static_rec_mutex_lock (&op->book->priv->pending_ops_lock);
+ g_hash_table_foreach (op->book->priv->pending_ops, cancel_ops_cb, NULL);
+ g_static_rec_mutex_unlock (&op->book->priv->pending_ops_lock);
break;
}
g_object_unref (op->book);
+ g_object_unref (op->cancellable);
g_slice_free (OperationData, op);
}
static OperationData *
-op_new (OperationID op, EDataBook *book, GDBusMethodInvocation *invocation)
+op_new (OperationID op, EDataBook *book)
{
OperationData *data;
data = g_slice_new0 (OperationData);
data->op = op;
data->book = g_object_ref (book);
- data->id = opid_store (invocation);
+ data->id = e_operation_pool_reserve_opid (ops_pool);
+ data->cancellable = g_cancellable_new ();
+
+ g_static_rec_mutex_lock (&book->priv->pending_ops_lock);
+ g_hash_table_insert (book->priv->pending_ops, GUINT_TO_POINTER (data->id), g_object_ref (data->cancellable));
+ g_static_rec_mutex_unlock (&book->priv->pending_ops_lock);
return data;
}
+static void
+op_complete (EDataBook *book, guint32 opid)
+{
+ g_return_if_fail (book != NULL);
+
+ e_operation_pool_release_opid (ops_pool, opid);
+
+ g_static_rec_mutex_lock (&book->priv->pending_ops_lock);
+ g_hash_table_remove (book->priv->pending_ops, GUINT_TO_POINTER (opid));
+ g_static_rec_mutex_unlock (&book->priv->pending_ops_lock);
+}
+
/**
* e_data_book_status_to_string:
*
@@ -171,6 +290,7 @@ e_data_book_status_to_string (EDataBookStatus status)
const gchar *msg;
} statuses[] = {
{ E_DATA_BOOK_STATUS_SUCCESS, N_("Success") },
+ { E_DATA_BOOK_STATUS_BUSY, N_("Backend is busy") },
{ E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, N_("Repository offline") },
{ E_DATA_BOOK_STATUS_PERMISSION_DENIED, N_("Permission denied") },
{ E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, N_("Contact not found") },
@@ -212,6 +332,7 @@ e_data_book_error_quark (void)
static const GDBusErrorEntry entries[] = {
{ E_DATA_BOOK_STATUS_SUCCESS, ERR_PREFIX "Success" },
+ { E_DATA_BOOK_STATUS_BUSY, ERR_PREFIX "Busy" },
{ E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, ERR_PREFIX "RepositoryOffline" },
{ E_DATA_BOOK_STATUS_PERMISSION_DENIED, ERR_PREFIX "PermissionDenied" },
{ E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, ERR_PREFIX "ContactNotFound" },
@@ -303,527 +424,572 @@ e_data_book_get_backend (EDataBook *book)
return book->priv->backend;
}
-static gboolean
-impl_Book_open (EGdbusBook *object, GDBusMethodInvocation *invocation, gboolean only_if_exists, EDataBook *book)
+static void
+data_book_return_error (GDBusMethodInvocation *invocation, const GError *perror, const gchar *error_prefix)
{
- OperationData *op;
+ GError *error;
- op = op_new (OP_OPEN, book, invocation);
- op->d.only_if_exists = only_if_exists;
- g_thread_pool_push (op_pool, op, NULL);
+ if (perror == NULL)
+ error = g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_OTHER_ERROR, "%s", _("Unknown error"));
+ else
+ error = g_error_new (E_DATA_BOOK_ERROR, perror->code, "%s", perror->message);
- return TRUE;
+ g_prefix_error (&error, "%s", error_prefix);
+
+ g_dbus_method_invocation_return_gerror (invocation, error);
+
+ g_error_free (error);
}
-void
-e_data_book_respond_open (EDataBook *book, guint opid, GError *error)
+/* takes a list of strings and converts it to a comma-separated string of values;
+ free returned pointer with g_free() */
+gchar *
+e_data_book_string_slist_to_comma_string (const GSList *strings)
{
- GDBusMethodInvocation *invocation = opid_fetch (opid);
+ GString *tmp;
+ gchar *res;
+ const GSList *l;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Cannot open book: %s"));
- g_error_free (error);
- } else {
- e_gdbus_book_complete_open (book->priv->gdbus_object, invocation);
+ tmp = g_string_new ("");
+ for (l = strings; l != NULL; l = l->next) {
+ const gchar *str = l->data;
+
+ if (!str)
+ continue;
+
+ if (strchr (str, ',')) {
+ g_warning ("%s: String cannot contain comma; skipping value '%s'\n", G_STRFUNC, str);
+ continue;
+ }
+
+ if (tmp->len)
+ g_string_append_c (tmp, ',');
+ g_string_append (tmp, str);
}
+
+ res = e_util_utf8_make_valid (tmp->str);
+
+ g_string_free (tmp, TRUE);
+
+ return res;
+}
+
+static gboolean
+impl_Book_open (EGdbusBook *object, GDBusMethodInvocation *invocation, gboolean only_if_exists, EDataBook *book)
+{
+ OperationData *op;
+
+ op = op_new (OP_OPEN, book);
+ op->d.only_if_exists = only_if_exists;
+
+ e_gdbus_book_complete_open (book->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
+
+ return TRUE;
}
static gboolean
impl_Book_remove (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
{
- e_book_backend_remove (book->priv->backend, book, opid_store (invocation));
+ OperationData *op;
+
+ op = op_new (OP_REMOVE, book);
+
+ e_gdbus_book_complete_remove (book->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-void
-e_data_book_respond_remove (EDataBook *book, guint opid, GError *error)
+static gboolean
+impl_Book_refresh (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
{
- GDBusMethodInvocation *invocation = opid_fetch (opid);
+ OperationData *op;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Cannot remove book: %s"));
- g_error_free (error);
- } else {
- e_gdbus_book_complete_remove (book->priv->gdbus_object, invocation);
- }
+ op = op_new (OP_REFRESH, book);
+
+ e_gdbus_book_complete_refresh (book->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
+
+ return TRUE;
}
static gboolean
-impl_Book_getContact (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *IN_uid, EDataBook *book)
+impl_Book_getContact (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_uid, EDataBook *book)
{
OperationData *op;
- if (IN_uid == NULL) {
+ if (in_uid == NULL) {
GError *error;
error = e_data_book_create_error (E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, NULL);
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Cannot get contact: %s"));
+ /* Translators: This is prefix to a detailed error message */
+ data_book_return_error (invocation, error, _("Cannot get contact: "));
g_error_free (error);
return TRUE;
}
- op = op_new (OP_GET_CONTACT, book, invocation);
- op->d.uid = g_strdup (IN_uid);
- g_thread_pool_push (op_pool, op, NULL);
+ op = op_new (OP_GET_CONTACT, book);
+ op->d.uid = g_strdup (in_uid);
+
+ e_gdbus_book_complete_get_contact (book->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-void
-e_data_book_respond_get_contact (EDataBook *book, guint32 opid, GError *error, const gchar *vcard)
+static gboolean
+impl_Book_getContactList (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_query, EDataBook *book)
{
- GDBusMethodInvocation *invocation = opid_fetch (opid);
+ OperationData *op;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Cannot get contact: %s"));
+ if (in_query == NULL || !*in_query) {
+ GError *error = e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_QUERY, NULL);
+ /* Translators: This is prefix to a detailed error message */
+ data_book_return_error (invocation, error, _("Empty query: "));
g_error_free (error);
- } else {
- gchar *gdbus_vcard = NULL;
+ return TRUE;
+ }
- e_gdbus_book_complete_get_contact (book->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (vcard, &gdbus_vcard));
+ op = op_new (OP_GET_CONTACTS, book);
+ op->d.query = g_strdup (in_query);
- g_free (gdbus_vcard);
- }
+ e_gdbus_book_complete_get_contact_list (book->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
+
+ return TRUE;
}
static gboolean
-impl_Book_getContactList (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *query, EDataBook *book)
+impl_Book_addContact (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_vcard, EDataBook *book)
{
OperationData *op;
- if (query == NULL || query[0] == '\0') {
+ if (in_vcard == NULL || !*in_vcard) {
GError *error = e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_QUERY, NULL);
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Empty query: %s"));
+ /* Translators: This is prefix to a detailed error message */
+ data_book_return_error (invocation, error, _("Cannot add contact: "));
g_error_free (error);
return TRUE;
}
- op = op_new (OP_GET_CONTACTS, book, invocation);
- op->d.query = g_strdup (query);
- g_thread_pool_push (op_pool, op, NULL);
+ op = op_new (OP_ADD_CONTACT, book);
+ op->d.vcard = g_strdup (in_vcard);
- return TRUE;
-}
+ e_gdbus_book_complete_add_contact (book->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
-void
-e_data_book_respond_get_contact_list (EDataBook *book, guint32 opid, GError *error, GList *cards)
-{
- /* Translators: The '%s' is replaced with a detailed error message */
- return_error_and_list (book->priv->gdbus_object, e_gdbus_book_complete_get_contact_list, opid, error, _("Cannot get contact list: %s"), cards, TRUE);
+ return TRUE;
}
static gboolean
-impl_Book_authenticateUser (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *IN_user, const gchar *IN_passwd, const gchar *IN_auth_method, EDataBook *book)
+impl_Book_modifyContact (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_vcard, EDataBook *book)
{
OperationData *op;
- op = op_new (OP_AUTHENTICATE, book, invocation);
- op->d.auth.username = g_strdup (IN_user);
- op->d.auth.password = g_strdup (IN_passwd);
- op->d.auth.method = g_strdup (IN_auth_method);
- g_thread_pool_push (op_pool, op, NULL);
+ if (in_vcard == NULL) {
+ GError *error = e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_QUERY, NULL);
+ /* Translators: This is prefix to a detailed error message */
+ data_book_return_error (invocation, error, _("Cannot modify contact: "));
+ g_error_free (error);
+ return TRUE;
+ }
+
+ op = op_new (OP_MODIFY_CONTACT, book);
+ op->d.vcard = g_strdup (in_vcard);
+
+ e_gdbus_book_complete_modify_contact (book->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-static void
-data_book_return_error (GDBusMethodInvocation *invocation, const GError *perror, const gchar *error_fmt)
+static gboolean
+impl_Book_removeContacts (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar * const *in_uids, EDataBook *book)
{
- GError *error;
-
- if (perror == NULL)
- error = g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_OTHER_ERROR, error_fmt, _("Unknown error"));
- else
- error = g_error_new (E_DATA_BOOK_ERROR, perror->code, error_fmt, perror->message);
+ OperationData *op;
- g_dbus_method_invocation_return_gerror (invocation, error);
+ op = op_new (OP_REMOVE_CONTACTS, book);
- g_error_free (error);
-}
+ /* Allow an empty array to be removed */
+ for (; in_uids && *in_uids; in_uids++) {
+ op->d.ids = g_slist_prepend (op->d.ids, g_strdup (*in_uids));
+ }
-void
-e_data_book_respond_authenticate_user (EDataBook *book, guint32 opid, GError *error)
-{
- GDBusMethodInvocation *invocation = opid_fetch (opid);
+ e_gdbus_book_complete_remove_contacts (book->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Cannot authenticate user: %s"));
- g_error_free (error);
- } else {
- e_gdbus_book_complete_authenticate_user (book->priv->gdbus_object, invocation);
- }
+ return TRUE;
}
static gboolean
-impl_Book_addContact (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *IN_vcard, EDataBook *book)
+impl_Book_getBackendProperty (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_prop_name, EDataBook *book)
{
OperationData *op;
- if (IN_vcard == NULL || IN_vcard[0] == '\0') {
- GError *error = e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_QUERY, NULL);
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Cannot add contact: %s"));
- g_error_free (error);
- return TRUE;
- }
+ op = op_new (OP_GET_BACKEND_PROPERTY, book);
+ op->d.prop_name = g_strdup (in_prop_name);
- op = op_new (OP_ADD_CONTACT, book, invocation);
- op->d.vcard = g_strdup (IN_vcard);
- g_thread_pool_push (op_pool, op, NULL);
+ e_gdbus_book_complete_get_backend_property (book->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-void
-e_data_book_respond_create (EDataBook *book, guint32 opid, GError *error, EContact *contact)
+static gboolean
+impl_Book_setBackendProperty (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar * const *in_prop_name_value, EDataBook *book)
{
- GDBusMethodInvocation *invocation = opid_fetch (opid);
-
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Cannot add contact: %s"));
- g_error_free (error);
- } else {
- gchar *gdbus_uid = NULL;
+ OperationData *op;
- e_book_backend_notify_update (e_data_book_get_backend (book), contact);
- e_book_backend_notify_complete (e_data_book_get_backend (book));
+ op = op_new (OP_SET_BACKEND_PROPERTY, book);
+ g_return_val_if_fail (e_gdbus_book_decode_set_backend_property (in_prop_name_value, &op->d.sbp.prop_name, &op->d.sbp.prop_value), FALSE);
- e_gdbus_book_complete_add_contact (book->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (e_contact_get_const (contact, E_CONTACT_UID), &gdbus_uid));
+ e_gdbus_book_complete_set_backend_property (book->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
- g_free (gdbus_uid);
- }
+ return TRUE;
}
static gboolean
-impl_Book_modifyContact (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *IN_vcard, EDataBook *book)
+impl_Book_getBookView (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_query, EDataBook *book)
{
OperationData *op;
- if (IN_vcard == NULL) {
- GError *error = e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_QUERY, NULL);
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Cannot modify contact: %s"));
+ if (!in_query || !*in_query) {
+ GError *error;
+
+ error = e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_QUERY, NULL);
+ /* Translators: This is prefix to a detailed error message */
+ data_book_return_error (invocation, error, _("Invalid query: "));
g_error_free (error);
+
return TRUE;
}
- op = op_new (OP_MODIFY_CONTACT, book, invocation);
- op->d.vcard = g_strdup (IN_vcard);
- g_thread_pool_push (op_pool, op, NULL);
+ op = op_new (OP_GET_BOOK_VIEW, book);
+ op->d.query = g_strdup (in_query);
- return TRUE;
-}
-
-void
-e_data_book_respond_modify (EDataBook *book, guint32 opid, GError *error, EContact *contact)
-{
- GDBusMethodInvocation *invocation = opid_fetch (opid);
-
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Cannot modify contact: %s"));
- g_error_free (error);
- } else {
- e_book_backend_notify_update (e_data_book_get_backend (book), contact);
- e_book_backend_notify_complete (e_data_book_get_backend (book));
+ e_gdbus_book_complete_get_view (book->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
- e_gdbus_book_complete_modify_contact (book->priv->gdbus_object, invocation);
- }
+ return TRUE;
}
static gboolean
-impl_Book_removeContacts (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar * const *IN_uids, EDataBook *book)
+impl_Book_authenticateUser (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar * const *in_credentials, EDataBook *book)
{
OperationData *op;
- /* Allow an empty array to be removed */
- if (IN_uids == NULL) {
- e_gdbus_book_complete_remove_contacts (object, invocation);
+ if (in_credentials == NULL) {
+ GError *error = e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_ARG, NULL);
+ /* Translators: This is prefix to a detailed error message */
+ data_book_return_error (invocation, error, _("Cannot authenticate user: "));
+ g_error_free (error);
return TRUE;
}
- op = op_new (OP_REMOVE_CONTACTS, book, invocation);
+ op = op_new (OP_AUTHENTICATE, book);
+ op->d.credentials = e_credentials_new_strv (in_credentials);
- for (; *IN_uids; IN_uids++) {
- op->d.ids = g_list_prepend (op->d.ids, g_strdup (*IN_uids));
- }
-
- g_thread_pool_push (op_pool, op, NULL);
+ e_gdbus_book_complete_authenticate_user (book->priv->gdbus_object, invocation, NULL);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-void
-e_data_book_respond_remove_contacts (EDataBook *book, guint32 opid, GError *error, GList *ids)
+static gboolean
+impl_Book_cancelOperation (EGdbusBook *object, GDBusMethodInvocation *invocation, guint in_opid, EDataBook *book)
{
- GDBusMethodInvocation *invocation = opid_fetch (opid);
+ OperationData *op;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Cannot remove contacts: %s"));
- g_error_free (error);
- } else {
- GList *i;
+ op = op_new (OP_CANCEL_OPERATION, book);
+ op->d.opid = in_opid;
- for (i = ids; i; i = i->next)
- e_book_backend_notify_remove (e_data_book_get_backend (book), i->data);
- e_book_backend_notify_complete (e_data_book_get_backend (book));
+ e_gdbus_book_complete_cancel_operation (book->priv->gdbus_object, invocation, NULL);
+ e_operation_pool_push (ops_pool, op);
- e_gdbus_book_complete_remove_contacts (book->priv->gdbus_object, invocation);
- }
+ return TRUE;
}
static gboolean
-impl_Book_getStaticCapabilities (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
+impl_Book_cancelAll (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
{
- gchar *capabilities = e_book_backend_get_static_capabilities (e_data_book_get_backend (book));
- gchar *gdbus_capabilities = NULL;
+ OperationData *op;
- e_gdbus_book_complete_get_static_capabilities (object, invocation, e_util_ensure_gdbus_string (capabilities, &gdbus_capabilities));
+ op = op_new (OP_CANCEL_ALL, book);
- g_free (capabilities);
- g_free (gdbus_capabilities);
+ e_gdbus_book_complete_cancel_all (book->priv->gdbus_object, invocation, NULL);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
static gboolean
-impl_Book_getSupportedFields (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
+impl_Book_close (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
{
- e_book_backend_get_supported_fields (e_data_book_get_backend (book), book, opid_store (invocation));
+ OperationData *op;
+
+ op = op_new (OP_CLOSE, book);
+
+ e_gdbus_book_complete_close (book->priv->gdbus_object, invocation, NULL);
+ e_operation_pool_push (ops_pool, op);
+
+ g_object_unref (book);
return TRUE;
}
void
-e_data_book_respond_get_supported_fields (EDataBook *book, guint32 opid, GError *error, GList *fields)
+e_data_book_respond_open (EDataBook *book, guint opid, GError *error)
{
- /* Translators: The '%s' is replaced with a detailed error message */
- return_error_and_list (book->priv->gdbus_object, e_gdbus_book_complete_get_supported_fields, opid, error, _("Cannot get supported fields: %s"), fields, FALSE);
-}
+ op_complete (book, opid);
-static gboolean
-impl_Book_getRequiredFields (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
-{
- e_book_backend_get_required_fields (e_data_book_get_backend (book), book, opid_store (invocation));
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot open book: "));
- return TRUE;
+ e_gdbus_book_emit_open_done (book->priv->gdbus_object, opid, error);
+
+ if (error)
+ g_error_free (error);
}
void
-e_data_book_respond_get_required_fields (EDataBook *book, guint32 opid, GError *error, GList *fields)
+e_data_book_respond_remove (EDataBook *book, guint opid, GError *error)
{
- /* Translators: The '%s' is replaced with a detailed error message */
- return_error_and_list (book->priv->gdbus_object, e_gdbus_book_complete_get_required_fields, opid, error, _("Cannot get required fields: %s"), fields, FALSE);
-}
+ op_complete (book, opid);
-static gboolean
-impl_Book_getSupportedAuthMethods (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
-{
- e_book_backend_get_supported_auth_methods (e_data_book_get_backend (book), book, opid_store (invocation));
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot remove book: "));
- return TRUE;
+ e_gdbus_book_emit_remove_done (book->priv->gdbus_object, opid, error);
+
+ if (error)
+ g_error_free (error);
+ else
+ e_book_backend_set_is_removed (book->priv->backend, TRUE);
}
+/**
+ * e_data_book_respond_refresh:
+ * @book: An addressbook client interface.
+ * @error: Operation error, if any, automatically freed if passed it.
+ *
+ * Notifies listeners of the completion of the refresh method call.
+ *
+ * Since: 3.2
+ */
void
-e_data_book_respond_get_supported_auth_methods (EDataBook *book, guint32 opid, GError *error, GList *auth_methods)
+e_data_book_respond_refresh (EDataBook *book, guint32 opid, GError *error)
{
- /* Translators: The '%s' is replaced with a detailed error message */
- return_error_and_list (book->priv->gdbus_object, e_gdbus_book_complete_get_supported_auth_methods, opid, error, _("Cannot get supported authentication methods: %s"), auth_methods, FALSE);
-}
+ op_complete (book, opid);
-static gchar *
-construct_bookview_path (void)
-{
- static volatile guint counter = 1;
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot refresh address book: "));
- return g_strdup_printf ("/org/gnome/evolution/dataserver/AddressBookView/%d/%d",
- getpid (),
- g_atomic_int_exchange_and_add ((int*)&counter, 1));
+ e_gdbus_book_emit_refresh_done (book->priv->gdbus_object, opid, error);
+
+ if (error)
+ g_error_free (error);
}
-static gboolean
-impl_Book_getBookView (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *search, const guint max_results, EDataBook *book)
+void
+e_data_book_respond_get_backend_property (EDataBook *book, guint32 opid, GError *error, const gchar *prop_value)
{
- EBookBackend *backend = e_data_book_get_backend (book);
- EBookBackendSExp *card_sexp;
- EDataBookView *book_view;
- gchar *path;
- GError *error = NULL;
+ gchar *gdbus_prop_value = NULL;
- card_sexp = e_book_backend_sexp_new (search);
- if (!card_sexp) {
- error = e_data_book_create_error (E_DATA_BOOK_STATUS_INVALID_QUERY, NULL);
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Invalid query: %s"));
- g_error_free (error);
- return TRUE;
- }
+ op_complete (book, opid);
- path = construct_bookview_path ();
- book_view = e_data_book_view_new (book, search, card_sexp, max_results);
- e_data_book_view_register_gdbus_object (book_view, g_dbus_method_invocation_get_connection (invocation), path, &error);
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot get backend property: "));
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Invalid query: %s"));
+ e_gdbus_book_emit_get_backend_property_done (book->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (prop_value, &gdbus_prop_value));
+
+ if (error)
g_error_free (error);
- g_object_unref (book_view);
- g_free (path);
- return TRUE;
- }
+ g_free (gdbus_prop_value);
+}
- e_book_backend_add_book_view (backend, book_view);
+void
+e_data_book_respond_set_backend_property (EDataBook *book, guint32 opid, GError *error)
+{
+ op_complete (book, opid);
- e_gdbus_book_complete_get_book_view (object, invocation, path);
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot set backend property: "));
- g_free (path);
+ e_gdbus_book_emit_set_backend_property_done (book->priv->gdbus_object, opid, error);
- return TRUE;
+ if (error)
+ g_error_free (error);
}
-static gboolean
-impl_Book_getChanges (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *IN_change_id, EDataBook *book)
+void
+e_data_book_respond_get_contact (EDataBook *book, guint32 opid, GError *error, const gchar *vcard)
{
- OperationData *op;
+ gchar *gdbus_vcard = NULL;
- op = op_new (OP_GET_CHANGES, book, invocation);
- op->d.change_id = g_strdup (IN_change_id);
- g_thread_pool_push (op_pool, op, NULL);
+ op_complete (book, opid);
- return TRUE;
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot get contact: "));
+
+ e_gdbus_book_emit_get_contact_done (book->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (vcard, &gdbus_vcard));
+
+ if (error)
+ g_error_free (error);
+
+ g_free (gdbus_vcard);
}
void
-e_data_book_respond_get_changes (EDataBook *book, guint32 opid, GError *error, GList *changes)
+e_data_book_respond_get_contact_list (EDataBook *book, guint32 opid, GError *error, const GSList *cards)
{
- GDBusMethodInvocation *invocation = opid_fetch (opid);
-
if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Cannot get changes: %s"));
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot get contact list: "));
+ e_gdbus_book_emit_get_contact_list_done (book->priv->gdbus_object, opid, error, NULL);
g_error_free (error);
} else {
- GVariantBuilder *builder;
- GVariant *variant;
-
- builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
+ gchar **array;
+ const GSList *l;
+ gint i = 0;
- while (changes != NULL) {
- EDataBookChange *change = (EDataBookChange *) changes->data;
- gchar *gdbus_vcard = NULL;
+ array = g_new0 (gchar *, g_slist_length ((GSList *) cards) + 1);
+ for (l = cards; l != NULL; l = l->next) {
+ array[i++] = e_util_utf8_make_valid (l->data);
+ }
- g_variant_builder_add (builder, "(us)", change->change_type, e_util_ensure_gdbus_string (change->vcard, &gdbus_vcard));
+ e_gdbus_book_emit_get_contact_list_done (book->priv->gdbus_object, opid, NULL, (const gchar * const *) array);
- g_free (gdbus_vcard);
- g_free (change->vcard);
- g_free (change);
+ g_strfreev (array);
+ }
+}
- changes = g_list_remove (changes, change);
- }
+void
+e_data_book_respond_create (EDataBook *book, guint32 opid, GError *error, const EContact *contact)
+{
+ gchar *gdbus_uid = NULL;
- /* always add one empty value */
- g_variant_builder_add (builder, "(us)", -1, "");
+ op_complete (book, opid);
- variant = g_variant_builder_end (builder);
- g_variant_builder_unref (builder);
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot add contact: "));
- e_gdbus_book_complete_get_changes (book->priv->gdbus_object, invocation, variant);
+ e_gdbus_book_emit_add_contact_done (book->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (e_contact_get_const ((EContact *) contact, E_CONTACT_UID), &gdbus_uid));
- g_variant_unref (variant);
+ g_free (gdbus_uid);
+ if (error) {
+ g_error_free (error);
+ } else {
+ e_book_backend_notify_update (e_data_book_get_backend (book), contact);
+ e_book_backend_notify_complete (e_data_book_get_backend (book));
}
}
-static gboolean
-impl_Book_cancelOperation (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
+void
+e_data_book_respond_modify (EDataBook *book, guint32 opid, GError *error, const EContact *contact)
{
- GError *error = NULL;
+ op_complete (book, opid);
+
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot modify contact: "));
- e_book_backend_cancel_operation (e_data_book_get_backend (book), book, &error);
+ e_gdbus_book_emit_modify_contact_done (book->priv->gdbus_object, opid, error);
if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_book_return_error (invocation, error, _("Cancel operation failed: %s"));
g_error_free (error);
} else {
- e_gdbus_book_complete_cancel_operation (object, invocation);
+ e_book_backend_notify_update (e_data_book_get_backend (book), contact);
+ e_book_backend_notify_complete (e_data_book_get_backend (book));
}
-
- return TRUE;
}
-static gboolean
-impl_Book_close (EGdbusBook *object, GDBusMethodInvocation *invocation, EDataBook *book)
+void
+e_data_book_respond_remove_contacts (EDataBook *book, guint32 opid, GError *error, const GSList *ids)
{
- e_book_backend_cancel_operation (e_data_book_get_backend (book), book, NULL);
- e_book_backend_remove_client (e_data_book_get_backend (book), book);
+ op_complete (book, opid);
- e_gdbus_book_complete_close (object, invocation);
- g_object_unref (book);
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot remove contacts: "));
+
+ e_gdbus_book_emit_remove_contacts_done (book->priv->gdbus_object, opid, error);
+
+ if (error) {
+ g_error_free (error);
+ } else {
+ const GSList *ii;
+
+ for (ii = ids; ii; ii = ii->next)
+ e_book_backend_notify_remove (e_data_book_get_backend (book), ii->data);
+
+ e_book_backend_notify_complete (e_data_book_get_backend (book));
+ }
- return TRUE;
}
void
-e_data_book_report_writable (EDataBook *book, gboolean writable)
+e_data_book_report_error (EDataBook *book, const gchar *message)
{
g_return_if_fail (book != NULL);
+ g_return_if_fail (message != NULL);
- e_gdbus_book_emit_writable (book->priv->gdbus_object, writable);
+ e_gdbus_book_emit_backend_error (book->priv->gdbus_object, message);
}
void
-e_data_book_report_connection_status (EDataBook *book, gboolean connected)
+e_data_book_report_readonly (EDataBook *book, gboolean readonly)
{
g_return_if_fail (book != NULL);
- e_gdbus_book_emit_connection (book->priv->gdbus_object, connected);
+ e_gdbus_book_emit_readonly (book->priv->gdbus_object, readonly);
}
void
-e_data_book_report_auth_required (EDataBook *book)
+e_data_book_report_online (EDataBook *book, gboolean is_online)
{
g_return_if_fail (book != NULL);
- e_gdbus_book_emit_auth_required (book->priv->gdbus_object);
+ e_gdbus_book_emit_online (book->priv->gdbus_object, is_online);
}
-static void
-return_error_and_list (EGdbusBook *gdbus_object, void (* complete_func) (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar * const *out_array), guint32 opid, GError *error, const gchar *error_fmt, GList *list, gboolean free_data)
+/* credentilas contains extra information for a source for which authentication is requested.
+ This parameter can be NULL to indicate "for this book".
+*/
+void
+e_data_book_report_auth_required (EDataBook *book, const ECredentials *credentials)
{
- GDBusMethodInvocation *invocation = opid_fetch (opid);
+ gchar *empty_strv[2];
+ gchar **strv = NULL;
- g_return_if_fail (error_fmt != NULL);
- g_return_if_fail (complete_func != NULL);
+ g_return_if_fail (book != NULL);
- if (error) {
- data_book_return_error (invocation, error, error_fmt);
- g_error_free (error);
- } else {
- gchar **array;
- GList *l;
- gint i = 0;
+ empty_strv[0] = NULL;
+ empty_strv[1] = NULL;
- array = g_new0 (gchar *, g_list_length (list) + 1);
- for (l = list; l != NULL; l = l->next) {
- array[i++] = e_util_utf8_make_valid (l->data);
- if (free_data)
- g_free (l->data);
- }
+ if (credentials)
+ strv = e_credentials_to_strv (credentials);
- complete_func (gdbus_object, invocation, (const gchar * const *) array);
+ e_gdbus_book_emit_auth_required (book->priv->gdbus_object, (const gchar * const *) (strv ? strv : empty_strv));
- g_strfreev (array);
- }
+ g_strfreev (strv);
+}
+
+/* Reports to associated client that opening phase of the book is finished.
+ error being NULL means successfully, otherwise reports an error which happened
+ during opening phase. By opening phase is meant a process including successfull
+ authentication to the server/storage.
+*/
+void
+e_data_book_report_opened (EDataBook *book, const GError *error)
+{
+ gchar **strv_error;
+
+ strv_error = e_gdbus_templates_encode_error (error);
+
+ e_gdbus_book_emit_opened (book->priv->gdbus_object, (const gchar * const *) strv_error);
+
+ g_strfreev (strv_error);
}
/**
@@ -854,28 +1020,29 @@ e_data_book_init (EDataBook *ebook)
ebook, E_TYPE_DATA_BOOK, EDataBookPrivate);
ebook->priv->gdbus_object = e_gdbus_book_stub_new ();
+ ebook->priv->pending_ops = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
+ g_static_rec_mutex_init (&ebook->priv->pending_ops_lock);
gdbus_object = ebook->priv->gdbus_object;
g_signal_connect (gdbus_object, "handle-open", G_CALLBACK (impl_Book_open), ebook);
g_signal_connect (gdbus_object, "handle-remove", G_CALLBACK (impl_Book_remove), ebook);
+ g_signal_connect (gdbus_object, "handle-refresh", G_CALLBACK (impl_Book_refresh), ebook);
g_signal_connect (gdbus_object, "handle-get-contact", G_CALLBACK (impl_Book_getContact), ebook);
g_signal_connect (gdbus_object, "handle-get-contact-list", G_CALLBACK (impl_Book_getContactList), ebook);
g_signal_connect (gdbus_object, "handle-authenticate-user", G_CALLBACK (impl_Book_authenticateUser), ebook);
g_signal_connect (gdbus_object, "handle-add-contact", G_CALLBACK (impl_Book_addContact), ebook);
g_signal_connect (gdbus_object, "handle-remove-contacts", G_CALLBACK (impl_Book_removeContacts), ebook);
g_signal_connect (gdbus_object, "handle-modify-contact", G_CALLBACK (impl_Book_modifyContact), ebook);
- g_signal_connect (gdbus_object, "handle-get-static-capabilities", G_CALLBACK (impl_Book_getStaticCapabilities), ebook);
- g_signal_connect (gdbus_object, "handle-get-required-fields", G_CALLBACK (impl_Book_getRequiredFields), ebook);
- g_signal_connect (gdbus_object, "handle-get-supported-fields", G_CALLBACK (impl_Book_getSupportedFields), ebook);
- g_signal_connect (gdbus_object, "handle-get-supported-auth-methods", G_CALLBACK (impl_Book_getSupportedAuthMethods), ebook);
- g_signal_connect (gdbus_object, "handle-get-book-view", G_CALLBACK (impl_Book_getBookView), ebook);
- g_signal_connect (gdbus_object, "handle-get-changes", G_CALLBACK (impl_Book_getChanges), ebook);
+ g_signal_connect (gdbus_object, "handle-get-backend-property", G_CALLBACK (impl_Book_getBackendProperty), ebook);
+ g_signal_connect (gdbus_object, "handle-set-backend-property", G_CALLBACK (impl_Book_setBackendProperty), ebook);
+ g_signal_connect (gdbus_object, "handle-get-view", G_CALLBACK (impl_Book_getBookView), ebook);
g_signal_connect (gdbus_object, "handle-cancel-operation", G_CALLBACK (impl_Book_cancelOperation), ebook);
+ g_signal_connect (gdbus_object, "handle-cancel-all", G_CALLBACK (impl_Book_cancelAll), ebook);
g_signal_connect (gdbus_object, "handle-close", G_CALLBACK (impl_Book_close), ebook);
}
static void
-e_data_book_dispose (GObject *object)
+data_book_dispose (GObject *object)
{
EDataBook *book = E_DATA_BOOK (object);
@@ -897,6 +1064,13 @@ data_book_finalize (GObject *object)
{
EDataBook *book = E_DATA_BOOK (object);
+ if (book->priv->pending_ops) {
+ g_hash_table_destroy (book->priv->pending_ops);
+ book->priv->pending_ops = NULL;
+ }
+
+ g_static_rec_mutex_free (&book->priv->pending_ops_lock);
+
if (book->priv->gdbus_object) {
g_object_unref (book->priv->gdbus_object);
book->priv->gdbus_object = NULL;
@@ -912,15 +1086,11 @@ e_data_book_class_init (EDataBookClass *klass)
g_type_class_add_private (klass, sizeof (EDataBookPrivate));
- object_class->dispose = e_data_book_dispose;
+ object_class->dispose = data_book_dispose;
object_class->finalize = data_book_finalize;
- if (!op_pool) {
- op_pool = g_thread_pool_new (operation_thread, NULL, 10, FALSE, NULL);
-
- /* Kill threads which don't do anything for 10 seconds */
- g_thread_pool_set_max_idle_time (10 * 1000);
- }
+ if (!ops_pool)
+ ops_pool = e_operation_pool_new (10, operation_thread, NULL);
}
EDataBook *
diff --git a/addressbook/libedata-book/e-data-book.h b/addressbook/libedata-book/e-data-book.h
index 5ea18a0..5f5d879 100644
--- a/addressbook/libedata-book/e-data-book.h
+++ b/addressbook/libedata-book/e-data-book.h
@@ -20,12 +20,15 @@
* Author: Ross Burton <ross linux intel com>
*/
-#ifndef __E_DATA_BOOK_H__
-#define __E_DATA_BOOK_H__
+#ifndef E_DATA_BOOK_H
+#define E_DATA_BOOK_H
#include <glib-object.h>
#include <gio/gio.h>
+
+#include <libedataserver/e-credentials.h>
#include <libedataserver/e-source.h>
+
#include "e-book-backend.h"
#include "e-data-book-types.h"
@@ -101,69 +104,54 @@ const gchar *e_data_book_status_to_string (EDataBookStatus status);
} \
} G_STMT_END
-EDataBook *e_data_book_new (EBookBackend *backend, ESource *source);
-
-guint e_data_book_register_gdbus_object (EDataBook *cal, GDBusConnection *connection, const gchar *object_path, GError **error);
-
-EBookBackend *e_data_book_get_backend (EDataBook *book);
-ESource *e_data_book_get_source (EDataBook *book);
-
-void e_data_book_respond_open (EDataBook *book,
- guint32 opid,
- GError *error);
-void e_data_book_respond_remove (EDataBook *book,
- guint32 opid,
- GError *error);
-void e_data_book_respond_create (EDataBook *book,
- guint32 opid,
- GError *error,
- EContact *contact);
-void e_data_book_respond_remove_contacts (EDataBook *book,
- guint32 opid,
- GError *error,
- GList *ids);
-void e_data_book_respond_modify (EDataBook *book,
- guint32 opid,
- GError *error,
- EContact *contact);
-void e_data_book_respond_authenticate_user (EDataBook *book,
- guint32 opid,
- GError *error);
-void e_data_book_respond_get_supported_fields (EDataBook *book,
- guint32 opid,
- GError *error,
- GList *fields);
-void e_data_book_respond_get_required_fields (EDataBook *book,
- guint32 opid,
- GError *error,
- GList *fields);
-void e_data_book_respond_get_supported_auth_methods (EDataBook *book,
- guint32 opid,
- GError *error,
- GList *fields);
-
-void e_data_book_respond_get_contact (EDataBook *book,
- guint32 opid,
- GError *error,
- const gchar *vcard);
-void e_data_book_respond_get_contact_list (EDataBook *book,
- guint32 opid,
- GError *error,
- GList *cards);
-void e_data_book_respond_get_changes (EDataBook *book,
- guint32 opid,
- GError *error,
- GList *changes);
-
-void e_data_book_report_writable (EDataBook *book,
- gboolean writable);
-void e_data_book_report_connection_status (EDataBook *book,
- gboolean is_online);
-
-void e_data_book_report_auth_required (EDataBook *book);
-
-GType e_data_book_get_type (void);
+/**
+ * e_return_data_book_error_if_fail:
+ *
+ * Same as e_return_data_book_error_if_fail(), only returns FALSE on a failure
+ *
+ * Since: 3.2
+ **/
+#define e_return_data_book_error_val_if_fail(expr, _code) \
+ G_STMT_START { \
+ if (G_LIKELY (expr)) { \
+ } else { \
+ g_log (G_LOG_DOMAIN, \
+ G_LOG_LEVEL_CRITICAL, \
+ "file %s: line %d (%s): assertion `%s' failed", \
+ __FILE__, __LINE__, G_STRFUNC, #expr); \
+ g_set_error (error, E_DATA_BOOK_ERROR, (_code), \
+ "file %s: line %d (%s): assertion `%s' failed", \
+ __FILE__, __LINE__, G_STRFUNC, #expr); \
+ return FALSE; \
+ } \
+ } G_STMT_END
+
+GType e_data_book_get_type (void);
+EDataBook * e_data_book_new (EBookBackend *backend, ESource *source);
+EBookBackend * e_data_book_get_backend (EDataBook *book);
+ESource * e_data_book_get_source (EDataBook *book);
+
+guint e_data_book_register_gdbus_object (EDataBook *cal, GDBusConnection *connection, const gchar *object_path, GError **error);
+
+void e_data_book_respond_open (EDataBook *book, guint32 opid, GError *error);
+void e_data_book_respond_remove (EDataBook *book, guint32 opid, GError *error);
+void e_data_book_respond_refresh (EDataBook *book, guint32 opid, GError *error);
+void e_data_book_respond_get_backend_property (EDataBook *book, guint32 opid, GError *error, const gchar *prop_value);
+void e_data_book_respond_set_backend_property (EDataBook *book, guint32 opid, GError *error);
+void e_data_book_respond_create (EDataBook *book, guint32 opid, GError *error, const EContact *contact);
+void e_data_book_respond_remove_contacts (EDataBook *book, guint32 opid, GError *error, const GSList *ids);
+void e_data_book_respond_modify (EDataBook *book, guint32 opid, GError *error, const EContact *contact);
+void e_data_book_respond_get_contact (EDataBook *book, guint32 opid, GError *error, const gchar *vcard);
+void e_data_book_respond_get_contact_list (EDataBook *book, guint32 opid, GError *error, const GSList *cards);
+
+void e_data_book_report_error (EDataBook *book, const gchar *message);
+void e_data_book_report_readonly (EDataBook *book, gboolean readonly);
+void e_data_book_report_online (EDataBook *book, gboolean is_online);
+void e_data_book_report_auth_required (EDataBook *book, const ECredentials *credentials);
+void e_data_book_report_opened (EDataBook *book, const GError *error);
+
+gchar * e_data_book_string_slist_to_comma_string (const GSList *strings);
G_END_DECLS
-#endif /* __E_DATA_BOOK_H__ */
+#endif /* E_DATA_BOOK_H */
diff --git a/addressbook/libegdbus/Makefile.am b/addressbook/libegdbus/Makefile.am
index 41644a3..f564535 100644
--- a/addressbook/libegdbus/Makefile.am
+++ b/addressbook/libegdbus/Makefile.am
@@ -1,13 +1,3 @@
-GDBUS_XML_FILES = \
- ../libedata-book/e-data-book-factory.xml \
- ../libedata-book/e-data-book-view.xml \
- ../libedata-book/e-data-book.xml
-
-gdbus-files: $(GDBUS_XML_FILES)
- gdbus-codegen --namespace=EGdbus --strip-prefix=org.gnome.evolution.dataserver.addressbook --output-prefix=e-gdbus $(GDBUS_XML_FILES)
- rm e-gdbus-bindings.h
- rm e-gdbus-bindings.stamp
-
# The library
noinst_LTLIBRARIES = libegdbus-book.la
@@ -19,21 +9,17 @@ libegdbus_book_la_CPPFLAGS = \
$(E_DATA_SERVER_CFLAGS)
libegdbus_book_la_SOURCES = \
- e-gdbus-egdbusbook.h \
- e-gdbus-egdbusbook.c \
- e-gdbus-egdbusbookfactory.h \
- e-gdbus-egdbusbookfactory.c \
- e-gdbus-egdbusbookview.h \
- e-gdbus-egdbusbookview.c \
- e-gdbus-marshallers.h \
- e-gdbus-marshallers.c \
- e-gdbus-typemappers.h
+ e-gdbus-book.h \
+ e-gdbus-book.c \
+ e-gdbus-book-factory.h \
+ e-gdbus-book-factory.c \
+ e-gdbus-book-view.h \
+ e-gdbus-book-view.c
libegdbus_book_la_LIBADD = \
+ $(top_builddir)/libedataserver/libedataserver-1.2.la \
$(E_DATA_SERVER_LIBS)
libegdbus_book_la_LDFLAGS = $(NO_UNDEFINED)
-EXTRA_DIST = e-gdbus-marshallers.list
-
-include $(top_srcdir)/git.mk
diff --git a/addressbook/libegdbus/e-gdbus-book-factory.c b/addressbook/libegdbus/e-gdbus-book-factory.c
new file mode 100644
index 0000000..3536f59
--- /dev/null
+++ b/addressbook/libegdbus/e-gdbus-book-factory.c
@@ -0,0 +1,551 @@
+/*
+ * e-gdbus-book-factory.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#include <stdio.h>
+#include <gio/gio.h>
+
+#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-gdbus-marshallers.h>
+
+#include "e-gdbus-book-factory.h"
+
+#define GDBUS_BOOK_FACTORY_INTERFACE_NAME "org.gnome.evolution.dataserver.AddressBookFactory"
+
+typedef EGdbusBookFactoryIface EGdbusBookFactoryInterface;
+G_DEFINE_INTERFACE (EGdbusBookFactory, e_gdbus_book_factory, G_TYPE_OBJECT);
+
+enum
+{
+ _0_SIGNAL,
+ __GET_BOOK_METHOD,
+ __LAST_SIGNAL
+};
+
+static guint signals[__LAST_SIGNAL] = {0};
+
+/* ------------------------------------------------------------------------- */
+
+/* Various lookup tables */
+
+static GHashTable *_method_name_to_id = NULL;
+static GHashTable *_method_name_to_type = NULL;
+
+static guint
+lookup_method_id_from_method_name (const gchar *method_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_method_name_to_id, method_name));
+}
+
+static guint
+lookup_method_type_from_method_name (const gchar *method_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_method_name_to_type, method_name));
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void
+e_gdbus_book_factory_default_init (EGdbusBookFactoryIface *iface)
+{
+ /* Build lookup structures */
+ _method_name_to_id = g_hash_table_new (g_str_hash, g_str_equal);
+ _method_name_to_type = g_hash_table_new (g_str_hash, g_str_equal);
+
+ E_INIT_GDBUS_METHOD_STRING (EGdbusBookFactoryIface, "getBook", get_book, __GET_BOOK_METHOD)
+}
+
+void
+e_gdbus_book_factory_call_get_book (GDBusProxy *proxy, const gchar *in_source, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_string ("getBook", proxy, in_source, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_factory_call_get_book_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_path, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_string (proxy, result, out_path, error);
+}
+
+gboolean
+e_gdbus_book_factory_call_get_book_sync (GDBusProxy *proxy, const gchar *in_source, gchar **out_path, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_string__string ("getBook", proxy, in_source, out_path, cancellable, error);
+}
+
+void
+e_gdbus_book_factory_complete_get_book (EGdbusBookFactory *object, GDBusMethodInvocation *invocation, const gchar *out_path, const GError *error)
+{
+ e_gdbus_complete_sync_method_string (object, invocation, out_path, error);
+}
+
+E_DECLARE_GDBUS_SYNC_METHOD_1_WITH_RETURN (book_factory, getBook, source, "s", path, "s")
+
+static const GDBusMethodInfo * const e_gdbus_book_factory_method_info_pointers[] =
+{
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book_factory, getBook),
+ NULL
+};
+
+static const GDBusInterfaceInfo _e_gdbus_book_factory_interface_info =
+{
+ -1,
+ (gchar *) GDBUS_BOOK_FACTORY_INTERFACE_NAME,
+ (GDBusMethodInfo **) &e_gdbus_book_factory_method_info_pointers,
+ (GDBusSignalInfo **) NULL,
+ (GDBusPropertyInfo **) NULL
+};
+
+static void
+handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ guint method_id, method_type;
+
+ method_id = lookup_method_id_from_method_name (method_name);
+ method_type = lookup_method_type_from_method_name (method_name);
+
+ g_return_if_fail (method_id != 0);
+ g_return_if_fail (method_type != 0);
+
+ e_gdbus_stub_handle_method_call (user_data, invocation, parameters, method_name, signals[method_id], method_type);
+}
+
+static GVariant *
+get_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data)
+{
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This implementation does not support property `%s'", property_name);
+ return NULL;
+}
+
+static gboolean
+set_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GVariant *value, GError **error, gpointer user_data)
+{
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This implementation does not support property `%s'", property_name);
+ return FALSE;
+}
+
+static const GDBusInterfaceVTable e_gdbus_book_factory_interface_vtable =
+{
+ handle_method_call,
+ get_property,
+ set_property
+};
+
+static gboolean
+emit_notifications_in_idle (gpointer user_data)
+{
+ GObject *object = G_OBJECT (user_data);
+ GDBusConnection *connection;
+ const gchar *path;
+ GHashTable *notification_queue;
+ GHashTableIter iter;
+ const gchar *property_name;
+ GVariant *value;
+ GVariantBuilder *builder;
+ GVariantBuilder *invalidated_builder;
+ GHashTable *pvc;
+ gboolean has_changes;
+
+ notification_queue = g_object_get_data (object, "gdbus-codegen-notification-queue");
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ pvc = g_object_get_data (object, "gdbus-codegen-pvc");
+ g_assert (notification_queue != NULL && path != NULL && connection != NULL && pvc != NULL);
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
+ invalidated_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ g_hash_table_iter_init (&iter, notification_queue);
+ has_changes = FALSE;
+ while (g_hash_table_iter_next (&iter, (gpointer) &property_name, (gpointer) &value)) {
+ GVariant *cached_value;
+ cached_value = g_hash_table_lookup (pvc, property_name);
+ if (cached_value == NULL || !g_variant_equal (cached_value, value)) {
+ g_hash_table_insert (pvc, (gpointer) property_name, (gpointer) g_variant_ref (value));
+ g_variant_builder_add (builder, "{sv}", property_name, value);
+ has_changes = TRUE;
+ }
+ }
+
+ if (has_changes) {
+ g_dbus_connection_emit_signal (connection,
+ NULL,
+ path,
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ g_variant_new ("(sa{sv}as)",
+ GDBUS_BOOK_FACTORY_INTERFACE_NAME,
+ builder,
+ invalidated_builder),
+ NULL);
+ } else {
+ g_variant_builder_unref (builder);
+ g_variant_builder_unref (invalidated_builder);
+ }
+
+ g_hash_table_remove_all (notification_queue);
+ g_object_set_data (object, "gdbus-codegen-notification-idle-id", GUINT_TO_POINTER (0));
+ return FALSE;
+}
+
+/**
+ * e_gdbus_book_factory_drain_notify:
+ * @object: A #EGdbusBookFactory that is exported.
+ *
+ * If @object has queued notifications, empty the queue forcing
+ * the <literal>PropertiesChanged</literal> signal to be emitted.
+ * See <xref linkend="EGdbusBookFactory.description"/> for more background information.
+ */
+void
+e_gdbus_book_factory_drain_notify (EGdbusBookFactory *object)
+{
+ gint idle_id;
+ idle_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (object), "gdbus-codegen-notification-idle-id"));
+ if (idle_id > 0) {
+ emit_notifications_in_idle (object);
+ g_source_remove (idle_id);
+ }
+}
+
+static void
+on_object_unregistered (GObject *object)
+{
+ gint idle_id;
+ idle_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (object), "gdbus-codegen-notification-idle-id"));
+ if (idle_id > 0) {
+ g_source_remove (idle_id);
+ }
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-path", NULL);
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-connection", NULL);
+}
+
+/**
+ * e_gdbus_book_factory_register_object:
+ * @object: An instance of a #GObject<!-- -->-derived type implementing the #EGdbusBookFactory interface.
+ * @connection: A #GDBusConnection.
+ * @object_path: The object to register the object at.
+ * @error: Return location for error or %NULL.
+ *
+ * Registers @object at @object_path on @connection.
+ *
+ * See <xref linkend="EGdbusBookFactory.description"/>
+ * for how properties, methods and signals are handled.
+ *
+ * Returns: 0 if @error is set, otherwise a registration id (never 0) that can be used with g_dbus_connection_unregister_object().
+ */
+guint
+e_gdbus_book_factory_register_object (EGdbusBookFactory *object, GDBusConnection *connection, const gchar *object_path, GError **error)
+{
+ GHashTable *pvc;
+
+ pvc = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_variant_unref);
+
+ g_object_set_data_full (G_OBJECT (object), "gdbus-codegen-path", (gpointer) g_strdup (object_path), g_free);
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-connection", (gpointer) connection);
+ g_object_set_data_full (G_OBJECT (object), "gdbus-codegen-pvc", (gpointer) pvc, (GDestroyNotify) g_hash_table_unref);
+
+ return g_dbus_connection_register_object (connection,
+ object_path,
+ (GDBusInterfaceInfo *) &_e_gdbus_book_factory_interface_info,
+ &e_gdbus_book_factory_interface_vtable,
+ object,
+ (GDestroyNotify) on_object_unregistered,
+ error);
+}
+
+/**
+ * e_gdbus_book_factory_interface_info:
+ *
+ * Gets interface description for the <literal>org.gnome.evolution.dataserver.AddressBookFactory</literal> D-Bus interface.
+ *
+ * Returns: A #GDBusInterfaceInfo. Do not free, the object is statically allocated.
+ */
+const GDBusInterfaceInfo *
+e_gdbus_book_factory_interface_info (void)
+{
+ return &_e_gdbus_book_factory_interface_info;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void proxy_iface_init (EGdbusBookFactoryIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EGdbusBookFactoryProxy, e_gdbus_book_factory_proxy, G_TYPE_DBUS_PROXY,
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_BOOK_FACTORY, proxy_iface_init));
+
+static void
+e_gdbus_book_factory_proxy_init (EGdbusBookFactoryProxy *proxy)
+{
+ g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), (GDBusInterfaceInfo *) &_e_gdbus_book_factory_interface_info);
+}
+
+static void
+g_signal (GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters)
+{
+ /*
+ guint signal_id, signal_type;
+
+ signal_id = lookup_signal_id_from_signal_name (signal_name);
+ signal_type = lookup_signal_type_from_signal_name (signal_name);
+
+ g_return_if_fail (signal_id != 0);
+ g_return_if_fail (signal_type != 0);
+
+ e_gdbus_proxy_emit_signal (proxy, parameters, signals[signal_id], signal_type);
+ */
+}
+
+static void
+e_gdbus_book_factory_proxy_class_init (EGdbusBookFactoryProxyClass *klass)
+{
+ GDBusProxyClass *proxy_class;
+
+ proxy_class = G_DBUS_PROXY_CLASS (klass);
+ proxy_class->g_signal = g_signal;
+}
+
+static void
+proxy_iface_init (EGdbusBookFactoryIface *iface)
+{
+}
+
+/**
+ * e_gdbus_book_factory_proxy_new:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: Callback function to invoke when the proxy is ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_dbus_proxy_new() but returns a #EGdbusBookFactoryProxy.
+ *
+ * This is a failable asynchronous constructor - when the proxy is ready, callback will be invoked and you can use e_gdbus_book_factory_proxy_new_finish() to get the result.
+ */
+void
+e_gdbus_book_factory_proxy_new (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ g_async_initable_new_async (E_TYPE_GDBUS_BOOK_FACTORY_PROXY,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "g-flags", flags,
+ "g-name", name,
+ "g-connection", connection,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_BOOK_FACTORY_INTERFACE_NAME,
+ NULL);
+}
+
+/**
+ * e_gdbus_book_factory_proxy_new_finish:
+ * @result: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to e_gdbus_book_factory_proxy_new().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes creating a #EGdbusBookFactoryProxy.
+ *
+ * Returns: A #EGdbusBookFactoryProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+EGdbusBookFactory *
+e_gdbus_book_factory_proxy_new_finish (GAsyncResult *result, GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (result);
+ g_assert (source_object != NULL);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error);
+ g_object_unref (source_object);
+ if (object != NULL)
+ return E_GDBUS_BOOK_FACTORY (object);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_book_factory_proxy_new_sync:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_proxy_new_sync() but returns a #EGdbusBookFactoryProxy.
+ *
+ * This is a synchronous failable constructor. See e_gdbus_book_factory_proxy_new() and e_gdbus_book_factory_proxy_new_finish() for the asynchronous version.
+ *
+ * Returns: A #EGdbusBookFactoryProxy or %NULL if error is set. Free with g_object_unref().
+ */
+EGdbusBookFactory *
+e_gdbus_book_factory_proxy_new_sync (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error)
+{
+ GInitable *initable;
+ initable = g_initable_new (E_TYPE_GDBUS_BOOK_FACTORY_PROXY,
+ cancellable,
+ error,
+ "g-flags", flags,
+ "g-name", name,
+ "g-connection", connection,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_BOOK_FACTORY_INTERFACE_NAME,
+ NULL);
+ if (initable != NULL)
+ return E_GDBUS_BOOK_FACTORY (initable);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_book_factory_proxy_new_for_bus:
+ * @bus_type: A #GBusType.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: Callback function to invoke when the proxy is ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_dbus_proxy_new_for_bus() but returns a #EGdbusBookFactoryProxy.
+ *
+ * This is a failable asynchronous constructor - when the proxy is ready, callback will be invoked and you can use e_gdbus_book_factory_proxy_new_for_bus_finish() to get the result.
+ */
+void
+e_gdbus_book_factory_proxy_new_for_bus (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ g_async_initable_new_async (E_TYPE_GDBUS_BOOK_FACTORY_PROXY,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "g-flags", flags,
+ "g-name", name,
+ "g-bus-type", bus_type,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_BOOK_FACTORY_INTERFACE_NAME,
+ NULL);
+}
+
+/**
+ * e_gdbus_book_factory_proxy_new_for_bus_finish:
+ * @result: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to e_gdbus_book_factory_proxy_new_for_bus().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes creating a #EGdbusBookFactoryProxy.
+ *
+ * Returns: A #EGdbusBookFactoryProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+EGdbusBookFactory *
+e_gdbus_book_factory_proxy_new_for_bus_finish (GAsyncResult *result, GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (result);
+ g_assert (source_object != NULL);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error);
+ g_object_unref (source_object);
+ if (object != NULL)
+ return E_GDBUS_BOOK_FACTORY (object);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_book_factory_proxy_new_for_bus_sync:
+ * @bus_type: A #GBusType.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_proxy_new_for_bus_sync() but returns a #EGdbusBookFactoryProxy.
+ *
+ * This is a synchronous failable constructor. See e_gdbus_book_factory_proxy_new_for_bus() and e_gdbus_book_factory_proxy_new_for_bus_finish() for the asynchronous version.
+ *
+ * Returns: A #EGdbusBookFactoryProxy or %NULL if error is set. Free with g_object_unref().
+ */
+EGdbusBookFactory *
+e_gdbus_book_factory_proxy_new_for_bus_sync (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error)
+{
+ GInitable *initable;
+ initable = g_initable_new (E_TYPE_GDBUS_BOOK_FACTORY_PROXY,
+ cancellable,
+ error,
+ "g-flags", flags,
+ "g-name", name,
+ "g-bus-type", bus_type,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_BOOK_FACTORY_INTERFACE_NAME,
+ NULL);
+ if (initable != NULL)
+ return E_GDBUS_BOOK_FACTORY (initable);
+ else
+ return NULL;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct _EGdbusBookFactoryStubPrivate
+{
+ gint foo;
+};
+
+static void stub_iface_init (EGdbusBookFactoryIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EGdbusBookFactoryStub, e_gdbus_book_factory_stub, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_BOOK_FACTORY, stub_iface_init));
+
+static void
+e_gdbus_book_factory_stub_init (EGdbusBookFactoryStub *stub)
+{
+ stub->priv = G_TYPE_INSTANCE_GET_PRIVATE (stub, E_TYPE_GDBUS_BOOK_FACTORY_STUB, EGdbusBookFactoryStubPrivate);
+}
+
+static void
+e_gdbus_book_factory_stub_class_init (EGdbusBookFactoryStubClass *klass)
+{
+ g_type_class_add_private (klass, sizeof (EGdbusBookFactoryStubPrivate));
+}
+
+static void
+stub_iface_init (EGdbusBookFactoryIface *iface)
+{
+}
+
+/**
+ * e_gdbus_book_factory_stub_new:
+ *
+ * Creates a new stub object that can be exported via e_gdbus_book_factory_register_object().
+ *
+ * Returns: A #EGdbusBookFactoryStub instance. Free with g_object_unref().
+ */
+EGdbusBookFactory *
+e_gdbus_book_factory_stub_new (void)
+{
+ return E_GDBUS_BOOK_FACTORY (g_object_new (E_TYPE_GDBUS_BOOK_FACTORY_STUB, NULL));
+}
diff --git a/addressbook/libegdbus/e-gdbus-book-factory.h b/addressbook/libegdbus/e-gdbus-book-factory.h
new file mode 100644
index 0000000..588de6c
--- /dev/null
+++ b/addressbook/libegdbus/e-gdbus-book-factory.h
@@ -0,0 +1,120 @@
+/*
+ * e-gdbus-book-factory.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_GDBUS_BOOK_FACTORY_H
+#define E_GDBUS_BOOK_FACTORY_H
+
+#include <gio/gio.h>
+
+#include <libedataserver/e-gdbus-templates.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_GDBUS_BOOK_FACTORY (e_gdbus_book_factory_get_type ())
+#define E_GDBUS_BOOK_FACTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_GDBUS_BOOK_FACTORY, EGdbusBookFactory))
+#define E_IS_GDBUS_BOOK_FACTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_GDBUS_BOOK_FACTORY))
+#define E_GDBUS_BOOK_FACTORY_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE((o), E_TYPE_GDBUS_BOOK_FACTORY, EGdbusBookFactoryIface))
+
+/**
+ * EGdbusBookFactory:
+ *
+ * Opaque type representing a proxy or an exported object.
+ */
+typedef struct _EGdbusBookFactory EGdbusBookFactory; /* Dummy typedef */
+typedef struct _EGdbusBookFactoryIface EGdbusBookFactoryIface;
+
+GType e_gdbus_book_factory_get_type (void) G_GNUC_CONST;
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct _EGdbusBookFactoryProxy EGdbusBookFactoryProxy;
+typedef struct _EGdbusBookFactoryProxyClass EGdbusBookFactoryProxyClass;
+typedef struct _EGdbusBookFactoryProxyPrivate EGdbusBookFactoryProxyPrivate;
+
+struct _EGdbusBookFactoryProxy
+{
+ GDBusProxy parent_instance;
+ EGdbusBookFactoryProxyPrivate *priv;
+};
+
+struct _EGdbusBookFactoryProxyClass
+{
+ GDBusProxyClass parent_class;
+};
+
+#define E_TYPE_GDBUS_BOOK_FACTORY_PROXY (e_gdbus_book_factory_proxy_get_type ())
+GType e_gdbus_book_factory_proxy_get_type (void) G_GNUC_CONST;
+
+void e_gdbus_book_factory_proxy_new (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+EGdbusBookFactory * e_gdbus_book_factory_proxy_new_finish (GAsyncResult *result, GError **error);
+EGdbusBookFactory * e_gdbus_book_factory_proxy_new_sync (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_factory_proxy_new_for_bus (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+EGdbusBookFactory * e_gdbus_book_factory_proxy_new_for_bus_finish (GAsyncResult *result, GError **error);
+EGdbusBookFactory * e_gdbus_book_factory_proxy_new_for_bus_sync (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error);
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct _EGdbusBookFactoryStub EGdbusBookFactoryStub;
+typedef struct _EGdbusBookFactoryStubClass EGdbusBookFactoryStubClass;
+typedef struct _EGdbusBookFactoryStubPrivate EGdbusBookFactoryStubPrivate;
+
+struct _EGdbusBookFactoryStub
+{
+ GObject parent_instance;
+ EGdbusBookFactoryStubPrivate *priv;
+};
+
+struct _EGdbusBookFactoryStubClass
+{
+ GObjectClass parent_class;
+};
+
+#define E_TYPE_GDBUS_BOOK_FACTORY_STUB (e_gdbus_book_factory_stub_get_type ())
+GType e_gdbus_book_factory_stub_get_type (void) G_GNUC_CONST;
+
+EGdbusBookFactory *e_gdbus_book_factory_stub_new (void);
+
+guint e_gdbus_book_factory_register_object (EGdbusBookFactory *object, GDBusConnection *connection, const gchar *object_path, GError **error);
+
+void e_gdbus_book_factory_drain_notify (EGdbusBookFactory *object);
+
+const GDBusInterfaceInfo *e_gdbus_book_factory_interface_info (void) G_GNUC_CONST;
+
+struct _EGdbusBookFactoryIface
+{
+ GTypeInterface parent_iface;
+
+ /* Signal handlers for handling D-Bus method calls: */
+ gboolean (*handle_get_book) (EGdbusBookFactory *object, GDBusMethodInvocation *invocation, const gchar *in_source);
+};
+
+/* D-Bus Methods */
+void e_gdbus_book_factory_call_get_book (GDBusProxy *proxy, const gchar *in_source, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_factory_call_get_book_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_path, GError **error);
+gboolean e_gdbus_book_factory_call_get_book_sync (GDBusProxy *proxy, const gchar *in_source, gchar **out_path, GCancellable *cancellable, GError **error);
+
+/* D-Bus Methods Completion Helpers */
+void e_gdbus_book_factory_complete_get_book (EGdbusBookFactory *object, GDBusMethodInvocation *invocation, const gchar *out_path, const GError *error);
+
+G_END_DECLS
+
+#endif /* E_GDBUS_BOOK_FACTORY_H */
diff --git a/addressbook/libegdbus/e-gdbus-book-view.c b/addressbook/libegdbus/e-gdbus-book-view.c
new file mode 100644
index 0000000..d73ae51
--- /dev/null
+++ b/addressbook/libegdbus/e-gdbus-book-view.c
@@ -0,0 +1,690 @@
+/*
+ * e-gdbus-book-view.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#include <stdio.h>
+#include <gio/gio.h>
+
+#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-gdbus-marshallers.h>
+
+#include "e-gdbus-book-view.h"
+
+#define GDBUS_BOOK_VIEW_INTERFACE_NAME "org.gnome.evolution.dataserver.AddressBookView"
+
+typedef EGdbusBookViewIface EGdbusBookViewInterface;
+G_DEFINE_INTERFACE (EGdbusBookView, e_gdbus_book_view, G_TYPE_OBJECT);
+
+enum
+{
+ _0_SIGNAL,
+ __OBJECTS_ADDED_SIGNAL,
+ __OBJECTS_MODIFIED_SIGNAL,
+ __OBJECTS_REMOVED_SIGNAL,
+ __PROGRESS_SIGNAL,
+ __COMPLETE_SIGNAL,
+ __START_METHOD,
+ __STOP_METHOD,
+ __DISPOSE_METHOD,
+ __SET_FIELDS_OF_INTEREST_METHOD,
+ __LAST_SIGNAL
+};
+
+static guint signals[__LAST_SIGNAL] = {0};
+
+/* ------------------------------------------------------------------------- */
+
+/* Various lookup tables */
+
+static GHashTable *_method_name_to_id = NULL;
+static GHashTable *_method_name_to_type = NULL;
+static GHashTable *_signal_name_to_id = NULL;
+static GHashTable *_signal_name_to_type = NULL;
+
+static guint
+lookup_method_id_from_method_name (const gchar *method_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_method_name_to_id, method_name));
+}
+
+static guint
+lookup_method_type_from_method_name (const gchar *method_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_method_name_to_type, method_name));
+}
+
+static guint
+lookup_signal_id_from_signal_name (const gchar *signal_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_signal_name_to_id, signal_name));
+}
+
+static guint
+lookup_signal_type_from_signal_name (const gchar *signal_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_signal_name_to_type, signal_name));
+}
+
+/* ------------------------------------------------------------------------- */
+
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV (GDBUS_BOOK_VIEW_INTERFACE_NAME, objects_added)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV (GDBUS_BOOK_VIEW_INTERFACE_NAME, objects_modified)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV (GDBUS_BOOK_VIEW_INTERFACE_NAME, objects_removed)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_UINT_STRING (GDBUS_BOOK_VIEW_INTERFACE_NAME, progress)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV (GDBUS_BOOK_VIEW_INTERFACE_NAME, complete)
+
+static void
+e_gdbus_book_view_default_init (EGdbusBookViewIface *iface)
+{
+ /* Build lookup structures */
+ _method_name_to_id = g_hash_table_new (g_str_hash, g_str_equal);
+ _method_name_to_type = g_hash_table_new (g_str_hash, g_str_equal);
+ _signal_name_to_id = g_hash_table_new (g_str_hash, g_str_equal);
+ _signal_name_to_type = g_hash_table_new (g_str_hash, g_str_equal);
+
+
+ /* GObject signals definitions for D-Bus signals: */
+ E_INIT_GDBUS_SIGNAL_STRV (EGdbusBookViewIface, "ObjectsAdded", objects_added, __OBJECTS_ADDED_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_STRV (EGdbusBookViewIface, "ObjectsModified",objects_modified, __OBJECTS_MODIFIED_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_STRV (EGdbusBookViewIface, "ObjectsRemoved", objects_removed, __OBJECTS_REMOVED_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_UINT_STRING (EGdbusBookViewIface, "Progress", progress, __PROGRESS_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_STRV (EGdbusBookViewIface, "Complete", complete, __COMPLETE_SIGNAL)
+
+ /* GObject signals definitions for D-Bus methods: */
+ E_INIT_GDBUS_METHOD_VOID (EGdbusBookViewIface, "start", start, __START_METHOD)
+ E_INIT_GDBUS_METHOD_VOID (EGdbusBookViewIface, "stop", stop, __STOP_METHOD)
+ E_INIT_GDBUS_METHOD_VOID (EGdbusBookViewIface, "dispose", dispose, __DISPOSE_METHOD)
+ E_INIT_GDBUS_METHOD_STRV (EGdbusBookViewIface, "setFieldsOfInterest", set_fields_of_interest, __SET_FIELDS_OF_INTEREST_METHOD)
+}
+
+void
+e_gdbus_book_view_call_start (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_void ("start", proxy, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_view_call_start_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_book_view_call_start_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_void__void ("start", proxy, cancellable, error);
+}
+
+void
+e_gdbus_book_view_call_stop (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_void ("stop", proxy, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_view_call_stop_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_book_view_call_stop_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_void__void ("stop", proxy, cancellable, error);
+}
+
+void
+e_gdbus_book_view_call_dispose (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_void ("dispose", proxy, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_view_call_dispose_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_book_view_call_dispose_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_void__void ("dispose", proxy, cancellable, error);
+}
+
+void
+e_gdbus_book_view_call_set_fields_of_interest (GDBusProxy *proxy, const gchar * const *in_only_fields, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_strv ("setFieldsOfInterest", proxy, in_only_fields, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_view_call_set_fields_of_interest_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_book_view_call_set_fields_of_interest_sync (GDBusProxy *proxy, const gchar * const *in_only_fields, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_strv__void ("setFieldsOfInterest", proxy, in_only_fields, cancellable, error);
+}
+
+void
+e_gdbus_book_view_emit_objects_added (EGdbusBookView *object, const gchar * const *arg_objects)
+{
+ g_signal_emit (object, signals[__OBJECTS_ADDED_SIGNAL], 0, arg_objects);
+}
+
+void
+e_gdbus_book_view_emit_objects_modified (EGdbusBookView *object, const gchar * const *arg_objects)
+{
+ g_signal_emit (object, signals[__OBJECTS_MODIFIED_SIGNAL], 0, arg_objects);
+}
+
+void
+e_gdbus_book_view_emit_objects_removed (EGdbusBookView *object, const gchar * const *arg_uids)
+{
+ g_signal_emit (object, signals[__OBJECTS_REMOVED_SIGNAL], 0, arg_uids);
+}
+
+void
+e_gdbus_book_view_emit_progress (EGdbusBookView *object, guint arg_percent, const gchar *arg_message)
+{
+ g_signal_emit (object, signals[__PROGRESS_SIGNAL], 0, arg_percent, arg_message);
+}
+
+void
+e_gdbus_book_view_emit_complete (EGdbusBookView *object, const gchar * const *arg_error)
+{
+ g_signal_emit (object, signals[__COMPLETE_SIGNAL], 0, arg_error);
+}
+
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (book_view, ObjectsAdded, objects, "as")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (book_view, ObjectsModified, objects, "as")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (book_view, ObjectsRemoved, uids, "as")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_2 (book_view, Progress, percent, "u", message, "s")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (book_view, Complete, error, "as")
+
+E_DECLARE_GDBUS_SYNC_METHOD_0 (book_view, start)
+E_DECLARE_GDBUS_SYNC_METHOD_0 (book_view, stop)
+E_DECLARE_GDBUS_SYNC_METHOD_0 (book_view, dispose)
+E_DECLARE_GDBUS_SYNC_METHOD_1 (book_view, setFieldsOfInterest, fields_of_interest, "as")
+
+static const GDBusMethodInfo * const e_gdbus_book_view_method_info_pointers[] =
+{
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book_view, start),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book_view, stop),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book_view, dispose),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book_view, setFieldsOfInterest),
+ NULL
+};
+
+static const GDBusSignalInfo * const e_gdbus_book_view_signal_info_pointers[] =
+{
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book_view, ObjectsAdded),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book_view, ObjectsModified),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book_view, ObjectsRemoved),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book_view, Progress),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book_view, Complete),
+ NULL
+};
+
+static const GDBusInterfaceInfo _e_gdbus_book_view_interface_info =
+{
+ -1,
+ (gchar *) GDBUS_BOOK_VIEW_INTERFACE_NAME,
+ (GDBusMethodInfo **) &e_gdbus_book_view_method_info_pointers,
+ (GDBusSignalInfo **) &e_gdbus_book_view_signal_info_pointers,
+ (GDBusPropertyInfo **) NULL
+};
+
+static void
+handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ guint method_id, method_type;
+
+ method_id = lookup_method_id_from_method_name (method_name);
+ method_type = lookup_method_type_from_method_name (method_name);
+
+ g_return_if_fail (method_id != 0);
+ g_return_if_fail (method_type != 0);
+
+ e_gdbus_stub_handle_method_call (user_data, invocation, parameters, method_name, signals[method_id], method_type);
+}
+
+static GVariant *
+get_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data)
+{
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This implementation does not support property `%s'", property_name);
+ return NULL;
+}
+
+static gboolean
+set_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GVariant *value, GError **error, gpointer user_data)
+{
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This implementation does not support property `%s'", property_name);
+ return FALSE;
+}
+
+static const GDBusInterfaceVTable e_gdbus_book_view_interface_vtable =
+{
+ handle_method_call,
+ get_property,
+ set_property
+};
+
+static gboolean
+emit_notifications_in_idle (gpointer user_data)
+{
+ GObject *object = G_OBJECT (user_data);
+ GDBusConnection *connection;
+ const gchar *path;
+ GHashTable *notification_queue;
+ GHashTableIter iter;
+ const gchar *property_name;
+ GVariant *value;
+ GVariantBuilder *builder;
+ GVariantBuilder *invalidated_builder;
+ GHashTable *pvc;
+ gboolean has_changes;
+
+ notification_queue = g_object_get_data (object, "gdbus-codegen-notification-queue");
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ pvc = g_object_get_data (object, "gdbus-codegen-pvc");
+ g_assert (notification_queue != NULL && path != NULL && connection != NULL && pvc != NULL);
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
+ invalidated_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ g_hash_table_iter_init (&iter, notification_queue);
+ has_changes = FALSE;
+ while (g_hash_table_iter_next (&iter, (gpointer) &property_name, (gpointer) &value)) {
+ GVariant *cached_value;
+ cached_value = g_hash_table_lookup (pvc, property_name);
+ if (cached_value == NULL || !g_variant_equal (cached_value, value)) {
+ g_hash_table_insert (pvc, (gpointer) property_name, (gpointer) g_variant_ref (value));
+ g_variant_builder_add (builder, "{sv}", property_name, value);
+ has_changes = TRUE;
+ }
+ }
+
+ if (has_changes) {
+ g_dbus_connection_emit_signal (connection,
+ NULL,
+ path,
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ g_variant_new ("(sa{sv}as)",
+ GDBUS_BOOK_VIEW_INTERFACE_NAME,
+ builder,
+ invalidated_builder),
+ NULL);
+ } else {
+ g_variant_builder_unref (builder);
+ g_variant_builder_unref (invalidated_builder);
+ }
+
+ g_hash_table_remove_all (notification_queue);
+ g_object_set_data (object, "gdbus-codegen-notification-idle-id", GUINT_TO_POINTER (0));
+ return FALSE;
+}
+
+/**
+ * e_gdbus_book_view_drain_notify:
+ * @object: A #EGdbusBookView that is exported.
+ *
+ * If @object has queued notifications, empty the queue forcing
+ * the <literal>PropertiesChanged</literal> signal to be emitted.
+ * See <xref linkend="EGdbusBookView.description"/> for more background information.
+ */
+void
+e_gdbus_book_view_drain_notify (EGdbusBookView *object)
+{
+ gint idle_id;
+ idle_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (object), "gdbus-codegen-notification-idle-id"));
+ if (idle_id > 0) {
+ emit_notifications_in_idle (object);
+ g_source_remove (idle_id);
+ }
+}
+
+static void
+on_object_unregistered (GObject *object)
+{
+ gint idle_id;
+ idle_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (object), "gdbus-codegen-notification-idle-id"));
+ if (idle_id > 0) {
+ g_source_remove (idle_id);
+ }
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-path", NULL);
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-connection", NULL);
+}
+
+/**
+ * e_gdbus_book_view_register_object:
+ * @object: An instance of a #GObject<!-- -->-derived type implementing the #EGdbusBookView interface.
+ * @connection: A #GDBusConnection.
+ * @object_path: The object to register the object at.
+ * @error: Return location for error or %NULL.
+ *
+ * Registers @object at @object_path on @connection.
+ *
+ * See <xref linkend="EGdbusBookView.description"/>
+ * for how properties, methods and signals are handled.
+ *
+ * Returns: 0 if @error is set, otherwise a registration id (never 0) that can be used with g_dbus_connection_unregister_object().
+ */
+guint
+e_gdbus_book_view_register_object (EGdbusBookView *object, GDBusConnection *connection, const gchar *object_path, GError **error)
+{
+ GHashTable *pvc;
+
+ pvc = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_variant_unref);
+
+ g_object_set_data_full (G_OBJECT (object), "gdbus-codegen-path", (gpointer) g_strdup (object_path), g_free);
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-connection", (gpointer) connection);
+ g_object_set_data_full (G_OBJECT (object), "gdbus-codegen-pvc", (gpointer) pvc, (GDestroyNotify) g_hash_table_unref);
+ return g_dbus_connection_register_object (connection,
+ object_path,
+ (GDBusInterfaceInfo *) &_e_gdbus_book_view_interface_info,
+ &e_gdbus_book_view_interface_vtable,
+ object,
+ (GDestroyNotify) on_object_unregistered,
+ error);
+}
+
+/**
+ * e_gdbus_book_view_interface_info:
+ *
+ * Gets interface description for the <literal>org.gnome.evolution.dataserver.AddressBookView</literal> D-Bus interface.
+ *
+ * Returns: A #GDBusInterfaceInfo. Do not free, the object is statically allocated.
+ */
+const GDBusInterfaceInfo *
+e_gdbus_book_view_interface_info (void)
+{
+ return &_e_gdbus_book_view_interface_info;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void proxy_iface_init (EGdbusBookViewIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EGdbusBookViewProxy, e_gdbus_book_view_proxy, G_TYPE_DBUS_PROXY,
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_BOOK_VIEW, proxy_iface_init));
+
+static void
+e_gdbus_book_view_proxy_init (EGdbusBookViewProxy *proxy)
+{
+ g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), (GDBusInterfaceInfo *) &_e_gdbus_book_view_interface_info);
+}
+
+static void
+g_signal (GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters)
+{
+ guint signal_id, signal_type;
+
+ signal_id = lookup_signal_id_from_signal_name (signal_name);
+ signal_type = lookup_signal_type_from_signal_name (signal_name);
+
+ g_return_if_fail (signal_id != 0);
+ g_return_if_fail (signal_type != 0);
+
+ e_gdbus_proxy_emit_signal (proxy, parameters, signals[signal_id], signal_type);
+}
+
+static void
+e_gdbus_book_view_proxy_class_init (EGdbusBookViewProxyClass *klass)
+{
+ GDBusProxyClass *proxy_class;
+
+ proxy_class = G_DBUS_PROXY_CLASS (klass);
+ proxy_class->g_signal = g_signal;
+}
+
+static void
+proxy_iface_init (EGdbusBookViewIface *iface)
+{
+}
+
+/**
+ * e_gdbus_book_view_proxy_new:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: Callback function to invoke when the proxy is ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_dbus_proxy_new() but returns a #EGdbusBookViewProxy.
+ *
+ * This is a failable asynchronous constructor - when the proxy is ready, callback will be invoked and you can use e_gdbus_book_view_proxy_new_finish() to get the result.
+ */
+void
+e_gdbus_book_view_proxy_new (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ g_async_initable_new_async (E_TYPE_GDBUS_BOOK_VIEW_PROXY,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "g-flags", flags,
+ "g-name", name,
+ "g-connection", connection,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_BOOK_VIEW_INTERFACE_NAME,
+ NULL);
+}
+
+/**
+ * e_gdbus_book_view_proxy_new_finish:
+ * @result: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to e_gdbus_book_view_proxy_new().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes creating a #EGdbusBookViewProxy.
+ *
+ * Returns: A #EGdbusBookViewProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+EGdbusBookView *
+e_gdbus_book_view_proxy_new_finish (GAsyncResult *result, GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (result);
+ g_assert (source_object != NULL);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error);
+ g_object_unref (source_object);
+ if (object != NULL)
+ return E_GDBUS_BOOK_VIEW (object);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_book_view_proxy_new_sync:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_proxy_new_sync() but returns a #EGdbusBookViewProxy.
+ *
+ * This is a synchronous failable constructor. See e_gdbus_book_view_proxy_new() and e_gdbus_book_view_proxy_new_finish() for the asynchronous version.
+ *
+ * Returns: A #EGdbusBookViewProxy or %NULL if error is set. Free with g_object_unref().
+ */
+EGdbusBookView *
+e_gdbus_book_view_proxy_new_sync (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error)
+{
+ GInitable *initable;
+ initable = g_initable_new (E_TYPE_GDBUS_BOOK_VIEW_PROXY,
+ cancellable,
+ error,
+ "g-flags", flags,
+ "g-name", name,
+ "g-connection", connection,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_BOOK_VIEW_INTERFACE_NAME,
+ NULL);
+ if (initable != NULL)
+ return E_GDBUS_BOOK_VIEW (initable);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_book_view_proxy_new_for_bus:
+ * @bus_type: A #GBusType.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: Callback function to invoke when the proxy is ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_dbus_proxy_new_for_bus() but returns a #EGdbusBookViewProxy.
+ *
+ * This is a failable asynchronous constructor - when the proxy is ready, callback will be invoked and you can use e_gdbus_book_view_proxy_new_for_bus_finish() to get the result.
+ */
+void
+e_gdbus_book_view_proxy_new_for_bus (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ g_async_initable_new_async (E_TYPE_GDBUS_BOOK_VIEW_PROXY,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "g-flags", flags,
+ "g-name", name,
+ "g-bus-type", bus_type,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_BOOK_VIEW_INTERFACE_NAME,
+ NULL);
+}
+
+/**
+ * e_gdbus_book_view_proxy_new_for_bus_finish:
+ * @result: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to e_gdbus_book_view_proxy_new_for_bus().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes creating a #EGdbusBookViewProxy.
+ *
+ * Returns: A #EGdbusBookViewProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+EGdbusBookView *
+e_gdbus_book_view_proxy_new_for_bus_finish (GAsyncResult *result, GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (result);
+ g_assert (source_object != NULL);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error);
+ g_object_unref (source_object);
+ if (object != NULL)
+ return E_GDBUS_BOOK_VIEW (object);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_book_view_proxy_new_for_bus_sync:
+ * @bus_type: A #GBusType.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_proxy_new_for_bus_sync() but returns a #EGdbusBookViewProxy.
+ *
+ * This is a synchronous failable constructor. See e_gdbus_book_view_proxy_new_for_bus() and e_gdbus_book_view_proxy_new_for_bus_finish() for the asynchronous version.
+ *
+ * Returns: A #EGdbusBookViewProxy or %NULL if error is set. Free with g_object_unref().
+ */
+EGdbusBookView *
+e_gdbus_book_view_proxy_new_for_bus_sync (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error)
+{
+ GInitable *initable;
+ initable = g_initable_new (E_TYPE_GDBUS_BOOK_VIEW_PROXY,
+ cancellable,
+ error,
+ "g-flags", flags,
+ "g-name", name,
+ "g-bus-type", bus_type,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_BOOK_VIEW_INTERFACE_NAME,
+ NULL);
+ if (initable != NULL)
+ return E_GDBUS_BOOK_VIEW (initable);
+ else
+ return NULL;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct _EGdbusBookViewStubPrivate
+{
+ gint foo;
+};
+
+static void stub_iface_init (EGdbusBookViewIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EGdbusBookViewStub, e_gdbus_book_view_stub, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_BOOK_VIEW, stub_iface_init));
+
+static void
+e_gdbus_book_view_stub_init (EGdbusBookViewStub *stub)
+{
+ stub->priv = G_TYPE_INSTANCE_GET_PRIVATE (stub, E_TYPE_GDBUS_BOOK_VIEW_STUB, EGdbusBookViewStubPrivate);
+}
+
+static void
+e_gdbus_book_view_stub_class_init (EGdbusBookViewStubClass *klass)
+{
+ g_type_class_add_private (klass, sizeof (EGdbusBookViewStubPrivate));
+}
+
+static void
+stub_iface_init (EGdbusBookViewIface *iface)
+{
+}
+
+/**
+ * e_gdbus_book_view_stub_new:
+ *
+ * Creates a new stub object that can be exported via e_gdbus_book_view_register_object().
+ *
+ * Returns: A #EGdbusBookViewStub instance. Free with g_object_unref().
+ */
+EGdbusBookView *
+e_gdbus_book_view_stub_new (void)
+{
+ return E_GDBUS_BOOK_VIEW (g_object_new (E_TYPE_GDBUS_BOOK_VIEW_STUB, NULL));
+}
diff --git a/addressbook/libegdbus/e-gdbus-book-view.h b/addressbook/libegdbus/e-gdbus-book-view.h
new file mode 100644
index 0000000..3f750da
--- /dev/null
+++ b/addressbook/libegdbus/e-gdbus-book-view.h
@@ -0,0 +1,155 @@
+/*
+ * e-gdbus-book-view.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_GDBUS_BOOK_VIEW_H
+#define E_GDBUS_BOOK_VIEW_H
+
+#include <gio/gio.h>
+
+#include <libedataserver/e-gdbus-templates.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_GDBUS_BOOK_VIEW (e_gdbus_book_view_get_type ())
+#define E_GDBUS_BOOK_VIEW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_GDBUS_BOOK_VIEW, EGdbusBookView))
+#define E_IS_GDBUS_BOOK_VIEW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_GDBUS_BOOK_VIEW))
+#define E_GDBUS_BOOK_VIEW_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE((o), E_TYPE_GDBUS_BOOK_VIEW, EGdbusBookViewIface))
+
+/**
+ * EGdbusBookView:
+ *
+ * Opaque type representing a proxy or an exported object.
+ */
+typedef struct _EGdbusBookView EGdbusBookView; /* Dummy typedef */
+typedef struct _EGdbusBookViewIface EGdbusBookViewIface;
+
+GType e_gdbus_book_view_get_type (void) G_GNUC_CONST;
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct _EGdbusBookViewProxy EGdbusBookViewProxy;
+typedef struct _EGdbusBookViewProxyClass EGdbusBookViewProxyClass;
+typedef struct _EGdbusBookViewProxyPrivate EGdbusBookViewProxyPrivate;
+
+struct _EGdbusBookViewProxy
+{
+ GDBusProxy parent_instance;
+ EGdbusBookViewProxyPrivate *priv;
+};
+
+struct _EGdbusBookViewProxyClass
+{
+ GDBusProxyClass parent_class;
+};
+
+#define E_TYPE_GDBUS_BOOK_VIEW_PROXY (e_gdbus_book_view_proxy_get_type ())
+GType e_gdbus_book_view_proxy_get_type (void) G_GNUC_CONST;
+
+void e_gdbus_book_view_proxy_new (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+EGdbusBookView *e_gdbus_book_view_proxy_new_finish (GAsyncResult *result, GError **error);
+EGdbusBookView *e_gdbus_book_view_proxy_new_sync (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_view_proxy_new_for_bus (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+EGdbusBookView *e_gdbus_book_view_proxy_new_for_bus_finish (GAsyncResult *result, GError **error);
+EGdbusBookView *e_gdbus_book_view_proxy_new_for_bus_sync (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error);
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct _EGdbusBookViewStub EGdbusBookViewStub;
+typedef struct _EGdbusBookViewStubClass EGdbusBookViewStubClass;
+typedef struct _EGdbusBookViewStubPrivate EGdbusBookViewStubPrivate;
+
+struct _EGdbusBookViewStub
+{
+ GObject parent_instance;
+ EGdbusBookViewStubPrivate *priv;
+};
+
+struct _EGdbusBookViewStubClass
+{
+ GObjectClass parent_class;
+};
+
+#define E_TYPE_GDBUS_BOOK_VIEW_STUB (e_gdbus_book_view_stub_get_type ())
+GType e_gdbus_book_view_stub_get_type (void) G_GNUC_CONST;
+
+EGdbusBookView *e_gdbus_book_view_stub_new (void);
+
+guint e_gdbus_book_view_register_object (EGdbusBookView *object, GDBusConnection *connection, const gchar *object_path, GError **error);
+
+void e_gdbus_book_view_drain_notify (EGdbusBookView *object);
+
+const GDBusInterfaceInfo *e_gdbus_book_view_interface_info (void) G_GNUC_CONST;
+
+struct _EGdbusBookViewIface
+{
+ GTypeInterface parent_iface;
+
+ /* Signal handlers for receiving D-Bus signals: */
+ void (*objects_added) (EGdbusBookView *object, const gchar * const *arg_objects);
+ void (*objects_modified) (EGdbusBookView *object, const gchar * const *arg_objects);
+ void (*objects_removed) (EGdbusBookView *object, const gchar * const *arg_uids);
+
+ void (*progress) (EGdbusBookView *object, guint arg_percent, const gchar *arg_message);
+ void (*complete) (EGdbusBookView *object, const gchar * const *arg_error);
+
+ /* Signal handlers for handling D-Bus method calls: */
+ gboolean (*handle_start) (EGdbusBookView *object, GDBusMethodInvocation *invocation);
+ gboolean (*handle_stop) (EGdbusBookView *object, GDBusMethodInvocation *invocation);
+ gboolean (*handle_dispose) (EGdbusBookView *object, GDBusMethodInvocation *invocation);
+ gboolean (*handle_set_fields_of_interest)(EGdbusBookView *object, GDBusMethodInvocation *invocation, const gchar * const *in_only_fields);
+};
+
+/* D-Bus Methods */
+void e_gdbus_book_view_call_start (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_view_call_start_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_view_call_start_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_view_call_stop (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_view_call_stop_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_view_call_stop_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_view_call_dispose (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_view_call_dispose_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_view_call_dispose_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_view_call_set_fields_of_interest (GDBusProxy *proxy, const gchar * const *in_only_fileds, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_view_call_set_fields_of_interest_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_view_call_set_fields_of_interest_sync (GDBusProxy *proxy, const gchar * const *in_only_fileds, GCancellable *cancellable, GError **error);
+
+/* D-Bus Methods Completion Helpers */
+#define e_gdbus_book_view_complete_start e_gdbus_complete_sync_method_void
+#define e_gdbus_book_view_complete_stop e_gdbus_complete_sync_method_void
+#define e_gdbus_book_view_complete_dispose e_gdbus_complete_sync_method_void
+#define e_gdbus_book_view_complete_set_fields_of_interest e_gdbus_complete_sync_method_void
+
+
+/* D-Bus Signal Emission Helpers */
+void e_gdbus_book_view_emit_objects_added (EGdbusBookView *object, const gchar * const *arg_objects);
+void e_gdbus_book_view_emit_objects_modified (EGdbusBookView *object, const gchar * const *arg_objects);
+void e_gdbus_book_view_emit_objects_removed (EGdbusBookView *object, const gchar * const *arg_uids);
+
+void e_gdbus_book_view_emit_progress (EGdbusBookView *object, guint arg_percent, const gchar *arg_message);
+void e_gdbus_book_view_emit_complete (EGdbusBookView *object, const gchar * const *arg_error);
+
+G_END_DECLS
+
+#endif /* E_GDBUS_BOOK_VIEW_H */
diff --git a/addressbook/libegdbus/e-gdbus-book.c b/addressbook/libegdbus/e-gdbus-book.c
new file mode 100644
index 0000000..c6d2df5
--- /dev/null
+++ b/addressbook/libegdbus/e-gdbus-book.c
@@ -0,0 +1,1126 @@
+/*
+ * e-gdbus-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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#include <stdio.h>
+#include <gio/gio.h>
+
+#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-gdbus-marshallers.h>
+
+#include "e-gdbus-book.h"
+
+#define GDBUS_BOOK_INTERFACE_NAME "org.gnome.evolution.dataserver.AddressBook"
+
+typedef EGdbusBookIface EGdbusBookInterface;
+G_DEFINE_INTERFACE (EGdbusBook, e_gdbus_book, G_TYPE_OBJECT);
+
+enum
+{
+ _0_SIGNAL,
+ __BACKEND_ERROR_SIGNAL,
+ __READONLY_SIGNAL,
+ __ONLINE_SIGNAL,
+ __AUTH_REQUIRED_SIGNAL,
+ __OPENED_SIGNAL,
+ __OPEN_METHOD,
+ __OPEN_DONE_SIGNAL,
+ __REMOVE_METHOD,
+ __REMOVE_DONE_SIGNAL,
+ __REFRESH_METHOD,
+ __REFRESH_DONE_SIGNAL,
+ __GET_CONTACT_METHOD,
+ __GET_CONTACT_DONE_SIGNAL,
+ __GET_CONTACT_LIST_METHOD,
+ __GET_CONTACT_LIST_DONE_SIGNAL,
+ __ADD_CONTACT_METHOD,
+ __ADD_CONTACT_DONE_SIGNAL,
+ __REMOVE_CONTACTS_METHOD,
+ __REMOVE_CONTACTS_DONE_SIGNAL,
+ __MODIFY_CONTACT_METHOD,
+ __MODIFY_CONTACT_DONE_SIGNAL,
+ __GET_BACKEND_PROPERTY_METHOD,
+ __GET_BACKEND_PROPERTY_DONE_SIGNAL,
+ __SET_BACKEND_PROPERTY_METHOD,
+ __SET_BACKEND_PROPERTY_DONE_SIGNAL,
+ __GET_VIEW_METHOD,
+ __GET_VIEW_DONE_SIGNAL,
+ __AUTHENTICATE_USER_METHOD,
+ __CANCEL_OPERATION_METHOD,
+ __CANCEL_ALL_METHOD,
+ __CLOSE_METHOD,
+ __LAST_SIGNAL
+};
+
+static guint signals[__LAST_SIGNAL] = {0};
+
+struct _EGdbusBookProxyPrivate
+{
+ GHashTable *pending_ops;
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Various lookup tables */
+
+static GHashTable *_method_name_to_id = NULL;
+static GHashTable *_method_name_to_type = NULL;
+static GHashTable *_signal_name_to_id = NULL;
+static GHashTable *_signal_name_to_type = NULL;
+
+static guint
+lookup_method_id_from_method_name (const gchar *method_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_method_name_to_id, method_name));
+}
+
+static guint
+lookup_method_type_from_method_name (const gchar *method_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_method_name_to_type, method_name));
+}
+
+static guint
+lookup_signal_id_from_signal_name (const gchar *signal_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_signal_name_to_id, signal_name));
+}
+
+static guint
+lookup_signal_type_from_signal_name (const gchar *signal_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_signal_name_to_type, signal_name));
+}
+
+/* ------------------------------------------------------------------------- */
+
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRING (GDBUS_BOOK_INTERFACE_NAME, backend_error)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_BOOLEAN (GDBUS_BOOK_INTERFACE_NAME, readonly)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_BOOLEAN (GDBUS_BOOK_INTERFACE_NAME, online)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV (GDBUS_BOOK_INTERFACE_NAME, auth_required)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV (GDBUS_BOOK_INTERFACE_NAME, opened)
+
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_BOOK_INTERFACE_NAME, open)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_BOOK_INTERFACE_NAME, remove)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_BOOK_INTERFACE_NAME, refresh)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING (GDBUS_BOOK_INTERFACE_NAME, get_contact)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRV (GDBUS_BOOK_INTERFACE_NAME, get_contact_list)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING (GDBUS_BOOK_INTERFACE_NAME, add_contact)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_BOOK_INTERFACE_NAME, remove_contacts)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_BOOK_INTERFACE_NAME, modify_contact)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING (GDBUS_BOOK_INTERFACE_NAME, get_backend_property)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_BOOK_INTERFACE_NAME, set_backend_property)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING (GDBUS_BOOK_INTERFACE_NAME, get_view)
+
+static void
+e_gdbus_book_default_init (EGdbusBookIface *iface)
+{
+ /* Build lookup structures */
+ _method_name_to_id = g_hash_table_new (g_str_hash, g_str_equal);
+ _method_name_to_type = g_hash_table_new (g_str_hash, g_str_equal);
+ _signal_name_to_id = g_hash_table_new (g_str_hash, g_str_equal);
+ _signal_name_to_type = g_hash_table_new (g_str_hash, g_str_equal);
+
+ /* GObject signals definitions for D-Bus signals: */
+ E_INIT_GDBUS_SIGNAL_STRING (EGdbusBookIface, "backend_error", backend_error, __BACKEND_ERROR_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_BOOLEAN (EGdbusBookIface, "readonly", readonly, __READONLY_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_BOOLEAN (EGdbusBookIface, "online", online, __ONLINE_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_STRV (EGdbusBookIface, "auth_required", auth_required, __AUTH_REQUIRED_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_STRV (EGdbusBookIface, "opened", opened, __OPENED_SIGNAL)
+
+ /* GObject signals definitions for D-Bus methods: */
+ E_INIT_GDBUS_METHOD_ASYNC_BOOLEAN__VOID (EGdbusBookIface, "open", open, __OPEN_METHOD, __OPEN_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_VOID__VOID (EGdbusBookIface, "remove", remove, __REMOVE_METHOD, __REMOVE_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_VOID__VOID (EGdbusBookIface, "refresh", refresh, __REFRESH_METHOD, __REFRESH_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusBookIface, "getContact", get_contact, __GET_CONTACT_METHOD, __GET_CONTACT_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__STRV (EGdbusBookIface, "getContactList", get_contact_list, __GET_CONTACT_LIST_METHOD, __GET_CONTACT_LIST_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusBookIface, "addContact", add_contact, __ADD_CONTACT_METHOD, __ADD_CONTACT_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRV__VOID (EGdbusBookIface, "removeContacts", remove_contacts, __REMOVE_CONTACTS_METHOD, __REMOVE_CONTACTS_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__VOID (EGdbusBookIface, "modifyContact", modify_contact, __MODIFY_CONTACT_METHOD, __MODIFY_CONTACT_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusBookIface, "getBackendProperty", get_backend_property, __GET_BACKEND_PROPERTY_METHOD, __GET_BACKEND_PROPERTY_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRV__VOID (EGdbusBookIface, "setBackendProperty", set_backend_property, __SET_BACKEND_PROPERTY_METHOD, __SET_BACKEND_PROPERTY_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusBookIface, "getView", get_view, __GET_VIEW_METHOD, __GET_VIEW_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_STRV (EGdbusBookIface, "authenticateUser", authenticate_user, __AUTHENTICATE_USER_METHOD)
+ E_INIT_GDBUS_METHOD_UINT (EGdbusBookIface, "cancelOperation", cancel_operation, __CANCEL_OPERATION_METHOD)
+ E_INIT_GDBUS_METHOD_VOID (EGdbusBookIface, "cancelAll", cancel_all, __CANCEL_ALL_METHOD)
+ E_INIT_GDBUS_METHOD_VOID (EGdbusBookIface, "close", close, __CLOSE_METHOD)
+}
+
+void
+e_gdbus_book_call_open (GDBusProxy *proxy, gboolean in_only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_boolean ("open", e_gdbus_book_call_open, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_only_if_exists, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_open_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_book_call_open);
+}
+
+gboolean
+e_gdbus_book_call_open_sync (GDBusProxy *proxy, gboolean in_only_if_exists, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_boolean__void (proxy, in_only_if_exists, cancellable, error,
+ e_gdbus_book_call_open,
+ e_gdbus_book_call_open_finish);
+}
+
+void
+e_gdbus_book_call_remove (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_void ("remove", e_gdbus_book_call_remove, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_remove_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_book_call_remove);
+}
+
+gboolean
+e_gdbus_book_call_remove_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_void__void (proxy, cancellable, error,
+ e_gdbus_book_call_remove,
+ e_gdbus_book_call_remove_finish);
+}
+
+void
+e_gdbus_book_call_refresh (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_void ("refresh", e_gdbus_book_call_refresh, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_refresh_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_book_call_refresh);
+}
+
+gboolean
+e_gdbus_book_call_refresh_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_void__void (proxy, cancellable, error,
+ e_gdbus_book_call_refresh,
+ e_gdbus_book_call_refresh_finish);
+}
+
+void
+e_gdbus_book_call_get_contact (GDBusProxy *proxy, const gchar *in_uid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("getContact", e_gdbus_book_call_get_contact, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_uid, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_get_contact_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_vcard, GError **error)
+{
+ return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_vcard, error, e_gdbus_book_call_get_contact);
+}
+
+gboolean
+e_gdbus_book_call_get_contact_sync (GDBusProxy *proxy, const gchar *in_uid, gchar **out_vcard, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__string (proxy, in_uid, out_vcard, cancellable, error,
+ e_gdbus_book_call_get_contact,
+ e_gdbus_book_call_get_contact_finish);
+}
+
+void
+e_gdbus_book_call_get_contact_list (GDBusProxy *proxy, const gchar *in_query, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("getContactList", e_gdbus_book_call_get_contact_list, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_query, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_get_contact_list_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_vcards, GError **error)
+{
+ return e_gdbus_proxy_finish_call_strv (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_vcards, error, e_gdbus_book_call_get_contact_list);
+}
+
+gboolean
+e_gdbus_book_call_get_contact_list_sync (GDBusProxy *proxy, const gchar *in_query, gchar ***out_vcards, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__strv (proxy, in_query, out_vcards, cancellable, error,
+ e_gdbus_book_call_get_contact_list,
+ e_gdbus_book_call_get_contact_list_finish);
+}
+
+void
+e_gdbus_book_call_add_contact (GDBusProxy *proxy, const gchar *in_vcard, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("addContact", e_gdbus_book_call_add_contact, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_vcard, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_add_contact_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_uid, GError **error)
+{
+ return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_uid, error, e_gdbus_book_call_add_contact);
+}
+
+gboolean
+e_gdbus_book_call_add_contact_sync (GDBusProxy *proxy, const gchar *in_vcard, gchar **out_uid, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__string (proxy, in_vcard, out_uid, cancellable, error,
+ e_gdbus_book_call_add_contact,
+ e_gdbus_book_call_add_contact_finish);
+}
+
+void
+e_gdbus_book_call_remove_contacts (GDBusProxy *proxy, const gchar * const *in_list, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_strv ("removeContacts", e_gdbus_book_call_remove_contacts, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_list, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_remove_contacts_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_book_call_remove_contacts);
+}
+
+gboolean
+e_gdbus_book_call_remove_contacts_sync (GDBusProxy *proxy, const gchar * const *in_list, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_strv__void (proxy, in_list, cancellable, error,
+ e_gdbus_book_call_remove_contacts,
+ e_gdbus_book_call_remove_contacts_finish);
+}
+
+void
+e_gdbus_book_call_modify_contact (GDBusProxy *proxy, const gchar *in_vcard, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("modifyContact", e_gdbus_book_call_modify_contact, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_vcard, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_modify_contact_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_book_call_modify_contact);
+}
+
+gboolean
+e_gdbus_book_call_modify_contact_sync (GDBusProxy *proxy, const gchar *in_vcard, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__void (proxy, in_vcard, cancellable, error,
+ e_gdbus_book_call_modify_contact,
+ e_gdbus_book_call_modify_contact_finish);
+}
+
+void
+e_gdbus_book_call_get_backend_property (GDBusProxy *proxy, const gchar *in_prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("getBackendProperty", e_gdbus_book_call_get_backend_property, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_prop_name, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_get_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_prop_value, GError **error)
+{
+ return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_prop_value, error, e_gdbus_book_call_get_backend_property);
+}
+
+gboolean
+e_gdbus_book_call_get_backend_property_sync (GDBusProxy *proxy, const gchar *in_prop_name, gchar **out_prop_value, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__string (proxy, in_prop_name, out_prop_value, cancellable, error,
+ e_gdbus_book_call_get_backend_property,
+ e_gdbus_book_call_get_backend_property_finish);
+}
+
+/* free returned pointer with g_strfreev() */
+gchar **
+e_gdbus_book_encode_set_backend_property (const gchar *in_prop_name, const gchar *in_prop_value)
+{
+ gchar **strv;
+
+ strv = g_new0 (gchar *, 3);
+ strv[0] = e_util_utf8_make_valid (in_prop_name ? in_prop_name : "");
+ strv[1] = e_util_utf8_make_valid (in_prop_value ? in_prop_value : "");
+ strv[2] = NULL;
+
+ return strv;
+}
+
+/* free out_prop_name and out_prop_value with g_free() */
+gboolean
+e_gdbus_book_decode_set_backend_property (const gchar * const *in_strv, gchar **out_prop_name, gchar **out_prop_value)
+{
+ g_return_val_if_fail (in_strv != NULL, FALSE);
+ g_return_val_if_fail (in_strv[0] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[1] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[2] == NULL, FALSE);
+ g_return_val_if_fail (out_prop_name != NULL, FALSE);
+ g_return_val_if_fail (out_prop_value != NULL, FALSE);
+
+ *out_prop_name = g_strdup (in_strv[0]);
+ *out_prop_value = g_strdup (in_strv[1]);
+
+ return TRUE;
+}
+
+void
+e_gdbus_book_call_set_backend_property (GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_strv ("setBackendProperty", e_gdbus_book_call_set_backend_property, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_prop_name_value, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_set_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_book_call_set_backend_property);
+}
+
+gboolean
+e_gdbus_book_call_set_backend_property_sync (GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_strv__void (proxy, in_prop_name_value, cancellable, error,
+ e_gdbus_book_call_set_backend_property,
+ e_gdbus_book_call_set_backend_property_finish);
+}
+
+void
+e_gdbus_book_call_get_view (GDBusProxy *proxy, const gchar *in_query, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("getView", e_gdbus_book_call_get_view, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_query, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_get_view_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_view_path, GError **error)
+{
+ return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_view_path, error, e_gdbus_book_call_get_view);
+}
+
+gboolean
+e_gdbus_book_call_get_view_sync (GDBusProxy *proxy, const gchar *in_query, gchar **out_view_path, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__string (proxy, in_query, out_view_path, cancellable, error,
+ e_gdbus_book_call_get_view,
+ e_gdbus_book_call_get_view_finish);
+}
+
+void
+e_gdbus_book_call_authenticate_user (GDBusProxy *proxy, const gchar * const *in_credentials, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_strv ("authenticateUser", proxy, in_credentials, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_authenticate_user_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_book_call_authenticate_user_sync (GDBusProxy *proxy, const gchar * const *in_credentials, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_strv__void ("authenticateUser", proxy, in_credentials, cancellable, error);
+}
+
+void
+e_gdbus_book_call_cancel_operation (GDBusProxy *proxy, guint in_opid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_uint ("cancelOperation", proxy, in_opid, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_cancel_operation_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_book_call_cancel_operation_sync (GDBusProxy *proxy, guint in_opid, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_uint__void ("cancelOperation", proxy, in_opid, cancellable, error);
+}
+
+void
+e_gdbus_book_call_cancel_all (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_void ("cancelAll", proxy, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_cancel_all_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_book_call_cancel_all_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_void__void ("cancelAll", proxy, cancellable, error);
+}
+
+void
+e_gdbus_book_call_close (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_void ("close", proxy, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_book_call_close_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_book_call_close_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_void__void ("close", proxy, cancellable, error);
+}
+
+#define DECLARE_EMIT_DONE_SIGNAL_0(_mname, _sig_id) \
+void \
+e_gdbus_book_emit_ ## _mname ## _done (EGdbusBook *object, guint arg_opid, const GError *arg_error) \
+{ \
+ g_signal_emit (object, signals[_sig_id], 0, arg_opid, arg_error); \
+}
+
+#define DECLARE_EMIT_DONE_SIGNAL_1(_mname, _sig_id, _par_type) \
+void \
+e_gdbus_book_emit_ ## _mname ## _done (EGdbusBook *object, guint arg_opid, const GError *arg_error, _par_type out_par) \
+{ \
+ g_signal_emit (object, signals[_sig_id], 0, arg_opid, arg_error, out_par); \
+}
+
+DECLARE_EMIT_DONE_SIGNAL_0 (open, __OPEN_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_0 (remove, __REMOVE_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_0 (refresh, __REFRESH_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_1 (get_contact, __GET_CONTACT_DONE_SIGNAL, const gchar *)
+DECLARE_EMIT_DONE_SIGNAL_1 (get_contact_list, __GET_CONTACT_LIST_DONE_SIGNAL, const gchar * const *)
+DECLARE_EMIT_DONE_SIGNAL_1 (add_contact, __ADD_CONTACT_DONE_SIGNAL, const gchar *)
+DECLARE_EMIT_DONE_SIGNAL_0 (remove_contacts, __REMOVE_CONTACTS_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_0 (modify_contact, __MODIFY_CONTACT_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_1 (get_backend_property, __GET_BACKEND_PROPERTY_DONE_SIGNAL, const gchar *)
+DECLARE_EMIT_DONE_SIGNAL_0 (set_backend_property, __SET_BACKEND_PROPERTY_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_1 (get_view, __GET_VIEW_DONE_SIGNAL, const gchar *)
+
+void
+e_gdbus_book_emit_backend_error (EGdbusBook *object, const gchar *arg_message)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (arg_message != NULL);
+
+ g_signal_emit (object, signals[__BACKEND_ERROR_SIGNAL], 0, arg_message);
+}
+
+void
+e_gdbus_book_emit_readonly (EGdbusBook *object, gboolean arg_is_readonly)
+{
+ g_signal_emit (object, signals[__READONLY_SIGNAL], 0, arg_is_readonly);
+}
+
+void
+e_gdbus_book_emit_online (EGdbusBook *object, gboolean arg_is_online)
+{
+ g_signal_emit (object, signals[__ONLINE_SIGNAL], 0, arg_is_online);
+}
+
+void
+e_gdbus_book_emit_auth_required (EGdbusBook *object, const gchar * const *arg_credentials)
+{
+ g_signal_emit (object, signals[__AUTH_REQUIRED_SIGNAL], 0, arg_credentials);
+}
+
+void
+e_gdbus_book_emit_opened (EGdbusBook *object, const gchar * const *arg_error)
+{
+ g_signal_emit (object, signals[__OPENED_SIGNAL], 0, arg_error);
+}
+
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (book, backend_error, message, "s")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (book, readonly, is_readonly, "b")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (book, online, is_online, "b")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (book, auth_required, credentials, "as")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (book, opened, error, "as")
+
+E_DECLARE_GDBUS_ASYNC_METHOD_1 (book, open, only_if_exists, "b")
+E_DECLARE_GDBUS_ASYNC_METHOD_0 (book, remove)
+E_DECLARE_GDBUS_ASYNC_METHOD_0 (book, refresh)
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (book, getContact, uid, "s", vcard, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (book, getContactList, query, "s", vcards, "as")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (book, addContact, vcard, "s", uid, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_1 (book, removeContacts, list, "as")
+E_DECLARE_GDBUS_ASYNC_METHOD_1 (book, modifyContact, vcard, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (book, getBackendProperty, prop_name, "s", prop_value, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_1 (book, setBackendProperty, prop_name_value, "as")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (book, getView, query, "s", view, "s")
+
+E_DECLARE_GDBUS_SYNC_METHOD_1 (book, authenticateUser, credentials, "as")
+E_DECLARE_GDBUS_SYNC_METHOD_1 (book, cancelOperation, opid, "u")
+E_DECLARE_GDBUS_SYNC_METHOD_0 (book, cancelAll)
+E_DECLARE_GDBUS_SYNC_METHOD_0 (book, close)
+
+static const GDBusMethodInfo * const e_gdbus_book_method_info_pointers[] =
+{
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, open),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, remove),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, refresh),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, getContact),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, getContactList),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, addContact),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, removeContacts),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, modifyContact),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, getBackendProperty),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, setBackendProperty),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, getView),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, authenticateUser),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, cancelOperation),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, cancelAll),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (book, close),
+ NULL
+};
+
+static const GDBusSignalInfo * const e_gdbus_book_signal_info_pointers[] =
+{
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, backend_error),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, readonly),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, online),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, auth_required),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, opened),
+
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, open_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, remove_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, refresh_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, getContact_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, getContactList_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, addContact_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, removeContacts_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, modifyContact_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, getBackendProperty_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, setBackendProperty_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (book, getView_done),
+ NULL
+};
+
+static const GDBusInterfaceInfo _e_gdbus_book_interface_info =
+{
+ -1,
+ (gchar *) GDBUS_BOOK_INTERFACE_NAME,
+ (GDBusMethodInfo **) &e_gdbus_book_method_info_pointers,
+ (GDBusSignalInfo **) &e_gdbus_book_signal_info_pointers,
+ (GDBusPropertyInfo **) NULL
+};
+
+static void
+handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ guint method_id, method_type;
+
+ method_id = lookup_method_id_from_method_name (method_name);
+ method_type = lookup_method_type_from_method_name (method_name);
+
+ g_return_if_fail (method_id != 0);
+ g_return_if_fail (method_type != 0);
+
+ e_gdbus_stub_handle_method_call (user_data, invocation, parameters, method_name, signals[method_id], method_type);
+}
+
+static GVariant *
+get_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data)
+{
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This implementation does not support property `%s'", property_name);
+ return NULL;
+}
+
+static gboolean
+set_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GVariant *value, GError **error, gpointer user_data)
+{
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This implementation does not support property `%s'", property_name);
+ return FALSE;
+}
+
+static const GDBusInterfaceVTable e_gdbus_book_interface_vtable =
+{
+ handle_method_call,
+ get_property,
+ set_property
+};
+
+static gboolean
+emit_notifications_in_idle (gpointer user_data)
+{
+ GObject *object = G_OBJECT (user_data);
+ GDBusConnection *connection;
+ const gchar *path;
+ GHashTable *notification_queue;
+ GHashTableIter iter;
+ const gchar *property_name;
+ GVariant *value;
+ GVariantBuilder *builder;
+ GVariantBuilder *invalidated_builder;
+ GHashTable *pvc;
+ gboolean has_changes;
+
+ notification_queue = g_object_get_data (object, "gdbus-codegen-notification-queue");
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ pvc = g_object_get_data (object, "gdbus-codegen-pvc");
+ g_assert (notification_queue != NULL && path != NULL && connection != NULL && pvc != NULL);
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
+ invalidated_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ g_hash_table_iter_init (&iter, notification_queue);
+ has_changes = FALSE;
+ while (g_hash_table_iter_next (&iter, (gpointer) &property_name, (gpointer) &value)) {
+ GVariant *cached_value;
+ cached_value = g_hash_table_lookup (pvc, property_name);
+ if (cached_value == NULL || !g_variant_equal (cached_value, value)) {
+ g_hash_table_insert (pvc, (gpointer) property_name, (gpointer) g_variant_ref (value));
+ g_variant_builder_add (builder, "{sv}", property_name, value);
+ has_changes = TRUE;
+ }
+ }
+
+ if (has_changes) {
+ g_dbus_connection_emit_signal (connection, NULL, path, "org.freedesktop.DBus.Properties", "PropertiesChanged",
+ g_variant_new ("(sa{sv}as)", GDBUS_BOOK_INTERFACE_NAME, builder, invalidated_builder),
+ NULL);
+ } else {
+ g_variant_builder_unref (builder);
+ g_variant_builder_unref (invalidated_builder);
+ }
+
+ g_hash_table_remove_all (notification_queue);
+ g_object_set_data (object, "gdbus-codegen-notification-idle-id", GUINT_TO_POINTER (0));
+
+ return FALSE;
+}
+
+/**
+ * e_gdbus_book_drain_notify:
+ * @object: A #EGdbusBook that is exported.
+ *
+ * If @object has queued notifications, empty the queue forcing
+ * the <literal>PropertiesChanged</literal> signal to be emitted.
+ * See <xref linkend="EGdbusBook.description"/> for more background information.
+ */
+void
+e_gdbus_book_drain_notify (EGdbusBook *object)
+{
+ gint idle_id;
+ idle_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (object), "gdbus-codegen-notification-idle-id"));
+ if (idle_id > 0) {
+ emit_notifications_in_idle (object);
+ g_source_remove (idle_id);
+ }
+}
+
+static void
+on_object_unregistered (GObject *object)
+{
+ gint idle_id;
+ idle_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (object), "gdbus-codegen-notification-idle-id"));
+ if (idle_id > 0) {
+ g_source_remove (idle_id);
+ }
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-path", NULL);
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-connection", NULL);
+}
+
+/**
+ * e_gdbus_book_register_object:
+ * @object: An instance of a #GObject<!-- -->-derived type implementing the #EGdbusBook interface.
+ * @connection: A #GDBusConnection.
+ * @object_path: The object to register the object at.
+ * @error: Return location for error or %NULL.
+ *
+ * Registers @object at @object_path on @connection.
+ *
+ * See <xref linkend="EGdbusBook.description"/>
+ * for how properties, methods and signals are handled.
+ *
+ * Returns: 0 if @error is set, otherwise a registration id (never 0) that can be used with g_dbus_connection_unregister_object().
+ */
+guint
+e_gdbus_book_register_object (EGdbusBook *object, GDBusConnection *connection, const gchar *object_path, GError **error)
+{
+ GHashTable *pvc;
+
+ pvc = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_variant_unref);
+
+ g_object_set_data_full (G_OBJECT (object), "gdbus-codegen-path", (gpointer) g_strdup (object_path), g_free);
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-connection", (gpointer) connection);
+ g_object_set_data_full (G_OBJECT (object), "gdbus-codegen-pvc", (gpointer) pvc, (GDestroyNotify) g_hash_table_unref);
+
+ return g_dbus_connection_register_object (connection, object_path, (GDBusInterfaceInfo *) &_e_gdbus_book_interface_info,
+ &e_gdbus_book_interface_vtable, object, (GDestroyNotify) on_object_unregistered, error);
+}
+
+/**
+ * e_gdbus_book_interface_info:
+ *
+ * Gets interface description for the <literal>org.gnome.evolution.dataserver.AddressBook</literal> D-Bus interface.
+ *
+ * Returns: A #GDBusInterfaceInfo. Do not free, the object is statically allocated.
+ */
+const GDBusInterfaceInfo *
+e_gdbus_book_interface_info (void)
+{
+ return &_e_gdbus_book_interface_info;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void proxy_iface_init (EGdbusBookIface *iface);
+static void async_op_keeper_iface_init (EGdbusAsyncOpKeeperInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EGdbusBookProxy, e_gdbus_book_proxy, G_TYPE_DBUS_PROXY,
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_BOOK, proxy_iface_init)
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_ASYNC_OP_KEEPER, async_op_keeper_iface_init));
+
+static void
+e_gdbus_book_proxy_init (EGdbusBookProxy *proxy)
+{
+ g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), (GDBusInterfaceInfo *) &_e_gdbus_book_interface_info);
+
+ proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, E_TYPE_GDBUS_BOOK_PROXY, EGdbusBookProxyPrivate);
+ proxy->priv->pending_ops = e_gdbus_async_op_keeper_create_pending_ops (E_GDBUS_ASYNC_OP_KEEPER (proxy));
+
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (open);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (remove);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (refresh);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_contact);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRV (get_contact_list);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (add_contact);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (remove_contacts);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (modify_contact);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_backend_property);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (set_backend_property);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_view);
+}
+
+static void
+g_signal (GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters)
+{
+ guint signal_id, signal_type;
+
+ signal_id = lookup_signal_id_from_signal_name (signal_name);
+ signal_type = lookup_signal_type_from_signal_name (signal_name);
+
+ g_return_if_fail (signal_id != 0);
+ g_return_if_fail (signal_type != 0);
+
+ e_gdbus_proxy_emit_signal (proxy, parameters, signals[signal_id], signal_type);
+}
+
+static void
+gdbus_book_proxy_finalize (GObject *object)
+{
+ EGdbusBookProxy *proxy = E_GDBUS_BOOK_PROXY (object);
+
+ g_return_if_fail (proxy != NULL);
+ g_return_if_fail (proxy->priv != NULL);
+
+ if (g_hash_table_size (proxy->priv->pending_ops))
+ g_debug ("%s: Kept %d items in pending_ops", G_STRFUNC, g_hash_table_size (proxy->priv->pending_ops));
+
+ g_hash_table_destroy (proxy->priv->pending_ops);
+
+ G_OBJECT_CLASS (e_gdbus_book_proxy_parent_class)->finalize (object);
+}
+
+static void
+e_gdbus_book_proxy_class_init (EGdbusBookProxyClass *klass)
+{
+ GObjectClass *object_class;
+ GDBusProxyClass *proxy_class;
+
+ g_type_class_add_private (klass, sizeof (EGdbusBookProxyPrivate));
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gdbus_book_proxy_finalize;
+
+ proxy_class = G_DBUS_PROXY_CLASS (klass);
+ proxy_class->g_signal = g_signal;
+}
+
+static void
+proxy_iface_init (EGdbusBookIface *iface)
+{
+}
+
+static GHashTable *
+gdbus_book_get_pending_ops (EGdbusAsyncOpKeeper *object)
+{
+ EGdbusBookProxy *proxy;
+
+ g_return_val_if_fail (object != NULL, NULL);
+ g_return_val_if_fail (E_IS_GDBUS_BOOK_PROXY (object), NULL);
+
+ proxy = E_GDBUS_BOOK_PROXY (object);
+ g_return_val_if_fail (proxy != NULL, NULL);
+ g_return_val_if_fail (proxy->priv != NULL, NULL);
+
+ return proxy->priv->pending_ops;
+}
+
+static gboolean
+gdbus_book_call_cancel_operation_sync (EGdbusAsyncOpKeeper *object, guint in_opid, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_book_call_cancel_operation_sync (G_DBUS_PROXY (object), in_opid, cancellable, error);
+}
+
+static void
+async_op_keeper_iface_init (EGdbusAsyncOpKeeperInterface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->get_pending_ops = gdbus_book_get_pending_ops;
+ iface->cancel_op_sync = gdbus_book_call_cancel_operation_sync;
+}
+
+/**
+ * e_gdbus_book_proxy_new:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: Callback function to invoke when the proxy is ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_dbus_proxy_new() but returns a #EGdbusBookProxy.
+ *
+ * This is a failable asynchronous constructor - when the proxy is ready, callback will be invoked and you can use e_gdbus_book_proxy_new_finish() to get the result.
+ */
+void
+e_gdbus_book_proxy_new (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ g_async_initable_new_async (E_TYPE_GDBUS_BOOK_PROXY,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "g-flags", flags,
+ "g-name", name,
+ "g-connection", connection,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_BOOK_INTERFACE_NAME,
+ NULL);
+}
+
+/**
+ * e_gdbus_book_proxy_new_finish:
+ * @result: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to e_gdbus_book_proxy_new().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes creating a #EGdbusBookProxy.
+ *
+ * Returns: A #EGdbusBookProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+EGdbusBook *
+e_gdbus_book_proxy_new_finish (GAsyncResult *result, GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (result);
+ g_assert (source_object != NULL);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error);
+ g_object_unref (source_object);
+
+ if (object != NULL)
+ return E_GDBUS_BOOK (object);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_book_proxy_new_sync:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_proxy_new_sync() but returns a #EGdbusBookProxy.
+ *
+ * This is a synchronous failable constructor. See e_gdbus_book_proxy_new() and e_gdbus_book_proxy_new_finish() for the asynchronous version.
+ *
+ * Returns: A #EGdbusBookProxy or %NULL if error is set. Free with g_object_unref().
+ */
+EGdbusBook *
+e_gdbus_book_proxy_new_sync (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error)
+{
+ GInitable *initable;
+ initable = g_initable_new (E_TYPE_GDBUS_BOOK_PROXY,
+ cancellable,
+ error,
+ "g-flags", flags,
+ "g-name", name,
+ "g-connection", connection,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_BOOK_INTERFACE_NAME,
+ NULL);
+ if (initable != NULL)
+ return E_GDBUS_BOOK (initable);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_book_proxy_new_for_bus:
+ * @bus_type: A #GBusType.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: Callback function to invoke when the proxy is ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_dbus_proxy_new_for_bus() but returns a #EGdbusBookProxy.
+ *
+ * This is a failable asynchronous constructor - when the proxy is ready, callback will be invoked and you can use e_gdbus_book_proxy_new_for_bus_finish() to get the result.
+ */
+void
+e_gdbus_book_proxy_new_for_bus (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ g_async_initable_new_async (E_TYPE_GDBUS_BOOK_PROXY,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "g-flags", flags,
+ "g-name", name,
+ "g-bus-type", bus_type,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_BOOK_INTERFACE_NAME,
+ NULL);
+}
+
+/**
+ * e_gdbus_book_proxy_new_for_bus_finish:
+ * @result: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to e_gdbus_book_proxy_new_for_bus().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes creating a #EGdbusBookProxy.
+ *
+ * Returns: A #EGdbusBookProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+EGdbusBook *
+e_gdbus_book_proxy_new_for_bus_finish (GAsyncResult *result, GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (result);
+ g_assert (source_object != NULL);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error);
+ g_object_unref (source_object);
+
+ if (object != NULL)
+ return E_GDBUS_BOOK (object);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_book_proxy_new_for_bus_sync:
+ * @bus_type: A #GBusType.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_proxy_new_for_bus_sync() but returns a #EGdbusBookProxy.
+ *
+ * This is a synchronous failable constructor. See e_gdbus_book_proxy_new_for_bus() and e_gdbus_book_proxy_new_for_bus_finish() for the asynchronous version.
+ *
+ * Returns: A #EGdbusBookProxy or %NULL if error is set. Free with g_object_unref().
+ */
+EGdbusBook *
+e_gdbus_book_proxy_new_for_bus_sync (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error)
+{
+ GInitable *initable;
+
+ initable = g_initable_new (E_TYPE_GDBUS_BOOK_PROXY,
+ cancellable,
+ error,
+ "g-flags", flags,
+ "g-name", name,
+ "g-bus-type", bus_type,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_BOOK_INTERFACE_NAME,
+ NULL);
+ if (initable != NULL)
+ return E_GDBUS_BOOK (initable);
+ else
+ return NULL;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct _EGdbusBookStubPrivate
+{
+ gint foo;
+};
+
+static void stub_iface_init (EGdbusBookIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EGdbusBookStub, e_gdbus_book_stub, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_BOOK, stub_iface_init));
+
+static void
+e_gdbus_book_stub_init (EGdbusBookStub *stub)
+{
+ stub->priv = G_TYPE_INSTANCE_GET_PRIVATE (stub, E_TYPE_GDBUS_BOOK_STUB, EGdbusBookStubPrivate);
+}
+
+static void
+e_gdbus_book_stub_class_init (EGdbusBookStubClass *klass)
+{
+ g_type_class_add_private (klass, sizeof (EGdbusBookStubPrivate));
+}
+
+static void
+stub_iface_init (EGdbusBookIface *iface)
+{
+}
+
+/**
+ * e_gdbus_book_stub_new:
+ *
+ * Creates a new stub object that can be exported via e_gdbus_book_register_object().
+ *
+ * Returns: A #EGdbusBookStub instance. Free with g_object_unref().
+ */
+EGdbusBook *
+e_gdbus_book_stub_new (void)
+{
+ return E_GDBUS_BOOK (g_object_new (E_TYPE_GDBUS_BOOK_STUB, NULL));
+}
+
+/* Returns GDBus connection associated with the stub object */
+GDBusConnection *
+e_gdbus_book_stub_get_connection (EGdbusBook *stub)
+{
+ g_return_val_if_fail (stub != NULL, NULL);
+ g_return_val_if_fail (E_IS_GDBUS_BOOK_STUB (stub), NULL);
+
+ return g_object_get_data (G_OBJECT (stub), "gdbus-codegen-connection");
+}
diff --git a/addressbook/libegdbus/e-gdbus-book.h b/addressbook/libegdbus/e-gdbus-book.h
new file mode 100644
index 0000000..ae0dd9e
--- /dev/null
+++ b/addressbook/libegdbus/e-gdbus-book.h
@@ -0,0 +1,265 @@
+/*
+ * e-gdbus-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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_GDBUS_BOOK_H
+#define E_GDBUS_BOOK_H
+
+#include <gio/gio.h>
+
+#include <libedataserver/e-gdbus-templates.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_GDBUS_BOOK (e_gdbus_book_get_type ())
+#define E_GDBUS_BOOK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_GDBUS_BOOK, EGdbusBook))
+#define E_IS_GDBUS_BOOK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_GDBUS_BOOK))
+#define E_GDBUS_BOOK_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE((o), E_TYPE_GDBUS_BOOK, EGdbusBookIface))
+
+/**
+ * EGdbusBook:
+ *
+ * Opaque type representing a proxy or an exported object.
+ */
+typedef struct _EGdbusBook EGdbusBook; /* Dummy typedef */
+
+typedef struct _EGdbusBookIface EGdbusBookIface;
+
+GType e_gdbus_book_get_type (void) G_GNUC_CONST;
+
+/* ---------------------------------------------------------------------- */
+
+#define E_TYPE_GDBUS_BOOK_PROXY (e_gdbus_book_proxy_get_type ())
+#define E_GDBUS_BOOK_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_GDBUS_BOOK_PROXY, EGdbusBookProxy))
+#define E_IS_GDBUS_BOOK_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_GDBUS_BOOK_PROXY))
+
+typedef struct _EGdbusBookProxy EGdbusBookProxy;
+typedef struct _EGdbusBookProxyClass EGdbusBookProxyClass;
+typedef struct _EGdbusBookProxyPrivate EGdbusBookProxyPrivate;
+
+struct _EGdbusBookProxy
+{
+ GDBusProxy parent_instance;
+ EGdbusBookProxyPrivate *priv;
+};
+
+struct _EGdbusBookProxyClass
+{
+ GDBusProxyClass parent_class;
+};
+
+GType e_gdbus_book_proxy_get_type (void) G_GNUC_CONST;
+
+void e_gdbus_book_proxy_new (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+EGdbusBook *e_gdbus_book_proxy_new_finish (GAsyncResult *result, GError **error);
+EGdbusBook *e_gdbus_book_proxy_new_sync (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_proxy_new_for_bus (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+EGdbusBook *e_gdbus_book_proxy_new_for_bus_finish (GAsyncResult *result, GError **error);
+EGdbusBook *e_gdbus_book_proxy_new_for_bus_sync (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error);
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct _EGdbusBookStub EGdbusBookStub;
+typedef struct _EGdbusBookStubClass EGdbusBookStubClass;
+typedef struct _EGdbusBookStubPrivate EGdbusBookStubPrivate;
+
+struct _EGdbusBookStub
+{
+ GObject parent_instance;
+ EGdbusBookStubPrivate *priv;
+};
+
+struct _EGdbusBookStubClass
+{
+ GObjectClass parent_class;
+};
+
+#define E_TYPE_GDBUS_BOOK_STUB (e_gdbus_book_stub_get_type ())
+#define E_GDBUS_BOOK_STUB(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_GDBUS_BOOK_STUB, EGdbusBookStub))
+#define E_IS_GDBUS_BOOK_STUB(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_GDBUS_BOOK_STUB))
+
+GType e_gdbus_book_stub_get_type (void) G_GNUC_CONST;
+
+EGdbusBook *e_gdbus_book_stub_new (void);
+GDBusConnection *e_gdbus_book_stub_get_connection (EGdbusBook *stub);
+
+guint e_gdbus_book_register_object (EGdbusBook *object, GDBusConnection *connection, const gchar *object_path, GError **error);
+
+void e_gdbus_book_drain_notify (EGdbusBook *object);
+
+const GDBusInterfaceInfo *e_gdbus_book_interface_info (void) G_GNUC_CONST;
+
+struct _EGdbusBookIface
+{
+ GTypeInterface parent_iface;
+
+ /* Signal handlers for receiving D-Bus signals: */
+ void (*backend_error) (EGdbusBook *object, const gchar *arg_message);
+ void (*readonly) (EGdbusBook *object, gboolean arg_is_readonly);
+ void (*online) (EGdbusBook *object, gboolean arg_is_online);
+ void (*auth_required) (EGdbusBook *object, const gchar * const *arg_credentials);
+ void (*opened) (EGdbusBook *object, const gchar * const *arg_error);
+
+ /* Signal handlers for handling D-Bus method calls: */
+ gboolean (*handle_open) (EGdbusBook *object, GDBusMethodInvocation *invocation, gboolean in_only_if_exists);
+ void (*open_done) (EGdbusBook *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_remove) (EGdbusBook *object, GDBusMethodInvocation *invocation);
+ void (*remove_done) (EGdbusBook *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_refresh) (EGdbusBook *object, GDBusMethodInvocation *invocation);
+ void (*refresh_done) (EGdbusBook *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_get_contact) (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_uid);
+ void (*get_contact_done) (EGdbusBook *object, guint arg_opid, const GError *arg_error, gchar **out_vcard);
+
+ gboolean (*handle_get_contact_list) (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_query);
+ void (*get_contact_list_done) (EGdbusBook *object, guint arg_opid, const GError *arg_error, gchar ***out_vcards);
+
+ gboolean (*handle_add_contact) (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_vcard);
+ void (*add_contact_done) (EGdbusBook *object, guint arg_opid, const GError *arg_error, gchar **out_uid);
+
+ gboolean (*handle_remove_contacts) (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar * const *in_list);
+ void (*remove_contacts_done) (EGdbusBook *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_modify_contact) (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_vcard);
+ void (*modify_contact_done) (EGdbusBook *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_get_backend_property) (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_prop_name);
+ void (*get_backend_property_done) (EGdbusBook *object, guint arg_opid, const GError *arg_error, gchar **out_prop_value);
+
+ gboolean (*handle_set_backend_property) (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_prop_name_value);
+ void (*set_backend_property_done) (EGdbusBook *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_get_view) (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar *in_query);
+ void (*get_view_done) (EGdbusBook *object, guint arg_opid, const GError *arg_error, gchar **out_view);
+
+ gboolean (*handle_authenticate_user) (EGdbusBook *object, GDBusMethodInvocation *invocation, const gchar * const *in_credentials);
+ gboolean (*handle_cancel_operation) (EGdbusBook *object, GDBusMethodInvocation *invocation, guint in_opid);
+ gboolean (*handle_cancel_all) (EGdbusBook *object, GDBusMethodInvocation *invocation);
+ gboolean (*handle_close) (EGdbusBook *object, GDBusMethodInvocation *invocation);
+
+};
+
+/* C Bindings for properties */
+
+/* D-Bus Methods */
+void e_gdbus_book_call_open (GDBusProxy *proxy, gboolean in_only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_open_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_call_open_sync (GDBusProxy *proxy, gboolean in_only_if_exists, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_call_remove (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_remove_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_call_remove_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_call_refresh (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_refresh_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_call_refresh_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_call_get_contact (GDBusProxy *proxy, const gchar *in_uid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_get_contact_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_vcard, GError **error);
+gboolean e_gdbus_book_call_get_contact_sync (GDBusProxy *proxy, const gchar *in_uid, gchar **out_vcard, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_call_get_contact_list (GDBusProxy *proxy, const gchar *in_query, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_get_contact_list_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_vcards, GError **error);
+gboolean e_gdbus_book_call_get_contact_list_sync (GDBusProxy *proxy, const gchar *in_query, gchar ***out_vcards, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_call_add_contact (GDBusProxy *proxy, const gchar *in_vcard, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_add_contact_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_uid, GError **error);
+gboolean e_gdbus_book_call_add_contact_sync (GDBusProxy *proxy, const gchar *in_vcard, gchar **out_uid, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_call_remove_contacts (GDBusProxy *proxy, const gchar * const *in_list, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_remove_contacts_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_call_remove_contacts_sync (GDBusProxy *proxy, const gchar * const *in_list, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_call_modify_contact (GDBusProxy *proxy, const gchar *in_vcard, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_modify_contact_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_call_modify_contact_sync (GDBusProxy *proxy, const gchar *in_vcard, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_call_get_backend_property (GDBusProxy *proxy, const gchar *in_prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_get_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_prop_value, GError **error);
+gboolean e_gdbus_book_call_get_backend_property_sync (GDBusProxy *proxy, const gchar *prop_name, gchar **out_prop_value, GCancellable *cancellable, GError **error);
+
+gchar ** e_gdbus_book_encode_set_backend_property (const gchar *in_prop_name, const gchar *in_prop_value);
+gboolean e_gdbus_book_decode_set_backend_property (const gchar * const *in_strv, gchar **out_prop_name, gchar **out_prop_value);
+void e_gdbus_book_call_set_backend_property (GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_set_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_call_set_backend_property_sync (GDBusProxy *proxy, const gchar * const *prop_name_value, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_call_get_view (GDBusProxy *proxy, const gchar *in_query, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_get_view_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_view_path, GError **error);
+gboolean e_gdbus_book_call_get_view_sync (GDBusProxy *proxy, const gchar *in_query, gchar **out_view_path, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_call_authenticate_user (GDBusProxy *proxy, const gchar * const *in_credentials, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_authenticate_user_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_call_authenticate_user_sync (GDBusProxy *proxy, const gchar * const *in_credentials, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_call_cancel_operation (GDBusProxy *proxy, guint in_opid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_cancel_operation_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_call_cancel_operation_sync (GDBusProxy *proxy, guint in_opid, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_call_cancel_all (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_cancel_all_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_call_cancel_all_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+void e_gdbus_book_call_close (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_book_call_close_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_book_call_close_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+/* D-Bus Methods Completion Helpers */
+#define e_gdbus_book_complete_open e_gdbus_complete_async_method
+#define e_gdbus_book_complete_remove e_gdbus_complete_async_method
+#define e_gdbus_book_complete_refresh e_gdbus_complete_async_method
+#define e_gdbus_book_complete_get_contact e_gdbus_complete_async_method
+#define e_gdbus_book_complete_get_contact_list e_gdbus_complete_async_method
+#define e_gdbus_book_complete_add_contact e_gdbus_complete_async_method
+#define e_gdbus_book_complete_remove_contacts e_gdbus_complete_async_method
+#define e_gdbus_book_complete_modify_contact e_gdbus_complete_async_method
+#define e_gdbus_book_complete_get_backend_property e_gdbus_complete_async_method
+#define e_gdbus_book_complete_set_backend_property e_gdbus_complete_async_method
+#define e_gdbus_book_complete_get_view e_gdbus_complete_async_method
+#define e_gdbus_book_complete_authenticate_user e_gdbus_complete_sync_method_void
+#define e_gdbus_book_complete_cancel_operation e_gdbus_complete_sync_method_void
+#define e_gdbus_book_complete_cancel_all e_gdbus_complete_sync_method_void
+#define e_gdbus_book_complete_close e_gdbus_complete_sync_method_void
+
+void e_gdbus_book_emit_open_done (EGdbusBook *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_book_emit_remove_done (EGdbusBook *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_book_emit_refresh_done (EGdbusBook *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_book_emit_get_contact_done (EGdbusBook *object, guint arg_opid, const GError *arg_error, const gchar *out_vcard);
+void e_gdbus_book_emit_get_contact_list_done (EGdbusBook *object, guint arg_opid, const GError *arg_error, const gchar * const *out_vcards);
+void e_gdbus_book_emit_add_contact_done (EGdbusBook *object, guint arg_opid, const GError *arg_error, const gchar *out_uid);
+void e_gdbus_book_emit_remove_contacts_done (EGdbusBook *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_book_emit_modify_contact_done (EGdbusBook *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_book_emit_get_backend_property_done (EGdbusBook *object, guint arg_opid, const GError *arg_error, const gchar *out_prop_value);
+void e_gdbus_book_emit_set_backend_property_done (EGdbusBook *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_book_emit_get_view_done (EGdbusBook *object, guint arg_opid, const GError *arg_error, const gchar *out_view);
+
+/* D-Bus Signal Emission Helpers */
+void e_gdbus_book_emit_backend_error (EGdbusBook *object, const gchar *arg_message);
+void e_gdbus_book_emit_readonly (EGdbusBook *object, gboolean arg_is_readonly);
+void e_gdbus_book_emit_online (EGdbusBook *object, gboolean arg_is_online);
+void e_gdbus_book_emit_auth_required (EGdbusBook *object, const gchar * const *arg_credentials);
+void e_gdbus_book_emit_opened (EGdbusBook *object, const gchar * const *arg_error);
+
+G_END_DECLS
+
+#endif /* E_GDBUS_BOOK_H */
diff --git a/calendar/backends/caldav/e-cal-backend-caldav.c b/calendar/backends/caldav/e-cal-backend-caldav.c
index 98afd27..b99491e 100644
--- a/calendar/backends/caldav/e-cal-backend-caldav.c
+++ b/calendar/backends/caldav/e-cal-backend-caldav.c
@@ -74,7 +74,7 @@ typedef enum {
struct _ECalBackendCalDAVPrivate {
/* online/offline */
- CalMode mode;
+ gboolean is_online;
/* The local disk cache */
ECalBackendStore *store;
@@ -113,15 +113,12 @@ struct _ECalBackendCalDAVPrivate {
gchar *uri;
/* Authentication info */
- gchar *username;
- gchar *password;
+ ECredentials *credentials;
gboolean need_auth;
/* object cleanup */
gboolean disposed;
- icaltimezone *default_zone;
-
/* support for 'getctag' extension */
gboolean ctag_supported;
gchar *ctag_to_store;
@@ -302,7 +299,6 @@ put_component_to_store (ECalBackendCalDAV *cbdav,
static ECalBackendSyncClass *parent_class = NULL;
-static icaltimezone *caldav_internal_get_default_timezone (ECalBackend *backend);
static icaltimezone *caldav_internal_get_timezone (ECalBackend *backend, const gchar *tzid);
static void caldav_source_changed_cb (ESource *source, ECalBackendCalDAV *cbdav);
@@ -571,7 +567,7 @@ check_state (ECalBackendCalDAV *cbdav, gboolean *online, GError **perror)
return FALSE;
}
- if (priv->mode == CAL_MODE_LOCAL) {
+ if (!priv->is_online) {
if (!priv->do_offline) {
g_propagate_error (perror, EDC_ERROR (RepositoryOffline));
@@ -906,8 +902,10 @@ soup_authenticate (SoupSession *session,
priv = cbdav->priv;
/* do not send same password twice, but keep it for later use */
- if (!retrying)
- soup_auth_authenticate (auth, priv->username, priv->password);
+ if (!retrying && priv->credentials && e_credentials_has_key (priv->credentials, E_CREDENTIALS_KEY_USERNAME)) {
+ soup_auth_authenticate (auth, e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_USERNAME), e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_PASSWORD));
+ e_credentials_clear_peek (priv->credentials);
+ }
}
/* ************************************************************************* */
@@ -2106,6 +2104,7 @@ caldav_synch_slave_loop (gpointer data)
}
e_cal_backend_notify_readonly (E_CAL_BACKEND (cbdav), priv->read_only);
+ e_cal_backend_notify_online (E_CAL_BACKEND (cbdav), priv->is_online);
}
if (priv->opened) {
@@ -2187,8 +2186,8 @@ get_usermail (ECalBackend *backend)
cbdav = E_CAL_BACKEND_CALDAV (backend);
priv = cbdav->priv;
- if (priv && priv->is_google && priv->username) {
- res = maybe_append_email_domain (priv->username, "@gmail.com");
+ if (priv && priv->is_google && priv->credentials) {
+ res = maybe_append_email_domain (e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_USERNAME), "@gmail.com");
}
return res;
@@ -2197,82 +2196,69 @@ get_usermail (ECalBackend *backend)
/* ************************************************************************* */
/* ********** ECalBackendSync virtual function implementation ************* */
-static void
-caldav_is_read_only (ECalBackendSync *backend,
- EDataCal *cal,
- gboolean *read_only,
- GError **perror)
+static gboolean
+caldav_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **perror)
{
- ECalBackendCalDAV *cbdav;
- ECalBackendCalDAVPrivate *priv;
+ gboolean processed = TRUE;
- cbdav = E_CAL_BACKEND_CALDAV (backend);
- priv = cbdav->priv;
+ g_return_val_if_fail (prop_name != NULL, FALSE);
+ g_return_val_if_fail (prop_value != NULL, FALSE);
- /* no write support in offline mode yet! */
- if (priv->mode == CAL_MODE_LOCAL) {
- *read_only = TRUE;
- } else {
- *read_only = priv->read_only;
- }
-}
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ ESource *source;
+ GString *caps;
+ gchar *usermail;
-static void
-caldav_get_cal_address (ECalBackendSync *backend,
- EDataCal *cal,
- gchar **address,
- GError **perror)
-{
- *address = get_usermail (E_CAL_BACKEND (backend));
-}
+ caps = g_string_new (CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
+ CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
+ CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED);
-static void
-caldav_get_alarm_email_address (ECalBackendSync *backend,
- EDataCal *cal,
- gchar **address,
- GError **perror)
-{
- *address = get_usermail (E_CAL_BACKEND (backend));
-}
+ usermail = get_usermail (E_CAL_BACKEND (backend));
+ if (!usermail || !*usermail)
+ g_string_append (caps, "," CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS);
+ g_free (usermail);
-static void
-caldav_get_ldap_attribute (ECalBackendSync *backend,
- EDataCal *cal,
- gchar **attribute,
- GError **perror)
-{
- *attribute = NULL;
-}
+ source = e_cal_backend_get_source (E_CAL_BACKEND (backend));
+ if (source) {
+ const gchar *prop = e_source_get_property (source, "autoschedule");
-static void
-caldav_get_static_capabilities (ECalBackendSync *backend,
- EDataCal *cal,
- gchar **capabilities,
- GError **perror)
-{
- ESource *source;
- GString *caps;
- gchar *usermail;
+ if (prop && g_str_equal (prop, "1"))
+ g_string_append (caps, "," CAL_STATIC_CAPABILITY_CREATE_MESSAGES
+ "," CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
+ }
- caps = g_string_new (CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
- CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
- CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED);
+ *prop_value = g_string_free (caps, FALSE);
+ } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+ g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+ *prop_value = get_usermail (E_CAL_BACKEND (backend));
+ } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+ ECalComponent *comp;
- usermail = get_usermail (E_CAL_BACKEND (backend));
- if (!usermail || !*usermail)
- g_string_append (caps, "," CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS);
- g_free (usermail);
+ comp = e_cal_component_new ();
- source = e_cal_backend_get_source (E_CAL_BACKEND (backend));
- if (source) {
- const gchar *prop = e_source_get_property (source, "autoschedule");
+ switch (e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
+ case ICAL_VEVENT_COMPONENT:
+ e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
+ break;
+ case ICAL_VTODO_COMPONENT:
+ e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
+ break;
+ case ICAL_VJOURNAL_COMPONENT:
+ e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
+ break;
+ default:
+ g_object_unref (comp);
+ g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
+ return TRUE;
+ }
- if (prop && g_str_equal (prop, "1"))
- g_string_append (caps, "," CAL_STATIC_CAPABILITY_CREATE_MESSAGES
- "," CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
+ *prop_value = e_cal_component_get_as_string (comp);
+ g_object_unref (comp);
+ } else {
+ processed = FALSE;
}
- *capabilities = g_string_free (caps, FALSE);
+ return processed;
}
static gboolean
@@ -2431,12 +2417,40 @@ proxy_settings_changed (EProxy *proxy, gpointer user_data)
}
static void
-caldav_do_open (ECalBackendSync *backend,
- EDataCal *cal,
- gboolean only_if_exists,
- const gchar *username,
- const gchar *password,
- GError **perror)
+open_calendar (ECalBackendCalDAV *cbdav, GError **error)
+{
+ gboolean server_unreachable = FALSE;
+ ECalBackendCalDAVPrivate *priv;
+ GError *local_error = NULL;
+
+ g_return_if_fail (cbdav != NULL);
+
+ priv = cbdav->priv;
+
+ /* set forward proxy */
+ proxy_settings_changed (priv->proxy, priv);
+
+ if (caldav_server_open_calendar (cbdav, &server_unreachable, &local_error)) {
+ priv->slave_cmd = SLAVE_SHOULD_WORK;
+ g_cond_signal (priv->cond);
+
+ priv->is_google = is_google_uri (priv->uri);
+ } else if (server_unreachable) {
+ priv->opened = FALSE;
+ priv->read_only = TRUE;
+ if (local_error) {
+ gchar *msg = g_strdup_printf (_("Server is unreachable, calendar is opened in read-only mode.\nError message: %s"), local_error->message);
+ e_cal_backend_notify_error (E_CAL_BACKEND (cbdav), msg);
+ g_free (msg);
+ g_clear_error (&local_error);
+ }
+ } else if (local_error) {
+ g_propagate_error (error, local_error);
+ }
+}
+
+static void
+caldav_do_open (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gboolean only_if_exists, GError **perror)
{
ECalBackendCalDAV *cbdav;
ECalBackendCalDAVPrivate *priv;
@@ -2454,20 +2468,7 @@ caldav_do_open (ECalBackendSync *backend,
return;
}
- if (priv->need_auth) {
- if ((username == NULL || password == NULL)) {
- g_mutex_unlock (priv->busy_lock);
- g_propagate_error (perror, EDC_ERROR (AuthenticationRequired));
- return;
- }
-
- g_free (priv->username);
- priv->username = g_strdup (username);
- g_free (priv->password);
- priv->password = g_strdup (password);
- }
-
- if (!priv->do_offline && priv->mode == CAL_MODE_LOCAL) {
+ if (!priv->do_offline && !priv->is_online) {
g_mutex_unlock (priv->busy_lock);
g_propagate_error (perror, EDC_ERROR (RepositoryOffline));
return;
@@ -2477,39 +2478,60 @@ caldav_do_open (ECalBackendSync *backend,
priv->opened = TRUE;
priv->is_google = FALSE;
- if (priv->mode == CAL_MODE_REMOTE) {
- gboolean server_unreachable = FALSE;
+ if (priv->is_online) {
GError *local_error = NULL;
- /* set forward proxy */
- proxy_settings_changed (priv->proxy, priv);
+ open_calendar (cbdav, &local_error);
- if (caldav_server_open_calendar (cbdav, &server_unreachable, &local_error)) {
- priv->slave_cmd = SLAVE_SHOULD_WORK;
- g_cond_signal (priv->cond);
-
- priv->is_google = is_google_uri (priv->uri);
- } else if (server_unreachable) {
- priv->opened = FALSE;
- priv->read_only = TRUE;
- if (local_error) {
- gchar *msg = g_strdup_printf (_("Server is unreachable, calendar is opened in read-only mode.\nError message: %s"), local_error->message);
- e_cal_backend_notify_error (E_CAL_BACKEND (backend), msg);
- g_free (msg);
- g_clear_error (&local_error);
- }
+ if (g_error_matches (local_error, E_DATA_CAL_ERROR, AuthenticationRequired) || g_error_matches (local_error, E_DATA_CAL_ERROR, AuthenticationFailed)) {
+ g_clear_error (&local_error);
+ e_cal_backend_notify_auth_required (E_CAL_BACKEND (cbdav), TRUE, priv->credentials);
} else {
- g_propagate_error (perror, local_error);
+ e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
}
+
+ if (local_error)
+ g_propagate_error (perror, local_error);
} else {
priv->read_only = TRUE;
+ e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
+ }
+
+ e_cal_backend_notify_readonly (E_CAL_BACKEND (backend), priv->read_only);
+ e_cal_backend_notify_online (E_CAL_BACKEND (backend), priv->is_online);
+
+ g_mutex_unlock (priv->busy_lock);
+}
+
+static void
+caldav_authenticate_user (ECalBackendSync *backend, GCancellable *cancellable, ECredentials *credentials, GError **error)
+{
+ ECalBackendCalDAV *cbdav;
+ ECalBackendCalDAVPrivate *priv;
+
+ cbdav = E_CAL_BACKEND_CALDAV (backend);
+ priv = cbdav->priv;
+
+ g_mutex_lock (priv->busy_lock);
+
+ e_credentials_free (priv->credentials);
+ priv->credentials = NULL;
+
+ if (!credentials || !e_credentials_has_key (credentials, E_CREDENTIALS_KEY_USERNAME)) {
+ g_mutex_unlock (priv->busy_lock);
+ g_propagate_error (error, EDC_ERROR (AuthenticationRequired));
+ return;
}
+ priv->credentials = e_credentials_new_clone (credentials);
+
+ open_calendar (cbdav, error);
+
g_mutex_unlock (priv->busy_lock);
}
static void
-caldav_refresh (ECalBackendSync *backend, EDataCal *cal, GError **perror)
+caldav_refresh (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **perror)
{
ECalBackendCalDAV *cbdav;
ECalBackendCalDAVPrivate *priv;
@@ -2536,9 +2558,7 @@ caldav_refresh (ECalBackendSync *backend, EDataCal *cal, GError **perror)
}
static void
-caldav_remove (ECalBackendSync *backend,
- EDataCal *cal,
- GError **perror)
+caldav_remove (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **perror)
{
ECalBackendCalDAV *cbdav;
ECalBackendCalDAVPrivate *priv;
@@ -3133,7 +3153,7 @@ static void
sanitize_component (ECalBackend *cb, ECalComponent *comp)
{
ECalComponentDateTime dt;
- icaltimezone *zone, *default_zone;
+ icaltimezone *zone;
/* Check dtstart, dtend and due's timezone, and convert it to local
* default timezone if the timezone is not in our builtin timezone
@@ -3142,9 +3162,8 @@ sanitize_component (ECalBackend *cb, ECalComponent *comp)
if (dt.value && dt.tzid) {
zone = caldav_internal_get_timezone (cb, dt.tzid);
if (!zone) {
- default_zone = caldav_internal_get_default_timezone (cb);
g_free ((gchar *) dt.tzid);
- dt.tzid = g_strdup (icaltimezone_get_tzid (default_zone));
+ dt.tzid = g_strdup ("UTC");
e_cal_component_set_dtstart (comp, &dt);
}
}
@@ -3154,9 +3173,8 @@ sanitize_component (ECalBackend *cb, ECalComponent *comp)
if (dt.value && dt.tzid) {
zone = caldav_internal_get_timezone (cb, dt.tzid);
if (!zone) {
- default_zone = caldav_internal_get_default_timezone (cb);
g_free ((gchar *) dt.tzid);
- dt.tzid = g_strdup (icaltimezone_get_tzid (default_zone));
+ dt.tzid = g_strdup ("UTC");
e_cal_component_set_dtend (comp, &dt);
}
}
@@ -3166,9 +3184,8 @@ sanitize_component (ECalBackend *cb, ECalComponent *comp)
if (dt.value && dt.tzid) {
zone = caldav_internal_get_timezone (cb, dt.tzid);
if (!zone) {
- default_zone = caldav_internal_get_default_timezone (cb);
g_free ((gchar *) dt.tzid);
- dt.tzid = g_strdup (icaltimezone_get_tzid (default_zone));
+ dt.tzid = g_strdup ("UTC");
e_cal_component_set_due (comp, &dt);
}
}
@@ -3312,7 +3329,7 @@ replace_master (ECalBackendCalDAV *cbdav, icalcomponent *old_comp, icalcomponent
/* a busy_lock is supposed to be locked already, when calling this function */
static void
-do_create_object (ECalBackendCalDAV *cbdav, gchar **calobj, gchar **uid, GError **perror)
+do_create_object (ECalBackendCalDAV *cbdav, const gchar *in_calobj, gchar **uid, gchar **new_calobj, GError **perror)
{
ECalComponent *comp;
gboolean online, did_put = FALSE;
@@ -3323,7 +3340,7 @@ do_create_object (ECalBackendCalDAV *cbdav, gchar **calobj, gchar **uid, GError
if (!check_state (cbdav, &online, perror))
return;
- comp = e_cal_component_new_from_string (*calobj);
+ comp = e_cal_component_new_from_string (in_calobj);
if (comp == NULL) {
g_propagate_error (perror, EDC_ERROR (InvalidObject));
@@ -3394,13 +3411,13 @@ do_create_object (ECalBackendCalDAV *cbdav, gchar **calobj, gchar **uid, GError
icalcomponent *master = get_master_comp (cbdav, icalcomp);
if (!master)
- *calobj = e_cal_component_get_as_string (comp);
+ *new_calobj = e_cal_component_get_as_string (comp);
else
- *calobj = icalcomponent_as_ical_string_r (master);
+ *new_calobj = icalcomponent_as_ical_string_r (master);
icalcomponent_free (icalcomp);
} else {
- *calobj = e_cal_component_get_as_string (comp);
+ *new_calobj = e_cal_component_get_as_string (comp);
}
}
@@ -3677,7 +3694,7 @@ do_remove_object (ECalBackendCalDAV *cbdav, const gchar *uid, const gchar *rid,
static void
extract_objects (icalcomponent *icomp,
icalcomponent_kind ekind,
- GList **objects,
+ GSList **objects,
GError **error)
{
icalcomponent *scomp;
@@ -3689,7 +3706,7 @@ extract_objects (icalcomponent *icomp,
kind = icalcomponent_isa (icomp);
if (kind == ekind) {
- *objects = g_list_prepend (NULL, icomp);
+ *objects = g_slist_prepend (NULL, icomp);
return;
}
@@ -3704,7 +3721,7 @@ extract_objects (icalcomponent *icomp,
while (scomp) {
/* Remove components from toplevel here */
- *objects = g_list_prepend (*objects, scomp);
+ *objects = g_slist_prepend (*objects, scomp);
icalcomponent_remove_component (icomp, scomp);
scomp = icalcomponent_get_next_component (icomp, ekind);
@@ -3715,7 +3732,7 @@ static gboolean
extract_timezones (ECalBackendCalDAV *cbdav, icalcomponent *icomp)
{
ECalBackendCalDAVPrivate *priv;
- GList *timezones = NULL, *iter;
+ GSList *timezones = NULL, *iter;
icaltimezone *zone;
GError *err = NULL;
@@ -3740,7 +3757,7 @@ extract_timezones (ECalBackendCalDAV *cbdav, icalcomponent *icomp)
}
icaltimezone_free (zone, TRUE);
- g_list_free (timezones);
+ g_slist_free (timezones);
return TRUE;
}
@@ -3812,7 +3829,7 @@ process_object (ECalBackendCalDAV *cbdav,
} else if (!is_declined) {
gchar *new_object = new_obj_str;
- do_create_object (cbdav, &new_object, NULL, &err);
+ do_create_object (cbdav, new_object, NULL, &new_object, &err);
if (!err) {
e_cal_backend_notify_object_created (backend, new_object);
}
@@ -3854,15 +3871,14 @@ process_object (ECalBackendCalDAV *cbdav,
}
static void
-do_receive_objects (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, GError **perror)
+do_receive_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GError **perror)
{
ECalBackendCalDAV *cbdav;
icalcomponent *icomp;
icalcomponent_kind kind;
icalproperty_method tmethod;
gboolean online;
- GList *objects;
- GList *iter;
+ GSList *objects, *iter;
GError *err = NULL;
cbdav = E_CAL_BACKEND_CALDAV (backend);
@@ -3913,7 +3929,7 @@ do_receive_objects (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj
g_object_unref (ecomp);
}
- g_list_free (objects);
+ g_slist_free (objects);
icalcomponent_free (icomp);
@@ -3954,62 +3970,30 @@ _func_name _params \
}
caldav_busy_stub (
- caldav_create_object, (ECalBackendSync *backend, EDataCal *cal, gchar **calobj, gchar **uid, GError **perror),
- do_create_object, (cbdav, calobj, uid, perror))
+ caldav_create_object, (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *in_calobj, gchar **uid, gchar **new_calobj, GError **perror),
+ do_create_object, (cbdav, in_calobj, uid, new_calobj, perror))
caldav_busy_stub (
- caldav_modify_object, (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, CalObjModType mod, gchar **old_object, gchar **new_object, GError **perror),
+ caldav_modify_object, (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, CalObjModType mod, gchar **old_object, gchar **new_object, GError **perror),
do_modify_object, (cbdav, calobj, mod, old_object, new_object, perror))
caldav_busy_stub (
- caldav_remove_object, (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *rid, CalObjModType mod, gchar **old_object, gchar **object, GError **perror),
+ caldav_remove_object, (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, CalObjModType mod, gchar **old_object, gchar **object, GError **perror),
do_remove_object, (cbdav, uid, rid, mod, old_object, object, perror))
caldav_busy_stub (
- caldav_receive_objects, (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, GError **perror),
- do_receive_objects, (backend, cal, calobj, perror))
-
-static void
-caldav_discard_alarm (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *auid, GError **perror)
-{
-}
+ caldav_receive_objects, (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GError **perror),
+ do_receive_objects, (backend, cal, cancellable, calobj, perror))
static void
-caldav_send_objects (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, GList **users, gchar **modified_calobj, GError **perror)
+caldav_send_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GSList **users, gchar **modified_calobj, GError **perror)
{
*users = NULL;
*modified_calobj = g_strdup (calobj);
}
static void
-caldav_get_default_object (ECalBackendSync *backend, EDataCal *cal, gchar **object, GError **perror)
-{
- ECalComponent *comp;
-
- comp = e_cal_component_new ();
-
- switch (e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
- case ICAL_VEVENT_COMPONENT:
- e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
- break;
- case ICAL_VTODO_COMPONENT:
- e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
- break;
- case ICAL_VJOURNAL_COMPONENT:
- e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
- break;
- default:
- g_object_unref (comp);
- g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
- return;
- }
-
- *object = e_cal_component_get_as_string (comp);
- g_object_unref (comp);
-}
-
-static void
-caldav_get_object (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *rid, gchar **object, GError **perror)
+caldav_get_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **object, GError **perror)
{
ECalBackendCalDAV *cbdav;
icalcomponent *icalcomp;
@@ -4029,10 +4013,7 @@ caldav_get_object (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, co
}
static void
-caldav_add_timezone (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *tzobj,
- GError **error)
+caldav_add_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobj, GError **error)
{
icalcomponent *tz_comp;
ECalBackendCalDAV *cbdav;
@@ -4066,44 +4047,7 @@ caldav_add_timezone (ECalBackendSync *backend,
}
static void
-caldav_set_default_zone (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *tzobj,
- GError **error)
-{
- icalcomponent *tz_comp;
- ECalBackendCalDAV *cbdav;
- ECalBackendCalDAVPrivate *priv;
- icaltimezone *zone;
-
- e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_CALDAV (backend), InvalidArg);
- e_return_data_cal_error_if_fail (tzobj != NULL, InvalidArg);
-
- cbdav = E_CAL_BACKEND_CALDAV (backend);
- priv = cbdav->priv;
-
- tz_comp = icalparser_parse_string (tzobj);
- if (!tz_comp) {
- g_propagate_error (error, EDC_ERROR (InvalidObject));
- return;
- }
-
- zone = icaltimezone_new ();
- icaltimezone_set_component (zone, tz_comp);
-
- if (priv->default_zone != icaltimezone_get_utc_timezone ())
- icaltimezone_free (priv->default_zone, 1);
-
- /* Set the default timezone to it. */
- priv->default_zone = zone;
-}
-
-static void
-caldav_get_object_list (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *sexp_string,
- GList **objects,
- GError **perror)
+caldav_get_object_list (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *sexp_string, GSList **objects, GError **perror)
{
ECalBackendCalDAV *cbdav;
ECalBackendCalDAVPrivate *priv;
@@ -4132,9 +4076,7 @@ caldav_get_object_list (ECalBackendSync *backend,
*objects = NULL;
- prunning_by_time = e_cal_backend_sexp_evaluate_occur_times (sexp,
- &occur_start,
- &occur_end);
+ prunning_by_time = e_cal_backend_sexp_evaluate_occur_times (sexp, &occur_start, &occur_end);
bkend = E_CAL_BACKEND (backend);
@@ -4149,7 +4091,7 @@ caldav_get_object_list (ECalBackendSync *backend,
if (!do_search ||
e_cal_backend_sexp_match_comp (sexp, comp, bkend)) {
- *objects = g_list_prepend (*objects, e_cal_component_get_as_string (comp));
+ *objects = g_slist_prepend (*objects, e_cal_component_get_as_string (comp));
}
g_object_unref (comp);
@@ -4160,8 +4102,7 @@ caldav_get_object_list (ECalBackendSync *backend,
}
static void
-caldav_start_query (ECalBackend *backend,
- EDataCalView *query)
+caldav_start_view (ECalBackend *backend, EDataCalView *query)
{
ECalBackendCalDAV *cbdav;
ECalBackendCalDAVPrivate *priv;
@@ -4211,17 +4152,11 @@ caldav_start_query (ECalBackend *backend,
g_object_unref (sexp);
g_slist_free (list);
- e_data_cal_view_notify_done (query, NULL /* Success */);
+ e_data_cal_view_notify_complete (query, NULL /* Success */);
}
static void
-caldav_get_free_busy (ECalBackendSync *backend,
- EDataCal *cal,
- GList *users,
- time_t start,
- time_t end,
- GList **freebusy,
- GError **error)
+caldav_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const GSList *users, time_t start, time_t end, GSList **freebusy, GError **error)
{
ECalBackendCalDAV *cbdav;
ECalBackendCalDAVPrivate *priv;
@@ -4231,7 +4166,7 @@ caldav_get_free_busy (ECalBackendSync *backend,
struct icaltimetype dtvalue;
icaltimezone *utc;
gchar *str, *usermail;
- GList *u;
+ const GSList *u;
GSList *attendees = NULL, *to_free = NULL;
GError *err = NULL;
@@ -4283,10 +4218,10 @@ caldav_get_free_busy (ECalBackendSync *backend,
usermail = NULL;
}
- if (priv->username || usermail) {
+ if ((priv->credentials && e_credentials_has_key (priv->credentials, E_CREDENTIALS_KEY_USERNAME)) || usermail) {
ECalComponentOrganizer organizer = {NULL};
- organizer.value = usermail ? usermail : priv->username;
+ organizer.value = usermail ? usermail : e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_USERNAME);
organizer.value = g_strconcat ("mailto:", organizer.value, NULL);
e_cal_component_set_organizer (comp, &organizer);
@@ -4361,7 +4296,7 @@ caldav_get_free_busy (ECalBackendSync *backend,
tmp = xp_object_get_string (xpath_eval (xpctx, "string(/C:schedule-response/C:response[%d]/C:calendar-data)", i + 1));
if (tmp && *tmp) {
- GList *objects = NULL, *o;
+ GSList *objects = NULL, *o;
icalcomp = icalparser_parse_string (tmp);
if (icalcomp)
@@ -4371,14 +4306,14 @@ caldav_get_free_busy (ECalBackendSync *backend,
gchar *obj_str = icalcomponent_as_ical_string_r (o->data);
if (obj_str && *obj_str)
- *freebusy = g_list_append (*freebusy, obj_str);
+ *freebusy = g_slist_append (*freebusy, obj_str);
else
g_free (obj_str);
}
}
- g_list_foreach (objects, (GFunc) icalcomponent_free, NULL);
- g_list_free (objects);
+ g_slist_foreach (objects, (GFunc) icalcomponent_free, NULL);
+ g_slist_free (objects);
if (icalcomp)
icalcomponent_free (icalcomp);
@@ -4405,44 +4340,7 @@ caldav_get_free_busy (ECalBackendSync *backend,
}
static void
-caldav_get_changes (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *change_id,
- GList **adds,
- GList **modifies,
- GList **deletes,
- GError **perror)
-{
- /* FIXME: implement me! */
- g_propagate_error (perror, EDC_ERROR (NotSupported));
-}
-
-static gboolean
-caldav_is_loaded (ECalBackend *backend)
-{
- ECalBackendCalDAV *cbdav;
- ECalBackendCalDAVPrivate *priv;
-
- cbdav = E_CAL_BACKEND_CALDAV (backend);
- priv = cbdav->priv;
-
- return priv->loaded;
-}
-
-static CalMode
-caldav_get_mode (ECalBackend *backend)
-{
- ECalBackendCalDAV *cbdav;
- ECalBackendCalDAVPrivate *priv;
-
- cbdav = E_CAL_BACKEND_CALDAV (backend);
- priv = cbdav->priv;
-
- return priv->mode;
-}
-
-static void
-caldav_set_mode (ECalBackend *backend, CalMode mode)
+caldav_set_online (ECalBackend *backend, gboolean is_online)
{
ECalBackendCalDAV *cbdav;
ECalBackendCalDAVPrivate *priv;
@@ -4452,28 +4350,16 @@ caldav_set_mode (ECalBackend *backend, CalMode mode)
/*g_mutex_lock (priv->busy_lock);*/
- /* We only support online and offline */
- if (mode != CAL_MODE_REMOTE &&
- mode != CAL_MODE_LOCAL) {
- e_cal_backend_notify_mode (backend,
- ModeNotSupported,
- cal_mode_to_corba (mode));
- /*g_mutex_unlock (priv->busy_lock);*/
- return;
- }
-
- if (priv->mode == mode || !priv->loaded) {
- priv->mode = mode;
- e_cal_backend_notify_mode (backend,
- ModeSet,
- cal_mode_to_corba (mode));
+ if ((priv->is_online ? 1: 0) == (is_online ? 1 : 0) || !priv->loaded) {
+ priv->is_online = is_online;
+ e_cal_backend_notify_online (backend, is_online);
/*g_mutex_unlock (priv->busy_lock);*/
return;
}
- priv->mode = mode;
+ priv->is_online = is_online;
- if (mode == CAL_MODE_REMOTE) {
+ if (is_online) {
/* Wake up the slave thread */
priv->slave_cmd = SLAVE_SHOULD_WORK;
g_cond_signal (priv->cond);
@@ -4482,30 +4368,12 @@ caldav_set_mode (ECalBackend *backend, CalMode mode)
priv->slave_cmd = SLAVE_SHOULD_SLEEP;
}
- e_cal_backend_notify_mode (backend,
- ModeSet,
- cal_mode_to_corba (mode));
+ e_cal_backend_notify_online (backend, is_online);
/*g_mutex_unlock (priv->busy_lock);*/
}
static icaltimezone *
-caldav_internal_get_default_timezone (ECalBackend *backend)
-{
- ECalBackendCalDAV *cbdav;
- ECalBackendCalDAVPrivate *priv;
-
- g_return_val_if_fail (E_IS_CAL_BACKEND_CALDAV (backend), NULL);
-
- cbdav = E_CAL_BACKEND_CALDAV (backend);
- priv = cbdav->priv;
-
- g_return_val_if_fail (priv->default_zone != NULL, NULL);
-
- return priv->default_zone;
-}
-
-static icaltimezone *
caldav_internal_get_timezone (ECalBackend *backend,
const gchar *tzid)
{
@@ -4598,8 +4466,9 @@ e_cal_backend_caldav_dispose (GObject *object)
g_object_unref (priv->session);
g_object_unref (priv->proxy);
- g_free (priv->username);
- g_free (priv->password);
+ e_credentials_free (priv->credentials);
+ priv->credentials = NULL;
+
g_free (priv->uri);
g_free (priv->schedule_outbox_url);
@@ -4627,11 +4496,6 @@ e_cal_backend_caldav_finalize (GObject *object)
g_cond_free (priv->cond);
g_cond_free (priv->slave_gone_cond);
- if (priv->default_zone && priv->default_zone != icaltimezone_get_utc_timezone ()) {
- icaltimezone_free (priv->default_zone, 1);
- }
- priv->default_zone = NULL;
-
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -4652,8 +4516,6 @@ e_cal_backend_caldav_init (ECalBackendCalDAV *cbdav)
if (G_UNLIKELY (caldav_debug_show (DEBUG_MESSAGE)))
caldav_debug_setup (cbdav->priv->session);
- cbdav->priv->default_zone = icaltimezone_get_utc_timezone ();
-
cbdav->priv->disposed = FALSE;
cbdav->priv->loaded = FALSE;
cbdav->priv->opened = FALSE;
@@ -4701,36 +4563,26 @@ e_cal_backend_caldav_class_init (ECalBackendCalDAVClass *class)
object_class->dispose = e_cal_backend_caldav_dispose;
object_class->finalize = e_cal_backend_caldav_finalize;
- sync_class->is_read_only_sync = caldav_is_read_only;
- sync_class->get_cal_address_sync = caldav_get_cal_address;
- sync_class->get_alarm_email_address_sync = caldav_get_alarm_email_address;
- sync_class->get_ldap_attribute_sync = caldav_get_ldap_attribute;
- sync_class->get_static_capabilities_sync = caldav_get_static_capabilities;
-
- sync_class->open_sync = caldav_do_open;
- sync_class->refresh_sync = caldav_refresh;
- sync_class->remove_sync = caldav_remove;
-
- sync_class->create_object_sync = caldav_create_object;
- sync_class->modify_object_sync = caldav_modify_object;
- sync_class->remove_object_sync = caldav_remove_object;
-
- sync_class->discard_alarm_sync = caldav_discard_alarm;
- sync_class->receive_objects_sync = caldav_receive_objects;
- sync_class->send_objects_sync = caldav_send_objects;
- sync_class->get_default_object_sync = caldav_get_default_object;
- sync_class->get_object_sync = caldav_get_object;
- sync_class->get_object_list_sync = caldav_get_object_list;
- sync_class->add_timezone_sync = caldav_add_timezone;
- sync_class->set_default_zone_sync = caldav_set_default_zone;
- sync_class->get_freebusy_sync = caldav_get_free_busy;
- sync_class->get_changes_sync = caldav_get_changes;
-
- backend_class->is_loaded = caldav_is_loaded;
- backend_class->start_query = caldav_start_query;
- backend_class->get_mode = caldav_get_mode;
- backend_class->set_mode = caldav_set_mode;
-
- backend_class->internal_get_default_timezone = caldav_internal_get_default_timezone;
- backend_class->internal_get_timezone = caldav_internal_get_timezone;
+ sync_class->get_backend_property_sync = caldav_get_backend_property;
+
+ sync_class->open_sync = caldav_do_open;
+ sync_class->authenticate_user_sync = caldav_authenticate_user;
+ sync_class->refresh_sync = caldav_refresh;
+ sync_class->remove_sync = caldav_remove;
+
+ sync_class->create_object_sync = caldav_create_object;
+ sync_class->modify_object_sync = caldav_modify_object;
+ sync_class->remove_object_sync = caldav_remove_object;
+
+ sync_class->receive_objects_sync = caldav_receive_objects;
+ sync_class->send_objects_sync = caldav_send_objects;
+ sync_class->get_object_sync = caldav_get_object;
+ sync_class->get_object_list_sync = caldav_get_object_list;
+ sync_class->add_timezone_sync = caldav_add_timezone;
+ sync_class->get_free_busy_sync = caldav_get_free_busy;
+
+ backend_class->start_view = caldav_start_view;
+ backend_class->set_online = caldav_set_online;
+
+ backend_class->internal_get_timezone = caldav_internal_get_timezone;
}
diff --git a/calendar/backends/contacts/e-cal-backend-contacts.c b/calendar/backends/contacts/e-cal-backend-contacts.c
index 7d9866f..89f7bfb 100644
--- a/calendar/backends/contacts/e-cal-backend-contacts.c
+++ b/calendar/backends/contacts/e-cal-backend-contacts.c
@@ -67,7 +67,6 @@ struct _ECalBackendContactsPrivate {
GHashTable *tracked_contacts; /* UID -> ContactRecord */
GHashTable *zones;
- icaltimezone *default_zone;
EFlag *init_done_flag; /* is set, when the init thread gone */
@@ -106,7 +105,7 @@ static ECalComponent * create_anniversary (ECalBackendContacts *cbc, EContact *c
static void contacts_changed_cb (EBookView *book_view, const GList *contacts, gpointer user_data);
static void contacts_added_cb (EBookView *book_view, const GList *contacts, gpointer user_data);
static void contacts_removed_cb (EBookView *book_view, const GList *contact_ids, gpointer user_data);
-static void e_cal_backend_contacts_add_timezone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **perror);
+static void e_cal_backend_contacts_add_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobj, GError **perror);
static void setup_alarm (ECalBackendContacts *cbc, ECalComponent *comp);
/* BookRecord methods */
@@ -258,7 +257,7 @@ contact_record_free (ContactRecord *cr)
typedef struct _ContactRecordCB {
ECalBackendContacts *cbc;
ECalBackendSExp *sexp;
- GList *result;
+ GSList *result;
} ContactRecordCB;
static ContactRecordCB *
@@ -276,8 +275,8 @@ contact_record_cb_new (ECalBackendContacts *cbc, ECalBackendSExp *sexp)
static void
contact_record_cb_free (ContactRecordCB *cb_data)
{
- g_list_foreach (cb_data->result, (GFunc) g_free, NULL);
- g_list_free (cb_data->result);
+ g_slist_foreach (cb_data->result, (GFunc) g_free, NULL);
+ g_slist_free (cb_data->result);
g_free (cb_data);
}
@@ -290,12 +289,12 @@ contact_record_cb (gpointer key, gpointer value, gpointer user_data)
if (record->comp_birthday && e_cal_backend_sexp_match_comp (cb_data->sexp, record->comp_birthday, E_CAL_BACKEND (cb_data->cbc))) {
gchar * comp_str = e_cal_component_get_as_string (record->comp_birthday);
- cb_data->result = g_list_append (cb_data->result, comp_str);
+ cb_data->result = g_slist_append (cb_data->result, comp_str);
}
if (record->comp_anniversary && e_cal_backend_sexp_match_comp (cb_data->sexp, record->comp_anniversary, E_CAL_BACKEND (cb_data->cbc))) {
gchar * comp_str = e_cal_component_get_as_string (record->comp_anniversary);
- cb_data->result = g_list_append (cb_data->result, comp_str);
+ cb_data->result = g_slist_append (cb_data->result, comp_str);
}
}
@@ -791,56 +790,40 @@ create_anniversary (ECalBackendContacts *cbc, EContact *contact)
/* First the empty stubs */
-static void
-e_cal_backend_contacts_get_cal_address (ECalBackendSync *backend, EDataCal *cal,
- gchar **address, GError **perror)
-{
- /* A contact backend has no particular email address associated
- * with it (although that would be a useful feature some day).
- */
- *address = NULL;
-}
-
-static void
-e_cal_backend_contacts_get_ldap_attribute (ECalBackendSync *backend, EDataCal *cal,
- gchar **attribute, GError **perror)
-{
- *attribute = NULL;
-}
-
-static void
-e_cal_backend_contacts_get_alarm_email_address (ECalBackendSync *backend, EDataCal *cal,
- gchar **address, GError **perror)
+static gboolean
+e_cal_backend_contacts_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **perror)
{
- /* A contact backend has no particular email address associated
- * with it (although that would be a useful feature some day).
- */
- *address = NULL;
-}
+ gboolean processed = TRUE;
+
+ g_return_val_if_fail (prop_name != NULL, FALSE);
+ g_return_val_if_fail (prop_value != NULL, FALSE);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ *prop_value = NULL;
+ } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+ g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+ /* A contact backend has no particular email address associated
+ * with it (although that would be a useful feature some day).
+ */
+ *prop_value = NULL;
+ } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+ g_propagate_error (perror, EDC_ERROR (UnsupportedMethod));
+ } else {
+ processed = FALSE;
+ }
-static void
-e_cal_backend_contacts_get_static_capabilities (ECalBackendSync *backend, EDataCal *cal,
- gchar **capabilities, GError **perror)
-{
- *capabilities = NULL;
+ return processed;
}
static void
-e_cal_backend_contacts_remove (ECalBackendSync *backend, EDataCal *cal, GError **perror)
+e_cal_backend_contacts_remove (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **perror)
{
/* WRITE ME */
g_propagate_error (perror, EDC_ERROR (PermissionDenied));
}
static void
-e_cal_backend_contacts_get_default_object (ECalBackendSync *backend, EDataCal *cal,
- gchar **object, GError **perror)
-{
- g_propagate_error (perror, EDC_ERROR (UnsupportedMethod));
-}
-
-static void
-e_cal_backend_contacts_get_object (ECalBackendSync *backend, EDataCal *cal,
+e_cal_backend_contacts_get_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable,
const gchar *uid, const gchar *rid,
gchar **object, GError **perror)
{
@@ -889,9 +872,9 @@ e_cal_backend_contacts_get_object (ECalBackendSync *backend, EDataCal *cal,
}
static void
-e_cal_backend_contacts_get_free_busy (ECalBackendSync *backend, EDataCal *cal,
- GList *users, time_t start, time_t end,
- GList **freebusy, GError **perror)
+e_cal_backend_contacts_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable,
+ const GSList *users, time_t start, time_t end,
+ GSList **freebusy, GError **perror)
{
/* Birthdays/anniversaries don't count as busy time */
@@ -916,7 +899,7 @@ e_cal_backend_contacts_get_free_busy (ECalBackendSync *backend, EDataCal *cal,
icalcomponent_set_dtend (vfb, icaltime_from_timet_with_zone (end, FALSE, utc_zone));
calobj = icalcomponent_as_ical_string_r (vfb);
- *freebusy = g_list_append (NULL, calobj);
+ *freebusy = g_slist_append (NULL, calobj);
icalcomponent_free (vfb);
/* WRITE ME */
@@ -924,30 +907,15 @@ e_cal_backend_contacts_get_free_busy (ECalBackendSync *backend, EDataCal *cal,
}
static void
-e_cal_backend_contacts_get_changes (ECalBackendSync *backend, EDataCal *cal,
- const gchar *change_id,
- GList **adds, GList **modifies, GList **deletes, GError **perror)
-{
- /* WRITE ME */
-}
-
-static void
-e_cal_backend_contacts_discard_alarm (ECalBackendSync *backend, EDataCal *cal,
- const gchar *uid, const gchar *auid, GError **perror)
-{
- /* WRITE ME */
-}
-
-static void
-e_cal_backend_contacts_receive_objects (ECalBackendSync *backend, EDataCal *cal,
+e_cal_backend_contacts_receive_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable,
const gchar *calobj, GError **perror)
{
g_propagate_error (perror, EDC_ERROR (PermissionDenied));
}
static void
-e_cal_backend_contacts_send_objects (ECalBackendSync *backend, EDataCal *cal,
- const gchar *calobj, GList **users, gchar **modified_calobj, GError **perror)
+e_cal_backend_contacts_send_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable,
+ const gchar *calobj, GSList **users, gchar **modified_calobj, GError **perror)
{
*users = NULL;
*modified_calobj = NULL;
@@ -957,23 +925,11 @@ e_cal_backend_contacts_send_objects (ECalBackendSync *backend, EDataCal *cal,
/* Then the real implementations */
-static CalMode
-e_cal_backend_contacts_get_mode (ECalBackend *backend)
-{
- return CAL_MODE_LOCAL;
-}
-
-static void
-e_cal_backend_contacts_set_mode (ECalBackend *backend, CalMode mode)
-{
- e_cal_backend_notify_mode (backend, ModeNotSupported, Local);
-}
-
static void
-e_cal_backend_contacts_is_read_only (ECalBackendSync *backend, EDataCal *cal,
- gboolean *read_only, GError **perror)
+e_cal_backend_contacts_set_online (ECalBackend *backend, gboolean is_online)
{
- *read_only = TRUE;
+ e_cal_backend_notify_online (backend, is_online);
+ e_cal_backend_notify_readonly (backend, TRUE);
}
static gpointer
@@ -1004,9 +960,8 @@ init_sources_cb (ECalBackendContacts *cbc)
}
static void
-e_cal_backend_contacts_open (ECalBackendSync *backend, EDataCal *cal,
- gboolean only_if_exists,
- const gchar *username, const gchar *password, GError **perror)
+e_cal_backend_contacts_open (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable,
+ gboolean only_if_exists, GError **perror)
{
ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (backend);
ECalBackendContactsPrivate *priv = cbc->priv;
@@ -1015,15 +970,6 @@ e_cal_backend_contacts_open (ECalBackendSync *backend, EDataCal *cal,
if (priv->addressbook_loaded)
return;
- if (priv->default_zone && priv->default_zone != icaltimezone_get_utc_timezone ()) {
- icalcomponent *icalcomp = icaltimezone_get_component (priv->default_zone);
- icaltimezone *zone = icaltimezone_new ();
-
- icaltimezone_set_component (zone, icalcomponent_new_clone (icalcomp));
-
- g_hash_table_insert (priv->zones, g_strdup (icaltimezone_get_tzid (zone)), zone);
- }
-
/* initialize addressbook sources in new thread to make this function quick as much as possible */
if (!g_thread_create ((GThreadFunc) init_sources_cb, cbc, FALSE, &error)) {
e_flag_set (priv->init_done_flag);
@@ -1032,24 +978,19 @@ e_cal_backend_contacts_open (ECalBackendSync *backend, EDataCal *cal,
g_error_free (error);
g_propagate_error (perror, EDC_ERROR (OtherError));
+ e_cal_backend_notify_opened (E_CAL_BACKEND (backend), EDC_ERROR (OtherError));
return;
}
priv->addressbook_loaded = TRUE;
-}
-
-static gboolean
-e_cal_backend_contacts_is_loaded (ECalBackend *backend)
-{
- ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (backend);
- ECalBackendContactsPrivate *priv = cbc->priv;
-
- return priv->addressbook_loaded;
+ e_cal_backend_notify_readonly (E_CAL_BACKEND (backend), TRUE);
+ e_cal_backend_notify_online (E_CAL_BACKEND (backend), TRUE);
+ e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
}
/* Add_timezone handler for the file backend */
static void
-e_cal_backend_contacts_add_timezone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **error)
+e_cal_backend_contacts_add_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobj, GError **error)
{
ECalBackendContacts *cbcontacts;
ECalBackendContactsPrivate *priv;
@@ -1087,39 +1028,8 @@ e_cal_backend_contacts_add_timezone (ECalBackendSync *backend, EDataCal *cal, co
}
static void
-e_cal_backend_contacts_set_default_zone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **error)
-{
- icalcomponent *tz_comp;
- ECalBackendContacts *cbcontacts;
- ECalBackendContactsPrivate *priv;
- icaltimezone *zone;
-
- cbcontacts = (ECalBackendContacts *) backend;
-
- e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_CONTACTS (cbcontacts), InvalidArg);
- e_return_data_cal_error_if_fail (tzobj != NULL, InvalidArg);
-
- priv = cbcontacts->priv;
-
- tz_comp = icalparser_parse_string (tzobj);
- if (!tz_comp) {
- g_propagate_error (error, EDC_ERROR (InvalidObject));
- return;
- }
-
- zone = icaltimezone_new ();
- icaltimezone_set_component (zone, tz_comp);
-
- if (priv->default_zone && priv->default_zone != icaltimezone_get_utc_timezone ())
- icaltimezone_free (priv->default_zone, 1);
-
- /* Set the default timezone to it. */
- priv->default_zone = zone;
-}
-
-static void
-e_cal_backend_contacts_get_object_list (ECalBackendSync *backend, EDataCal *cal,
- const gchar *sexp_string, GList **objects, GError **perror)
+e_cal_backend_contacts_get_object_list (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable,
+ const gchar *sexp_string, GSList **objects, GError **perror)
{
ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (backend);
ECalBackendContactsPrivate *priv = cbc->priv;
@@ -1141,7 +1051,7 @@ e_cal_backend_contacts_get_object_list (ECalBackendSync *backend, EDataCal *cal,
}
static void
-e_cal_backend_contacts_start_query (ECalBackend *backend, EDataCalView *query)
+e_cal_backend_contacts_start_view (ECalBackend *backend, EDataCalView *query)
{
ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (backend);
ECalBackendContactsPrivate *priv = cbc->priv;
@@ -1151,7 +1061,7 @@ e_cal_backend_contacts_start_query (ECalBackend *backend, EDataCalView *query)
sexp = e_data_cal_view_get_object_sexp (query);
if (!sexp) {
GError *error = EDC_ERROR (InvalidQuery);
- e_data_cal_view_notify_done (query, error);
+ e_data_cal_view_notify_complete (query, error);
g_error_free (error);
return;
}
@@ -1163,15 +1073,7 @@ e_cal_backend_contacts_start_query (ECalBackend *backend, EDataCalView *query)
contact_record_cb_free (cb_data);
- e_data_cal_view_notify_done (query, NULL /* Success */);
-}
-
-static icaltimezone *
-e_cal_backend_contacts_internal_get_default_timezone (ECalBackend *backend)
-{
- ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (backend);
-
- return cbc->priv->default_zone;
+ e_data_cal_view_notify_complete (query, NULL /* Success */);
}
static icaltimezone *
@@ -1179,7 +1081,7 @@ e_cal_backend_contacts_internal_get_timezone (ECalBackend *backend, const gchar
{
ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (backend);
- return cbc->priv->default_zone;
+ return g_hash_table_lookup (cbc->priv->zones, tzid ? tzid : "");
}
/***********************************************************************************
@@ -1215,11 +1117,6 @@ e_cal_backend_contacts_finalize (GObject *object)
priv->update_alarms_id = 0;
}
- if (priv->default_zone && priv->default_zone != icaltimezone_get_utc_timezone ()) {
- icaltimezone_free (priv->default_zone, 1);
- }
-
- priv->default_zone = NULL;
g_object_unref (priv->addressbook_sources);
g_hash_table_destroy (priv->addressbooks);
g_hash_table_destroy (priv->tracked_contacts);
@@ -1256,7 +1153,6 @@ e_cal_backend_contacts_init (ECalBackendContacts *cbc)
g_free, (GDestroyNotify) contact_record_free);
priv->zones = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_zone);
- priv->default_zone = icaltimezone_get_utc_timezone ();
priv->init_done_flag = e_flag_new ();
priv->conf_client = gconf_client_get_default ();
priv->notifyid1 = 0;
@@ -1273,7 +1169,7 @@ e_cal_backend_contacts_init (ECalBackendContacts *cbc)
}
static void
-e_cal_backend_contacts_create_object (ECalBackendSync *backend, EDataCal *cal, gchar **calobj, gchar **uid, GError **perror)
+e_cal_backend_contacts_create_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, gchar **uid, gchar **new_calobj, GError **perror)
{
g_propagate_error (perror, EDC_ERROR (PermissionDenied));
}
@@ -1294,29 +1190,18 @@ e_cal_backend_contacts_class_init (ECalBackendContactsClass *class)
object_class->finalize = e_cal_backend_contacts_finalize;
- sync_class->is_read_only_sync = e_cal_backend_contacts_is_read_only;
- sync_class->get_cal_address_sync = e_cal_backend_contacts_get_cal_address;
- sync_class->get_alarm_email_address_sync = e_cal_backend_contacts_get_alarm_email_address;
- sync_class->get_ldap_attribute_sync = e_cal_backend_contacts_get_ldap_attribute;
- sync_class->get_static_capabilities_sync = e_cal_backend_contacts_get_static_capabilities;
- sync_class->open_sync = e_cal_backend_contacts_open;
- sync_class->remove_sync = e_cal_backend_contacts_remove;
- sync_class->create_object_sync = e_cal_backend_contacts_create_object;
- sync_class->discard_alarm_sync = e_cal_backend_contacts_discard_alarm;
- sync_class->receive_objects_sync = e_cal_backend_contacts_receive_objects;
- sync_class->send_objects_sync = e_cal_backend_contacts_send_objects;
- sync_class->get_default_object_sync = e_cal_backend_contacts_get_default_object;
- sync_class->get_object_sync = e_cal_backend_contacts_get_object;
- sync_class->get_object_list_sync = e_cal_backend_contacts_get_object_list;
- sync_class->add_timezone_sync = e_cal_backend_contacts_add_timezone;
- sync_class->set_default_zone_sync = e_cal_backend_contacts_set_default_zone;
- sync_class->get_freebusy_sync = e_cal_backend_contacts_get_free_busy;
- sync_class->get_changes_sync = e_cal_backend_contacts_get_changes;
- backend_class->is_loaded = e_cal_backend_contacts_is_loaded;
- backend_class->start_query = e_cal_backend_contacts_start_query;
- backend_class->get_mode = e_cal_backend_contacts_get_mode;
- backend_class->set_mode = e_cal_backend_contacts_set_mode;
-
- backend_class->internal_get_default_timezone = e_cal_backend_contacts_internal_get_default_timezone;
- backend_class->internal_get_timezone = e_cal_backend_contacts_internal_get_timezone;
+ sync_class->get_backend_property_sync = e_cal_backend_contacts_get_backend_property;
+ sync_class->open_sync = e_cal_backend_contacts_open;
+ sync_class->remove_sync = e_cal_backend_contacts_remove;
+ sync_class->create_object_sync = e_cal_backend_contacts_create_object;
+ sync_class->receive_objects_sync = e_cal_backend_contacts_receive_objects;
+ sync_class->send_objects_sync = e_cal_backend_contacts_send_objects;
+ sync_class->get_object_sync = e_cal_backend_contacts_get_object;
+ sync_class->get_object_list_sync = e_cal_backend_contacts_get_object_list;
+ sync_class->add_timezone_sync = e_cal_backend_contacts_add_timezone;
+ sync_class->get_free_busy_sync = e_cal_backend_contacts_get_free_busy;
+
+ backend_class->start_view = e_cal_backend_contacts_start_view;
+ backend_class->set_online = e_cal_backend_contacts_set_online;
+ backend_class->internal_get_timezone = e_cal_backend_contacts_internal_get_timezone;
}
diff --git a/calendar/backends/file/e-cal-backend-file.c b/calendar/backends/file/e-cal-backend-file.c
index 0bbd4aa..e7c1958 100644
--- a/calendar/backends/file/e-cal-backend-file.c
+++ b/calendar/backends/file/e-cal-backend-file.c
@@ -93,10 +93,6 @@ struct _ECalBackendFilePrivate {
GList *comp;
- /* The calendar's default timezone, used for resolving DATE and
- floating DATE-TIME values. */
- icaltimezone *default_zone;
-
/* a custom filename opened */
gchar *custom_file;
@@ -127,17 +123,11 @@ static void e_cal_backend_file_finalize (GObject *object);
static ECalBackendSyncClass *parent_class;
-static void
-e_cal_backend_file_add_timezone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **perror);
-
static void free_refresh_data (ECalBackendFile *cbfile);
static icaltimezone *
e_cal_backend_file_internal_get_timezone (ECalBackend *backend, const gchar *tzid);
-static icaltimezone *
-e_cal_backend_file_internal_get_default_timezone (ECalBackend *backend);
-
/* g_hash_table_foreach() callback to destroy a ECalBackendFileObject */
static void
free_object_data (gpointer data)
@@ -371,11 +361,6 @@ e_cal_backend_file_finalize (GObject *object)
g_free (priv->custom_file);
priv->custom_file = NULL;
- if (priv->default_zone && priv->default_zone != icaltimezone_get_utc_timezone ()) {
- icaltimezone_free (priv->default_zone, 1);
- }
- priv->default_zone = NULL;
-
if (priv->file_name) {
g_free (priv->file_name);
priv->file_name = NULL;
@@ -406,47 +391,54 @@ lookup_component (ECalBackendFile *cbfile, const gchar *uid)
/* Calendar backend methods */
-/* Is_read_only handler for the file backend */
-static void
-e_cal_backend_file_is_read_only (ECalBackendSync *backend, EDataCal *cal, gboolean *read_only, GError **perror)
-{
- ECalBackendFile *cbfile = (ECalBackendFile *) backend;
-
- *read_only = cbfile->priv->read_only;
-}
-
/* Get_email_address handler for the file backend */
-static void
-e_cal_backend_file_get_cal_address (ECalBackendSync *backend, EDataCal *cal, gchar **address, GError **perror)
-{
- /* A file backend has no particular email address associated
- * with it (although that would be a useful feature some day).
- */
- *address = NULL;
-}
+static gboolean
+e_cal_backend_file_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **perror)
+{
+ gboolean processed = TRUE;
+
+ g_return_val_if_fail (prop_name != NULL, FALSE);
+ g_return_val_if_fail (prop_value != NULL, FALSE);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ *prop_value = g_strdup (CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS ","
+ CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
+ CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED ","
+ CAL_STATIC_CAPABILITY_NO_THISANDPRIOR);
+ } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+ g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+ /* A file backend has no particular email address associated
+ * with it (although that would be a useful feature some day).
+ */
+ *prop_value = NULL;
+ } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+ ECalComponent *comp;
-static void
-e_cal_backend_file_get_ldap_attribute (ECalBackendSync *backend, EDataCal *cal, gchar **attribute, GError **perror)
-{
- *attribute = NULL;
-}
+ comp = e_cal_component_new ();
-static void
-e_cal_backend_file_get_alarm_email_address (ECalBackendSync *backend, EDataCal *cal, gchar **address, GError **perror)
-{
- /* A file backend has no particular email address associated
- * with it (although that would be a useful feature some day).
- */
- *address = NULL;
-}
+ switch (e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
+ case ICAL_VEVENT_COMPONENT:
+ e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
+ break;
+ case ICAL_VTODO_COMPONENT:
+ e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
+ break;
+ case ICAL_VJOURNAL_COMPONENT:
+ e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
+ break;
+ default:
+ g_object_unref (comp);
+ g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
+ return TRUE;
+ }
-static void
-e_cal_backend_file_get_static_capabilities (ECalBackendSync *backend, EDataCal *cal, gchar **capabilities, GError **perror)
-{
- *capabilities = g_strdup (CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS ","
- CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
- CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED ","
- CAL_STATIC_CAPABILITY_NO_THISANDPRIOR);
+ *prop_value = e_cal_component_get_as_string (comp);
+ g_object_unref (comp);
+ } else {
+ processed = FALSE;
+ }
+
+ return processed;
}
/* function to resolve timezones */
@@ -533,7 +525,7 @@ add_component_to_intervaltree (ECalBackendFile *cbfile, ECalComponent *comp)
priv = cbfile->priv;
e_cal_util_get_component_occur_times (comp, &time_start, &time_end,
- resolve_tzid, priv->icalcomp, priv->default_zone,
+ resolve_tzid, priv->icalcomp, icaltimezone_get_utc_timezone (),
e_cal_backend_get_kind (E_CAL_BACKEND (cbfile)));
if (time_end != -1 && time_start > time_end)
@@ -1197,104 +1189,6 @@ get_uri_string (ECalBackend *backend)
return full_uri;
}
-static gboolean
-add_timezone (icalcomponent *icalcomp, icaltimezone *tzone)
-{
- GSList *to_remove = NULL, *r;
- icalcomponent *subcomp;
- icaltimezone *zone;
- gboolean add = TRUE, have_same = FALSE;
- const gchar *tzid;
- gchar *cmp;
-
- g_return_val_if_fail (icalcomp != NULL, FALSE);
-
- /* it's fine to have passed in NULL tzcomp; for example UTC timezone does this */
- if (!tzone || !icaltimezone_get_component (tzone))
- return FALSE;
-
- tzid = icaltimezone_get_tzid (tzone);
- if (!tzid)
- return FALSE;
-
- cmp = icalcomponent_as_ical_string_r (icaltimezone_get_component (tzone));
- zone = icaltimezone_new ();
-
- for (subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VTIMEZONE_COMPONENT);
- subcomp;
- subcomp = icalcomponent_get_next_component (icalcomp, ICAL_VTIMEZONE_COMPONENT)) {
- if (!icaltimezone_set_component (zone, icalcomponent_new_clone (subcomp))) {
- to_remove = g_slist_prepend (to_remove, subcomp);
- } else if (icaltimezone_get_tzid (zone) && g_str_equal (tzid, icaltimezone_get_tzid (zone))) {
- /* there is a timezone component with the same tzid already */
- if (have_same) {
- to_remove = g_slist_prepend (to_remove, subcomp);
- } else {
- gchar *str = icalcomponent_as_ical_string_r (subcomp);
-
- /* not the best way how to compare two components, but don't have better */
- if (str && g_str_equal (cmp, str)) {
- have_same = TRUE;
- add = FALSE;
- } else {
- to_remove = g_slist_prepend (to_remove, subcomp);
- }
-
- g_free (str);
- }
- }
- }
-
- g_free (cmp);
-
- for (r = to_remove; r; r = r->next) {
- icalcomponent_remove_component (icalcomp, r->data);
- }
-
- if (g_slist_length (to_remove) > 1) {
- /* there were more than once tzid as this,
- thus check for duplicities for all of timezones there */
- GHashTable *known = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- GSList *rem2 = NULL;
-
- for (subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VTIMEZONE_COMPONENT);
- subcomp;
- subcomp = icalcomponent_get_next_component (icalcomp, ICAL_VTIMEZONE_COMPONENT)) {
- if (!icaltimezone_set_component (zone, icalcomponent_new_clone (subcomp))) {
- rem2 = g_slist_prepend (rem2, subcomp);
- } else {
- const gchar *tzid2 = icaltimezone_get_tzid (zone);
-
- /* check all but not the one which was checked above */
- if (tzid2 && !g_str_equal (tzid, tzid2)) {
- if (g_hash_table_lookup (known, tzid2) == NULL) {
- /* the first component of this tzid, keep it */
- g_hash_table_insert (known, g_strdup (tzid2), GINT_TO_POINTER (1));
- } else {
- /* it's there already, remove it */
- rem2 = g_slist_prepend (rem2, subcomp);
- }
- }
- }
- }
-
- for (r = rem2; r; r = r->next) {
- icalcomponent_remove_component (icalcomp, r->data);
- }
-
- g_slist_free (rem2);
- g_hash_table_unref (known);
- }
-
- icaltimezone_free (zone, TRUE);
- g_slist_free (to_remove);
-
- if (add)
- icalcomponent_add_component (icalcomp, icalcomponent_new_clone (icaltimezone_get_component (tzone)));
-
- return add || to_remove != NULL;
-}
-
static void
source_changed_cb (ESource *source, ECalBackend *backend)
{
@@ -1334,8 +1228,7 @@ source_changed_cb (ESource *source, ECalBackend *backend)
/* Open handler for the file backend */
static void
-e_cal_backend_file_open (ECalBackendSync *backend, EDataCal *cal, gboolean only_if_exists,
- const gchar *username, const gchar *password, GError **perror)
+e_cal_backend_file_open (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gboolean only_if_exists, GError **perror)
{
ECalBackendFile *cbfile;
ECalBackendFilePrivate *priv;
@@ -1381,23 +1274,23 @@ e_cal_backend_file_open (ECalBackendSync *backend, EDataCal *cal, gboolean only_
priv->read_only = TRUE;
}
}
-
- if (priv->default_zone && add_timezone (priv->icalcomp, priv->default_zone)) {
- save (cbfile);
- }
}
g_free (str_uri);
done:
g_static_rec_mutex_unlock (&priv->idle_save_rmutex);
+ e_cal_backend_notify_readonly (E_CAL_BACKEND (backend), priv->read_only);
+ e_cal_backend_notify_online (E_CAL_BACKEND (backend), TRUE);
if (err)
- g_propagate_error (perror, err);
+ g_propagate_error (perror, g_error_copy (err));
+
+ e_cal_backend_notify_opened (E_CAL_BACKEND (backend), err);
}
static void
-e_cal_backend_file_remove (ECalBackendSync *backend, EDataCal *cal, GError **perror)
+e_cal_backend_file_remove (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **perror)
{
ECalBackendFile *cbfile;
ECalBackendFilePrivate *priv;
@@ -1441,6 +1334,11 @@ e_cal_backend_file_remove (ECalBackendSync *backend, EDataCal *cal, GError **per
full_path = NULL;
}
+ if (dir) {
+ g_dir_close (dir);
+ dir = NULL;
+ }
+
/* remove the directory itself */
if (g_rmdir (dirname) != 0) {
err = EDC_ERROR (OtherError);
@@ -1448,77 +1346,31 @@ e_cal_backend_file_remove (ECalBackendSync *backend, EDataCal *cal, GError **per
done:
if (dir) {
- g_dir_close (dir);
+ g_dir_close (dir);
+ dir = NULL;
}
- g_free (str_uri);
- g_free (dirname);
- g_free (full_path);
-
- g_static_rec_mutex_unlock (&priv->idle_save_rmutex);
/* lie here a bit, but otherwise the calendar will not be removed, even it should */
if (err) {
- g_print (G_STRLOC ": %s", err->message);
+ g_print (G_STRLOC ": %s on dir '%s' from uri '%s'\n", err->message, dirname, str_uri);
g_error_free (err);
}
- if (error)
- g_error_free (error);
-}
-
-/* is_loaded handler for the file backend */
-static gboolean
-e_cal_backend_file_is_loaded (ECalBackend *backend)
-{
- ECalBackendFile *cbfile;
- ECalBackendFilePrivate *priv;
-
- cbfile = E_CAL_BACKEND_FILE (backend);
- priv = cbfile->priv;
+ g_free (str_uri);
+ g_free (dirname);
+ g_free (full_path);
- return (priv->icalcomp != NULL);
-}
+ g_static_rec_mutex_unlock (&priv->idle_save_rmutex);
-/* is_remote handler for the file backend */
-static CalMode
-e_cal_backend_file_get_mode (ECalBackend *backend)
-{
- return CAL_MODE_LOCAL;
+ if (error)
+ g_error_free (error);
}
/* Set_mode handler for the file backend */
static void
-e_cal_backend_file_set_mode (ECalBackend *backend, CalMode mode)
-{
- e_cal_backend_notify_mode (backend, ModeNotSupported, Local);
-
-}
-
-static void
-e_cal_backend_file_get_default_object (ECalBackendSync *backend, EDataCal *cal, gchar **object, GError **perror)
+e_cal_backend_file_set_online (ECalBackend *backend, gboolean is_online)
{
- ECalComponent *comp;
-
- comp = e_cal_component_new ();
-
- switch (e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
- case ICAL_VEVENT_COMPONENT:
- e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
- break;
- case ICAL_VTODO_COMPONENT:
- e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
- break;
- case ICAL_VJOURNAL_COMPONENT:
- e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
- break;
- default:
- g_object_unref (comp);
- g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
- return;
- }
-
- *object = e_cal_component_get_as_string (comp);
- g_object_unref (comp);
+ e_cal_backend_notify_online (backend, TRUE);
}
static void
@@ -1534,7 +1386,7 @@ add_detached_recur_to_vcalendar (gpointer key, gpointer value, gpointer user_dat
/* Get_object_component handler for the file backend */
static void
-e_cal_backend_file_get_object (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *rid, gchar **object, GError **error)
+e_cal_backend_file_get_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **object, GError **error)
{
ECalBackendFile *cbfile;
ECalBackendFilePrivate *priv;
@@ -1614,7 +1466,7 @@ e_cal_backend_file_get_object (ECalBackendSync *backend, EDataCal *cal, const gc
/* Add_timezone handler for the file backend */
static void
-e_cal_backend_file_add_timezone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **error)
+e_cal_backend_file_add_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobj, GError **error)
{
icalcomponent *tz_comp;
ECalBackendFile *cbfile;
@@ -1651,46 +1503,12 @@ e_cal_backend_file_add_timezone (ECalBackendSync *backend, EDataCal *cal, const
}
}
-static void
-e_cal_backend_file_set_default_zone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **error)
-{
- icalcomponent *tz_comp;
- ECalBackendFile *cbfile;
- ECalBackendFilePrivate *priv;
- icaltimezone *zone;
-
- cbfile = (ECalBackendFile *) backend;
-
- e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_FILE (cbfile), InvalidArg);
- e_return_data_cal_error_if_fail (tzobj != NULL, InvalidArg);
-
- priv = cbfile->priv;
-
- tz_comp = icalparser_parse_string (tzobj);
- if (!tz_comp) {
- g_propagate_error (error, EDC_ERROR (InvalidObject));
- return;
- }
-
- zone = icaltimezone_new ();
- icaltimezone_set_component (zone, tz_comp);
-
- g_static_rec_mutex_lock (&priv->idle_save_rmutex);
- if (priv->default_zone != icaltimezone_get_utc_timezone ())
- icaltimezone_free (priv->default_zone, 1);
-
- /* Set the default timezone to it. */
- priv->default_zone = zone;
- g_static_rec_mutex_unlock (&priv->idle_save_rmutex);
-}
-
typedef struct {
- GList *obj_list;
+ GSList *obj_list;
gboolean search_needed;
const gchar *query;
ECalBackendSExp *obj_sexp;
ECalBackend *backend;
- icaltimezone *default_zone;
} MatchObjectData;
static void
@@ -1715,8 +1533,7 @@ match_object_sexp_to_component (gpointer value, gpointer data)
if ((!match_data->search_needed) ||
(e_cal_backend_sexp_match_comp (match_data->obj_sexp, comp, match_data->backend))) {
- match_data->obj_list = g_list_append (match_data->obj_list,
- e_cal_component_get_as_string (comp));
+ match_data->obj_list = g_slist_append (match_data->obj_list, e_cal_component_get_as_string (comp));
}
}
@@ -1728,8 +1545,7 @@ match_recurrence_sexp (gpointer key, gpointer value, gpointer data)
if ((!match_data->search_needed) ||
(e_cal_backend_sexp_match_comp (match_data->obj_sexp, comp, match_data->backend))) {
- match_data->obj_list = g_list_append (match_data->obj_list,
- e_cal_component_get_as_string (comp));
+ match_data->obj_list = g_slist_append (match_data->obj_list, e_cal_component_get_as_string (comp));
}
}
@@ -1742,8 +1558,7 @@ match_object_sexp (gpointer key, gpointer value, gpointer data)
if (obj_data->full_object) {
if ((!match_data->search_needed) ||
(e_cal_backend_sexp_match_comp (match_data->obj_sexp, obj_data->full_object, match_data->backend))) {
- match_data->obj_list = g_list_append (match_data->obj_list,
- e_cal_component_get_as_string (obj_data->full_object));
+ match_data->obj_list = g_slist_append (match_data->obj_list, e_cal_component_get_as_string (obj_data->full_object));
}
}
@@ -1755,7 +1570,7 @@ match_object_sexp (gpointer key, gpointer value, gpointer data)
/* Get_objects_in_range handler for the file backend */
static void
-e_cal_backend_file_get_object_list (ECalBackendSync *backend, EDataCal *cal, const gchar *sexp, GList **objects, GError **perror)
+e_cal_backend_file_get_object_list (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *sexp, GSList **objects, GError **perror)
{
ECalBackendFile *cbfile;
ECalBackendFilePrivate *priv;
@@ -1772,7 +1587,6 @@ e_cal_backend_file_get_object_list (ECalBackendSync *backend, EDataCal *cal, con
match_data.query = sexp;
match_data.obj_list = NULL;
match_data.backend = E_CAL_BACKEND (backend);
- match_data.default_zone = priv->default_zone;
if (!strcmp (sexp, "#t"))
match_data.search_needed = FALSE;
@@ -1814,17 +1628,124 @@ e_cal_backend_file_get_object_list (ECalBackendSync *backend, EDataCal *cal, con
g_object_unref (match_data.obj_sexp);
}
+static void
+add_attach_uris (GSList **attachment_uris, icalcomponent *icalcomp)
+{
+ icalproperty *prop;
+
+ g_return_if_fail (attachment_uris != NULL);
+ g_return_if_fail (icalcomp != NULL);
+
+ for (prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTACH_PROPERTY);
+ prop;
+ prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTACH_PROPERTY)) {
+ icalattach *attach = icalproperty_get_attach (prop);
+
+ if (attach && icalattach_get_is_url (attach)) {
+ const gchar *url;
+
+ url = icalattach_get_url (attach);
+ if (url) {
+ gsize buf_size;
+ gchar *buf;
+
+ buf_size = strlen (url);
+ buf = g_malloc0 (buf_size + 1);
+
+ icalvalue_decode_ical_string (url, buf, buf_size);
+
+ *attachment_uris = g_slist_prepend (*attachment_uris, g_strdup (buf));
+
+ g_free (buf);
+ }
+ }
+ }
+}
+
+static void
+add_detached_recur_attach_uris (gpointer key, gpointer value, gpointer user_data)
+{
+ ECalComponent *recurrence = value;
+ GSList **attachment_uris = user_data;
+
+ add_attach_uris (attachment_uris, e_cal_component_get_icalcomponent (recurrence));
+}
+
/* Gets the list of attachments */
static void
-e_cal_backend_file_get_attachment_list (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *rid, GSList **list, GError **perror)
+e_cal_backend_file_get_attachment_uris (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, GSList **attachment_uris, GError **error)
{
+ ECalBackendFile *cbfile;
+ ECalBackendFilePrivate *priv;
+ ECalBackendFileObject *obj_data;
+
+ cbfile = E_CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
+
+ e_return_data_cal_error_if_fail (priv->icalcomp != NULL, InvalidObject);
+ e_return_data_cal_error_if_fail (uid != NULL, ObjectNotFound);
+ e_return_data_cal_error_if_fail (attachment_uris != NULL, InvalidArg);
+ g_assert (priv->comp_uid_hash != NULL);
+
+ g_static_rec_mutex_lock (&priv->idle_save_rmutex);
+
+ obj_data = g_hash_table_lookup (priv->comp_uid_hash, uid);
+ if (!obj_data) {
+ g_static_rec_mutex_unlock (&priv->idle_save_rmutex);
+ g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+ return;
+ }
+
+ if (rid && *rid) {
+ ECalComponent *comp;
+
+ comp = g_hash_table_lookup (obj_data->recurrences, rid);
+ if (comp) {
+ add_attach_uris (attachment_uris, e_cal_component_get_icalcomponent (comp));
+ } else {
+ icalcomponent *icalcomp;
+ struct icaltimetype itt;
+
+ if (!obj_data->full_object) {
+ g_static_rec_mutex_unlock (&priv->idle_save_rmutex);
+ g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+ return;
+ }
+
+ itt = icaltime_from_string (rid);
+ icalcomp = e_cal_util_construct_instance (
+ e_cal_component_get_icalcomponent (obj_data->full_object),
+ itt);
+ if (!icalcomp) {
+ g_static_rec_mutex_unlock (&priv->idle_save_rmutex);
+ g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+ return;
+ }
+
+ add_attach_uris (attachment_uris, icalcomp);
- /* TODO implement the function */
+ icalcomponent_free (icalcomp);
+ }
+ } else {
+ if (g_hash_table_size (obj_data->recurrences) > 0) {
+ /* detached recurrences don't have full_object */
+ if (obj_data->full_object)
+ add_attach_uris (attachment_uris, e_cal_component_get_icalcomponent (obj_data->full_object));
+
+ /* add all detached recurrences */
+ g_hash_table_foreach (obj_data->recurrences, add_detached_recur_attach_uris, attachment_uris);
+ } else if (obj_data->full_object)
+ add_attach_uris (attachment_uris, e_cal_component_get_icalcomponent (obj_data->full_object));
+ }
+
+ *attachment_uris = g_slist_reverse (*attachment_uris);
+
+ g_static_rec_mutex_unlock (&priv->idle_save_rmutex);
}
/* get_query handler for the file backend */
static void
-e_cal_backend_file_start_query (ECalBackend *backend, EDataCalView *query)
+e_cal_backend_file_start_view (ECalBackend *backend, EDataCalView *query)
{
ECalBackendFile *cbfile;
ECalBackendFilePrivate *priv;
@@ -1842,7 +1763,6 @@ e_cal_backend_file_start_query (ECalBackend *backend, EDataCalView *query)
match_data.query = e_data_cal_view_get_text (query);
match_data.obj_list = NULL;
match_data.backend = backend;
- match_data.default_zone = priv->default_zone;
match_data.obj_sexp = e_data_cal_view_get_object_sexp (query);
if (!strcmp (match_data.query, "#t"))
@@ -1850,7 +1770,7 @@ e_cal_backend_file_start_query (ECalBackend *backend, EDataCalView *query)
if (!match_data.obj_sexp) {
GError *error = EDC_ERROR (InvalidQuery);
- e_data_cal_view_notify_done (query, error);
+ e_data_cal_view_notify_complete (query, error);
g_error_free (error);
return;
}
@@ -1887,11 +1807,11 @@ e_cal_backend_file_start_query (ECalBackend *backend, EDataCalView *query)
/* notify listeners of all objects */
if (match_data.obj_list) {
- e_data_cal_view_notify_objects_added (query, (const GList *) match_data.obj_list);
+ e_data_cal_view_notify_objects_added (query, match_data.obj_list);
/* free memory */
- g_list_foreach (match_data.obj_list, (GFunc) g_free, NULL);
- g_list_free (match_data.obj_list);
+ g_slist_foreach (match_data.obj_list, (GFunc) g_free, NULL);
+ g_slist_free (match_data.obj_list);
}
if (objs_occuring_in_tw) {
@@ -1900,7 +1820,7 @@ e_cal_backend_file_start_query (ECalBackend *backend, EDataCalView *query)
}
g_object_unref (match_data.obj_sexp);
- e_data_cal_view_notify_done (query, NULL /* Success */);
+ e_data_cal_view_notify_complete (query, NULL /* Success */);
}
static gboolean
@@ -2005,7 +1925,7 @@ create_user_free_busy (ECalBackendFile *cbfile, const gchar *address, const gcha
vfb,
resolve_tzid,
vcalendar_comp,
- priv->default_zone);
+ icaltimezone_get_utc_timezone ());
}
g_object_unref (obj_sexp);
@@ -2014,15 +1934,15 @@ create_user_free_busy (ECalBackendFile *cbfile, const gchar *address, const gcha
/* Get_free_busy handler for the file backend */
static void
-e_cal_backend_file_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GList *users,
- time_t start, time_t end, GList **freebusy, GError **error)
+e_cal_backend_file_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const GSList *users,
+ time_t start, time_t end, GSList **freebusy, GError **error)
{
ECalBackendFile *cbfile;
ECalBackendFilePrivate *priv;
gchar *address, *name;
icalcomponent *vfb;
gchar *calobj;
- GList *l;
+ const GSList *l;
cbfile = E_CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
@@ -2039,7 +1959,7 @@ e_cal_backend_file_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GList
if (e_cal_backend_mail_account_get_default (&address, &name)) {
vfb = create_user_free_busy (cbfile, address, name, start, end);
calobj = icalcomponent_as_ical_string_r (vfb);
- *freebusy = g_list_append (*freebusy, calobj);
+ *freebusy = g_slist_append (*freebusy, calobj);
icalcomponent_free (vfb);
g_free (address);
g_free (name);
@@ -2050,7 +1970,7 @@ e_cal_backend_file_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GList
if (e_cal_backend_mail_account_is_valid (address, &name)) {
vfb = create_user_free_busy (cbfile, address, name, start, end);
calobj = icalcomponent_as_ical_string_r (vfb);
- *freebusy = g_list_append (*freebusy, calobj);
+ *freebusy = g_slist_append (*freebusy, calobj);
icalcomponent_free (vfb);
g_free (name);
}
@@ -2060,145 +1980,6 @@ e_cal_backend_file_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GList
g_static_rec_mutex_unlock (&priv->idle_save_rmutex);
}
-typedef struct
-{
- ECalBackendFile *backend;
- icalcomponent_kind kind;
- GList *deletes;
- EXmlHash *ehash;
-} ECalBackendFileComputeChangesData;
-
-static gboolean
-e_cal_backend_file_compute_changes_foreach_key (const gchar *key, gpointer value, gpointer data)
-{
- ECalBackendFileComputeChangesData *be_data = data;
-
- if (!lookup_component (be_data->backend, key)) {
- ECalComponent *comp;
-
- comp = e_cal_component_new ();
- if (be_data->kind == ICAL_VTODO_COMPONENT)
- e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
- else
- e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
-
- e_cal_component_set_uid (comp, key);
- be_data->deletes = g_list_prepend (be_data->deletes, e_cal_component_get_as_string (comp));
-
- g_object_unref (comp);
- return TRUE;
- }
- return FALSE;
-}
-
-static void
-e_cal_backend_file_compute_changes (ECalBackendFile *cbfile, const gchar *change_id,
- GList **adds, GList **modifies, GList **deletes, GError **perror)
-{
- ECalBackendFilePrivate *priv;
- gchar *filename;
- EXmlHash *ehash;
- ECalBackendFileComputeChangesData be_data;
- GList *i;
- gchar *unescaped_uri;
-
- priv = cbfile->priv;
-
- /* FIXME Will this always work? */
- unescaped_uri = g_uri_unescape_string (priv->path, "");
- filename = g_strdup_printf ("%s-%s.db", unescaped_uri, change_id);
- g_free (unescaped_uri);
- if (!(ehash = e_xmlhash_new (filename))) {
- g_free (filename);
- g_propagate_error (perror, EDC_ERROR (OtherError));
- return;
- }
-
- g_free (filename);
-
- g_static_rec_mutex_lock (&priv->idle_save_rmutex);
-
- /* Calculate adds and modifies */
- for (i = priv->comp; i != NULL; i = i->next) {
- const gchar *uid;
- gchar *calobj;
-
- e_cal_component_get_uid (i->data, &uid);
- calobj = e_cal_component_get_as_string (i->data);
-
- g_assert (calobj != NULL);
-
- /* check what type of change has occurred, if any */
- switch (e_xmlhash_compare (ehash, uid, calobj)) {
- case E_XMLHASH_STATUS_SAME:
- break;
- case E_XMLHASH_STATUS_NOT_FOUND:
- *adds = g_list_prepend (*adds, g_strdup (calobj));
- e_xmlhash_add (ehash, uid, calobj);
- break;
- case E_XMLHASH_STATUS_DIFFERENT:
- *modifies = g_list_prepend (*modifies, g_strdup (calobj));
- e_xmlhash_add (ehash, uid, calobj);
- break;
- }
-
- g_free (calobj);
- }
-
- /* Calculate deletions */
- be_data.backend = cbfile;
- be_data.kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbfile));
- be_data.deletes = NULL;
- be_data.ehash = ehash;
-
- e_xmlhash_foreach_key_remove (ehash, (EXmlHashRemoveFunc) e_cal_backend_file_compute_changes_foreach_key, &be_data);
-
- *deletes = be_data.deletes;
-
- e_xmlhash_write (ehash);
- e_xmlhash_destroy (ehash);
-
- g_static_rec_mutex_unlock (&priv->idle_save_rmutex);
-}
-
-/* Get_changes handler for the file backend */
-static void
-e_cal_backend_file_get_changes (ECalBackendSync *backend, EDataCal *cal, const gchar *change_id,
- GList **adds, GList **modifies, GList **deletes, GError **error)
-{
- ECalBackendFile *cbfile;
- ECalBackendFilePrivate *priv;
-
- cbfile = E_CAL_BACKEND_FILE (backend);
- priv = cbfile->priv;
-
- e_return_data_cal_error_if_fail (priv->icalcomp != NULL, NoSuchCal);
- e_return_data_cal_error_if_fail (change_id != NULL, ObjectNotFound);
-
- e_cal_backend_file_compute_changes (cbfile, change_id, adds, modifies, deletes, error);
-}
-
-/* Discard_alarm handler for the file backend */
-static void
-e_cal_backend_file_discard_alarm (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *auid, GError **perror)
-{
- /* we just do nothing with the alarm */
-}
-
-static icaltimezone *
-e_cal_backend_file_internal_get_default_timezone (ECalBackend *backend)
-{
- ECalBackendFile *cbfile;
- ECalBackendFilePrivate *priv;
-
- cbfile = E_CAL_BACKEND_FILE (backend);
- priv = cbfile->priv;
-
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
-
- return priv->default_zone;
-}
-
static icaltimezone *
e_cal_backend_file_internal_get_timezone (ECalBackend *backend, const gchar *tzid)
{
@@ -2230,7 +2011,7 @@ static void
sanitize_component (ECalBackendFile *cbfile, ECalComponent *comp)
{
ECalComponentDateTime dt;
- icaltimezone *zone, *default_zone;
+ icaltimezone *zone;
/* Check dtstart, dtend and due's timezone, and convert it to local
* default timezone if the timezone is not in our builtin timezone
@@ -2239,9 +2020,8 @@ sanitize_component (ECalBackendFile *cbfile, ECalComponent *comp)
if (dt.value && dt.tzid) {
zone = e_cal_backend_file_internal_get_timezone ((ECalBackend *) cbfile, dt.tzid);
if (!zone) {
- default_zone = e_cal_backend_file_internal_get_default_timezone ((ECalBackend *) cbfile);
g_free ((gchar *) dt.tzid);
- dt.tzid = g_strdup (icaltimezone_get_tzid (default_zone));
+ dt.tzid = g_strdup ("UTC");
e_cal_component_set_dtstart (comp, &dt);
}
}
@@ -2251,9 +2031,8 @@ sanitize_component (ECalBackendFile *cbfile, ECalComponent *comp)
if (dt.value && dt.tzid) {
zone = e_cal_backend_file_internal_get_timezone ((ECalBackend *) cbfile, dt.tzid);
if (!zone) {
- default_zone = e_cal_backend_file_internal_get_default_timezone ((ECalBackend *) cbfile);
g_free ((gchar *) dt.tzid);
- dt.tzid = g_strdup (icaltimezone_get_tzid (default_zone));
+ dt.tzid = g_strdup ("UTC");
e_cal_component_set_dtend (comp, &dt);
}
}
@@ -2263,9 +2042,8 @@ sanitize_component (ECalBackendFile *cbfile, ECalComponent *comp)
if (dt.value && dt.tzid) {
zone = e_cal_backend_file_internal_get_timezone ((ECalBackend *) cbfile, dt.tzid);
if (!zone) {
- default_zone = e_cal_backend_file_internal_get_default_timezone ((ECalBackend *) cbfile);
g_free ((gchar *) dt.tzid);
- dt.tzid = g_strdup (icaltimezone_get_tzid (default_zone));
+ dt.tzid = g_strdup ("UTC");
e_cal_component_set_due (comp, &dt);
}
}
@@ -2275,7 +2053,7 @@ sanitize_component (ECalBackendFile *cbfile, ECalComponent *comp)
}
static void
-e_cal_backend_file_create_object (ECalBackendSync *backend, EDataCal *cal, gchar **calobj, gchar **uid, GError **error)
+e_cal_backend_file_create_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *in_calobj, gchar **uid, gchar **new_object, GError **error)
{
ECalBackendFile *cbfile;
ECalBackendFilePrivate *priv;
@@ -2288,10 +2066,11 @@ e_cal_backend_file_create_object (ECalBackendSync *backend, EDataCal *cal, gchar
priv = cbfile->priv;
e_return_data_cal_error_if_fail (priv->icalcomp != NULL, NoSuchCal);
- e_return_data_cal_error_if_fail (*calobj != NULL, ObjectNotFound);
+ e_return_data_cal_error_if_fail (in_calobj != NULL, ObjectNotFound);
+ e_return_data_cal_error_if_fail (new_object != NULL, ObjectNotFound);
/* Parse the icalendar text */
- icalcomp = icalparser_parse_string (*calobj);
+ icalcomp = icalparser_parse_string (in_calobj);
if (!icalcomp) {
g_propagate_error (error, EDC_ERROR (InvalidObject));
return;
@@ -2354,7 +2133,7 @@ e_cal_backend_file_create_object (ECalBackendSync *backend, EDataCal *cal, gchar
/* Return the UID and the modified component */
if (uid)
*uid = g_strdup (comp_uid);
- *calobj = e_cal_component_get_as_string (comp);
+ *new_object = e_cal_component_get_as_string (comp);
g_static_rec_mutex_unlock (&priv->idle_save_rmutex);
}
@@ -2394,7 +2173,7 @@ remove_object_instance_cb (gpointer key, gpointer value, gpointer user_data)
}
static void
-e_cal_backend_file_modify_object (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj,
+e_cal_backend_file_modify_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj,
CalObjModType mod, gchar **old_object, gchar **new_object, GError **error)
{
RemoveRecurrenceData rrdata;
@@ -2692,7 +2471,7 @@ get_object_string_from_fileobject (ECalBackendFileObject *obj_data, const gchar
/* Remove_object handler for the file backend */
static void
-e_cal_backend_file_remove_object (ECalBackendSync *backend, EDataCal *cal,
+e_cal_backend_file_remove_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable,
const gchar *uid, const gchar *rid,
CalObjModType mod, gchar **old_object,
gchar **object, GError **error)
@@ -2921,7 +2700,7 @@ fetch_attachments (ECalBackendSync *backend, ECalComponent *comp)
/* Update_objects handler for the file backend. */
static void
-e_cal_backend_file_receive_objects (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, GError **error)
+e_cal_backend_file_receive_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GError **error)
{
ECalBackendFile *cbfile;
ECalBackendFilePrivate *priv;
@@ -3185,7 +2964,7 @@ e_cal_backend_file_receive_objects (ECalBackendSync *backend, EDataCal *cal, con
}
static void
-e_cal_backend_file_send_objects (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, GList **users,
+e_cal_backend_file_send_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GSList **users,
gchar **modified_calobj, GError **perror)
{
*users = NULL;
@@ -3214,9 +2993,6 @@ e_cal_backend_file_init (ECalBackendFile *cbfile)
priv->custom_file = NULL;
priv->refresh_lock = g_mutex_new ();
- /* The timezone defaults to UTC. */
- priv->default_zone = icaltimezone_get_utc_timezone ();
-
/*
* data access is serialized via idle_save_rmutex, so locking at the
* backend method level is not needed
@@ -3297,35 +3073,23 @@ e_cal_backend_file_class_init (ECalBackendFileClass *class)
object_class->finalize = e_cal_backend_file_finalize;
object_class->constructed = cal_backend_file_constructed;
- sync_class->is_read_only_sync = e_cal_backend_file_is_read_only;
- sync_class->get_cal_address_sync = e_cal_backend_file_get_cal_address;
- sync_class->get_alarm_email_address_sync = e_cal_backend_file_get_alarm_email_address;
- sync_class->get_ldap_attribute_sync = e_cal_backend_file_get_ldap_attribute;
- sync_class->get_static_capabilities_sync = e_cal_backend_file_get_static_capabilities;
- sync_class->open_sync = e_cal_backend_file_open;
- sync_class->remove_sync = e_cal_backend_file_remove;
- sync_class->create_object_sync = e_cal_backend_file_create_object;
- sync_class->modify_object_sync = e_cal_backend_file_modify_object;
- sync_class->remove_object_sync = e_cal_backend_file_remove_object;
- sync_class->discard_alarm_sync = e_cal_backend_file_discard_alarm;
- sync_class->receive_objects_sync = e_cal_backend_file_receive_objects;
- sync_class->send_objects_sync = e_cal_backend_file_send_objects;
- sync_class->get_default_object_sync = e_cal_backend_file_get_default_object;
- sync_class->get_object_sync = e_cal_backend_file_get_object;
- sync_class->get_object_list_sync = e_cal_backend_file_get_object_list;
- sync_class->get_attachment_list_sync = e_cal_backend_file_get_attachment_list;
- sync_class->add_timezone_sync = e_cal_backend_file_add_timezone;
- sync_class->set_default_zone_sync = e_cal_backend_file_set_default_zone;
- sync_class->get_freebusy_sync = e_cal_backend_file_get_free_busy;
- sync_class->get_changes_sync = e_cal_backend_file_get_changes;
-
- backend_class->is_loaded = e_cal_backend_file_is_loaded;
- backend_class->start_query = e_cal_backend_file_start_query;
- backend_class->get_mode = e_cal_backend_file_get_mode;
- backend_class->set_mode = e_cal_backend_file_set_mode;
-
- backend_class->internal_get_default_timezone = e_cal_backend_file_internal_get_default_timezone;
- backend_class->internal_get_timezone = e_cal_backend_file_internal_get_timezone;
+ sync_class->get_backend_property_sync = e_cal_backend_file_get_backend_property;
+ sync_class->open_sync = e_cal_backend_file_open;
+ sync_class->remove_sync = e_cal_backend_file_remove;
+ sync_class->create_object_sync = e_cal_backend_file_create_object;
+ sync_class->modify_object_sync = e_cal_backend_file_modify_object;
+ sync_class->remove_object_sync = e_cal_backend_file_remove_object;
+ sync_class->receive_objects_sync = e_cal_backend_file_receive_objects;
+ sync_class->send_objects_sync = e_cal_backend_file_send_objects;
+ sync_class->get_object_sync = e_cal_backend_file_get_object;
+ sync_class->get_object_list_sync = e_cal_backend_file_get_object_list;
+ sync_class->get_attachment_uris_sync = e_cal_backend_file_get_attachment_uris;
+ sync_class->add_timezone_sync = e_cal_backend_file_add_timezone;
+ sync_class->get_free_busy_sync = e_cal_backend_file_get_free_busy;
+
+ backend_class->start_view = e_cal_backend_file_start_view;
+ backend_class->set_online = e_cal_backend_file_set_online;
+ backend_class->internal_get_timezone = e_cal_backend_file_internal_get_timezone;
}
void
@@ -3395,6 +3159,7 @@ e_cal_backend_file_reload (ECalBackendFile *cbfile, GError **perror)
}
done:
g_static_rec_mutex_unlock (&priv->idle_save_rmutex);
+ e_cal_backend_notify_readonly (E_CAL_BACKEND (cbfile), cbfile->priv->read_only);
if (err)
g_propagate_error (perror, err);
@@ -3404,7 +3169,7 @@ e_cal_backend_file_reload (ECalBackendFile *cbfile, GError **perror)
#include <glib.h>
static void
-test_query_by_scanning_all_objects (ECalBackendFile* cbfile, const gchar *sexp, GList **objects)
+test_query_by_scanning_all_objects (ECalBackendFile* cbfile, const gchar *sexp, GSList **objects)
{
MatchObjectData match_data;
ECalBackendFilePrivate *priv;
@@ -3414,7 +3179,6 @@ test_query_by_scanning_all_objects (ECalBackendFile* cbfile, const gchar *sexp,
match_data.search_needed = TRUE;
match_data.query = sexp;
match_data.obj_list = NULL;
- match_data.default_zone = priv->default_zone;
match_data.backend = E_CAL_BACKEND (cbfile);
if (!strcmp (sexp, "#t"))
@@ -3443,9 +3207,9 @@ test_query_by_scanning_all_objects (ECalBackendFile* cbfile, const gchar *sexp,
}
static void
-write_list (GList* list)
+write_list (GSList* list)
{
- GList *l;
+ GSList *l;
for (l = list; l; l = l->next)
{
@@ -3458,9 +3222,9 @@ write_list (GList* list)
}
static void
-get_difference_of_lists (ECalBackendFile* cbfile, GList* smaller, GList* bigger)
+get_difference_of_lists (ECalBackendFile* cbfile, GSList* smaller, GSList* bigger)
{
- GList *l, *lsmaller;
+ GSList *l, *lsmaller;
for (l = bigger; l; l = l->next) {
gchar *str = l->data;
@@ -3488,7 +3252,7 @@ get_difference_of_lists (ECalBackendFile* cbfile, GList* smaller, GList* bigger)
e_cal_util_get_component_occur_times (comp, &time_start, &time_end,
resolve_tzid, cbfile->priv->icalcomp,
- cbfile->priv->default_zone,
+ icaltimezone_get_utc_timezone (),
e_cal_backend_get_kind (E_CAL_BACKEND (cbfile)));
d (printf ("start %s\n", asctime(gmtime(&time_start))));
@@ -3502,27 +3266,27 @@ get_difference_of_lists (ECalBackendFile* cbfile, GList* smaller, GList* bigger)
static void
test_query (ECalBackendFile* cbfile, const gchar * query)
{
- GList *objects = NULL, *all_objects = NULL;
+ GSList *objects = NULL, *all_objects = NULL;
g_return_if_fail (query != NULL);
d (g_print ("Query %s\n", query));
test_query_by_scanning_all_objects (cbfile, query, &all_objects);
- e_cal_backend_file_get_object_list (E_CAL_BACKEND_SYNC (cbfile), NULL, query, &objects, NULL);
+ e_cal_backend_file_get_object_list (E_CAL_BACKEND_SYNC (cbfile), NULL, NULL, query, &objects, NULL);
if (objects == NULL)
{
g_message (G_STRLOC " failed to get objects\n");
exit (0);
}
- if (g_list_length (objects) < g_list_length (all_objects) )
+ if (g_slist_length (objects) < g_slist_length (all_objects) )
{
g_print ("ERROR\n");
get_difference_of_lists (cbfile, objects, all_objects);
exit (-1);
}
- else if (g_list_length (objects) > g_list_length (all_objects) )
+ else if (g_slist_length (objects) > g_slist_length (all_objects) )
{
g_print ("ERROR\n");
write_list (all_objects);
@@ -3530,29 +3294,29 @@ test_query (ECalBackendFile* cbfile, const gchar * query)
exit (-1);
}
- g_list_foreach (objects, (GFunc) g_free, NULL);
- g_list_free (objects);
- g_list_foreach (all_objects, (GFunc) g_free, NULL);
- g_list_free (all_objects);
+ g_slist_foreach (objects, (GFunc) g_free, NULL);
+ g_slist_free (objects);
+ g_slist_foreach (all_objects, (GFunc) g_free, NULL);
+ g_slist_free (all_objects);
}
static void
execute_query (ECalBackendFile* cbfile, const gchar * query)
{
- GList *objects = NULL;
+ GSList *objects = NULL;
g_return_if_fail (query != NULL);
d (g_print ("Query %s\n", query));
- e_cal_backend_file_get_object_list (E_CAL_BACKEND_SYNC (cbfile), NULL, query, &objects, NULL);
+ e_cal_backend_file_get_object_list (E_CAL_BACKEND_SYNC (cbfile), NULL, NULL, query, &objects, NULL);
if (objects == NULL)
{
g_message (G_STRLOC " failed to get objects\n");
exit (0);
}
- g_list_foreach (objects, (GFunc) g_free, NULL);
- g_list_free (objects);
+ g_slist_foreach (objects, (GFunc) g_free, NULL);
+ g_slist_free (objects);
}
static gchar *fname = NULL;
@@ -3700,4 +3464,3 @@ err0:
return 0;
}
#endif
-
diff --git a/calendar/backends/http/e-cal-backend-http.c b/calendar/backends/http/e-cal-backend-http.c
index 7bf25e7..e468a39 100644
--- a/calendar/backends/http/e-cal-backend-http.c
+++ b/calendar/backends/http/e-cal-backend-http.c
@@ -54,18 +54,11 @@ struct _ECalBackendHttpPrivate {
gchar *uri;
/* Local/remote mode */
- CalMode mode;
+ gboolean is_online;
/* The file cache */
ECalBackendStore *store;
- /* The calendar's default timezone, used for resolving DATE and
- floating DATE-TIME values. */
- icaltimezone *default_zone;
-
- /* The list of live queries */
- GList *queries;
-
/* Soup handles for remote file */
SoupSession *soup_session;
@@ -75,9 +68,9 @@ struct _ECalBackendHttpPrivate {
/* Flags */
gboolean opened;
+ gboolean requires_auth;
- gchar *username;
- gchar *password;
+ ECredentials *credentials;
};
@@ -87,7 +80,7 @@ struct _ECalBackendHttpPrivate {
static void e_cal_backend_http_dispose (GObject *object);
static void e_cal_backend_http_finalize (GObject *object);
static gboolean begin_retrieval_cb (ECalBackendHttp *cbhttp);
-static void e_cal_backend_http_add_timezone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **perror);
+static void e_cal_backend_http_add_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobj, GError **perror);
static ECalBackendSyncClass *parent_class;
@@ -103,10 +96,8 @@ e_cal_backend_http_dispose (GObject *object)
cbhttp = E_CAL_BACKEND_HTTP (object);
priv = cbhttp->priv;
- g_free (priv->username);
- g_free (priv->password);
- priv->username = NULL;
- priv->password = NULL;
+ e_credentials_free (priv->credentials);
+ priv->credentials = NULL;
if (priv->source_changed_id) {
g_signal_handler_disconnect (e_cal_backend_get_source (E_CAL_BACKEND (cbhttp)), priv->source_changed_id);
@@ -142,11 +133,6 @@ e_cal_backend_http_finalize (GObject *object)
priv->uri = NULL;
}
- if (priv->default_zone) {
- icaltimezone_free (priv->default_zone, 1);
- priv->default_zone = NULL;
- }
-
if (priv->soup_session) {
soup_session_abort (priv->soup_session);
g_object_unref (priv->soup_session);
@@ -169,45 +155,36 @@ e_cal_backend_http_finalize (GObject *object)
/* Calendar backend methods */
-/* Is_read_only handler for the file backend */
-static void
-e_cal_backend_http_is_read_only (ECalBackendSync *backend, EDataCal *cal, gboolean *read_only, GError **perror)
-{
- *read_only = TRUE;
-}
-
-/* Get_email_address handler for the file backend */
-static void
-e_cal_backend_http_get_cal_address (ECalBackendSync *backend, EDataCal *cal, gchar **address, GError **perror)
-{
- /* A HTTP backend has no particular email address associated
- * with it (although that would be a useful feature some day).
- */
- *address = NULL;
-}
-
-static void
-e_cal_backend_http_get_ldap_attribute (ECalBackendSync *backend, EDataCal *cal, gchar **attribute, GError **perror)
-{
- *attribute = NULL;
-}
-
-static void
-e_cal_backend_http_get_alarm_email_address (ECalBackendSync *backend, EDataCal *cal, gchar **address, GError **perror)
+static gboolean
+e_cal_backend_http_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **perror)
{
- /* A HTTP backend has no particular email address associated
- * with it (although that would be a useful feature some day).
- */
- *address = NULL;
-}
+ gboolean processed = TRUE;
+
+ g_return_val_if_fail (prop_name != NULL, FALSE);
+ g_return_val_if_fail (prop_value != NULL, FALSE);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ *prop_value = g_strdup (CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS ","
+ CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED);
+ } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+ g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+ /* A HTTP backend has no particular email address associated
+ * with it (although that would be a useful feature some day).
+ */
+ *prop_value = NULL;
+ } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+ icalcomponent *icalcomp;
+ icalcomponent_kind kind;
+
+ kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend));
+ icalcomp = e_cal_util_new_component (kind);
+ *prop_value = icalcomponent_as_ical_string_r (icalcomp);
+ icalcomponent_free (icalcomp);
+ } else {
+ processed = FALSE;
+ }
-static void
-e_cal_backend_http_get_static_capabilities (ECalBackendSync *backend, EDataCal *cal, gchar **capabilities, GError **perror)
-{
- *capabilities = g_strdup (
- CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS ","
- CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED
- );
+ return processed;
}
static gchar *
@@ -346,6 +323,11 @@ put_component_to_store (ECalBackendHttp *cb,
changed = (sequence1 != NULL && sequence2 == NULL) ||
(sequence1 == NULL && sequence2 != NULL) ||
(sequence1 != NULL && sequence2 != NULL && *sequence1 != *sequence2);
+
+ if (sequence1)
+ e_cal_component_free_sequence (sequence1);
+ if (sequence2)
+ e_cal_component_free_sequence (sequence2);
}
}
@@ -356,7 +338,7 @@ put_component_to_store (ECalBackendHttp *cb,
}
e_cal_util_get_component_occur_times (comp, &time_start, &time_end,
- resolve_tzid, cb, priv->default_zone,
+ resolve_tzid, cb, icaltimezone_get_utc_timezone (),
e_cal_backend_get_kind (E_CAL_BACKEND (cb)));
e_cal_backend_store_put_component_with_time_range (priv->store, comp, time_start, time_end);
@@ -430,9 +412,14 @@ retrieval_done (SoupSession *session, SoupMessage *msg, ECalBackendHttp *cbhttp)
/* check status code */
if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
if (!priv->opened) {
- e_cal_backend_notify_error (E_CAL_BACKEND (cbhttp),
- msg->reason_phrase && *msg->reason_phrase ? msg->reason_phrase :
- (soup_status_get_phrase (msg->status_code) ? soup_status_get_phrase (msg->status_code) : _("Unknown error")));
+ if (msg->status_code == 401 || msg->status_code == 403) {
+ priv->requires_auth = TRUE;
+ e_cal_backend_notify_auth_required (E_CAL_BACKEND (cbhttp), TRUE, priv->credentials);
+ return;
+ } else
+ e_cal_backend_notify_error (E_CAL_BACKEND (cbhttp),
+ msg->reason_phrase && *msg->reason_phrase ? msg->reason_phrase :
+ (soup_status_get_phrase (msg->status_code) ? soup_status_get_phrase (msg->status_code) : _("Unknown error")));
}
empty_cache (cbhttp);
@@ -564,11 +551,10 @@ soup_authenticate (SoupSession *session,
cbhttp = E_CAL_BACKEND_HTTP (data);
priv = cbhttp->priv;
- soup_auth_authenticate (auth, priv->username, priv->password);
-
- priv->username = NULL;
- priv->password = NULL;
-
+ if (!retrying && priv->credentials && e_credentials_has_key (priv->credentials, E_CREDENTIALS_KEY_USERNAME)) {
+ soup_auth_authenticate (auth, e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_USERNAME), e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_PASSWORD));
+ e_credentials_clear_peek (priv->credentials);
+ }
}
static gboolean reload_cb (ECalBackendHttp *cbhttp);
@@ -582,7 +568,7 @@ begin_retrieval_cb (ECalBackendHttp *cbhttp)
priv = cbhttp->priv;
- if (priv->mode != CAL_MODE_REMOTE)
+ if (!priv->is_online)
return FALSE;
maybe_start_reload_timeout (cbhttp);
@@ -733,8 +719,7 @@ source_changed_cb (ESource *source, ECalBackendHttp *cbhttp)
/* Open handler for the file backend */
static void
-e_cal_backend_http_open (ECalBackendSync *backend, EDataCal *cal, gboolean only_if_exists,
- const gchar *username, const gchar *password, GError **perror)
+e_cal_backend_http_open (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gboolean only_if_exists, GError **perror)
{
ECalBackendHttp *cbhttp;
ECalBackendHttpPrivate *priv;
@@ -745,8 +730,10 @@ e_cal_backend_http_open (ECalBackendSync *backend, EDataCal *cal, gboolean only_
priv = cbhttp->priv;
/* already opened, thus can skip all this initialization */
- if (priv->opened)
+ if (priv->opened) {
+ e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
return;
+ }
source = e_cal_backend_get_source (E_CAL_BACKEND (backend));
@@ -759,16 +746,6 @@ e_cal_backend_http_open (ECalBackendSync *backend, EDataCal *cal, gboolean only_
priv->uri = NULL;
g_free (tmp);
- if (e_source_get_property (source, "auth") != NULL) {
- if ((username == NULL || password == NULL)) {
- g_propagate_error (perror, EDC_ERROR (AuthenticationRequired));
- return;
- }
-
- priv->username = g_strdup (username);
- priv->password = g_strdup (password);
- }
-
if (!priv->store) {
const gchar *cache_dir;
@@ -781,20 +758,58 @@ e_cal_backend_http_open (ECalBackendSync *backend, EDataCal *cal, gboolean only_
if (!priv->store) {
g_propagate_error (perror, EDC_ERROR_EX (OtherError, _("Could not create cache file")));
+ e_cal_backend_notify_opened (E_CAL_BACKEND (backend), EDC_ERROR_EX (OtherError, _("Could not create cache file")));
return;
}
+ }
+
+ e_cal_backend_notify_readonly (E_CAL_BACKEND (backend), TRUE);
+ e_cal_backend_notify_online (E_CAL_BACKEND (backend), priv->is_online);
- if (priv->default_zone) {
- e_cal_backend_store_set_default_timezone (priv->store, priv->default_zone);
+ if (priv->is_online) {
+ if (e_source_get_property (source, "auth")) {
+ e_cal_backend_notify_auth_required (E_CAL_BACKEND (cbhttp), TRUE, priv->credentials);
+ } else if (priv->requires_auth && perror && !*perror) {
+ g_propagate_error (perror, EDC_ERROR (AuthenticationRequired));
+ e_cal_backend_notify_opened (E_CAL_BACKEND (backend), EDC_ERROR (AuthenticationRequired));
+ } else {
+ e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
+ g_idle_add ((GSourceFunc) begin_retrieval_cb, cbhttp);
}
+ } else {
+ e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
+ }
+}
+
+static void
+e_cal_backend_http_authenticate_user (ECalBackendSync *backend, GCancellable *cancellable, ECredentials *credentials, GError **error)
+{
+ ECalBackendHttp *cbhttp;
+ ECalBackendHttpPrivate *priv;
+
+ cbhttp = E_CAL_BACKEND_HTTP (backend);
+ priv = cbhttp->priv;
+
+ if (priv->credentials && credentials && e_credentials_equal_keys (priv->credentials, credentials, E_CREDENTIALS_KEY_USERNAME, E_CREDENTIALS_KEY_PASSWORD, NULL)) {
+ g_propagate_error (error, EDC_ERROR (AuthenticationRequired));
+ return;
}
- if (priv->mode != CAL_MODE_LOCAL)
- g_idle_add ((GSourceFunc) begin_retrieval_cb, cbhttp);
+ e_credentials_free (priv->credentials);
+ priv->credentials = NULL;
+
+ if (!credentials || !e_credentials_has_key (credentials, E_CREDENTIALS_KEY_USERNAME)) {
+ g_propagate_error (error, EDC_ERROR (AuthenticationRequired));
+ return;
+ }
+
+ priv->credentials = e_credentials_new_clone (credentials);
+
+ g_idle_add ((GSourceFunc) begin_retrieval_cb, cbhttp);
}
static void
-e_cal_backend_http_refresh (ECalBackendSync *backend, EDataCal *cal, GError **perror)
+e_cal_backend_http_refresh (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **perror)
{
ECalBackendHttp *cbhttp;
ECalBackendHttpPrivate *priv;
@@ -815,7 +830,7 @@ e_cal_backend_http_refresh (ECalBackendSync *backend, EDataCal *cal, GError **pe
}
static void
-e_cal_backend_http_remove (ECalBackendSync *backend, EDataCal *cal, GError **perror)
+e_cal_backend_http_remove (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **perror)
{
ECalBackendHttp *cbhttp;
ECalBackendHttpPrivate *priv;
@@ -829,106 +844,39 @@ e_cal_backend_http_remove (ECalBackendSync *backend, EDataCal *cal, GError **per
e_cal_backend_store_remove (priv->store);
}
-/* is_loaded handler for the file backend */
-static gboolean
-e_cal_backend_http_is_loaded (ECalBackend *backend)
-{
- ECalBackendHttp *cbhttp;
- ECalBackendHttpPrivate *priv;
-
- cbhttp = E_CAL_BACKEND_HTTP (backend);
- priv = cbhttp->priv;
-
- if (!priv->store)
- return FALSE;
-
- return TRUE;
-}
-
-/* is_remote handler for the http backend */
-static CalMode
-e_cal_backend_http_get_mode (ECalBackend *backend)
-{
- ECalBackendHttp *cbhttp;
- ECalBackendHttpPrivate *priv;
-
- cbhttp = E_CAL_BACKEND_HTTP (backend);
- priv = cbhttp->priv;
-
- return priv->mode;
-}
-
/* Set_mode handler for the http backend */
static void
-e_cal_backend_http_set_mode (ECalBackend *backend, CalMode mode)
+e_cal_backend_http_set_online (ECalBackend *backend, gboolean is_online)
{
ECalBackendHttp *cbhttp;
ECalBackendHttpPrivate *priv;
- EDataCalMode set_mode;
gboolean loaded;
cbhttp = E_CAL_BACKEND_HTTP (backend);
priv = cbhttp->priv;
- loaded = e_cal_backend_http_is_loaded (backend);
+ loaded = e_cal_backend_is_opened (backend);
- if (priv->mode != mode) {
- switch (mode) {
- case CAL_MODE_LOCAL:
- priv->mode = mode;
- set_mode = cal_mode_to_corba (mode);
- if (loaded && priv->reload_timeout_id) {
- g_source_remove (priv->reload_timeout_id);
- priv->reload_timeout_id = 0;
- }
- break;
- case CAL_MODE_REMOTE:
- case CAL_MODE_ANY:
- priv->mode = mode;
- set_mode = cal_mode_to_corba (mode);
- if (loaded)
- g_idle_add ((GSourceFunc) begin_retrieval_cb, backend);
- break;
-
- priv->mode = CAL_MODE_REMOTE;
- set_mode = Remote;
- break;
- default:
- set_mode = AnyMode;
- break;
+ if ((priv->is_online ? 1 : 0) != (is_online ? 1 : 0)) {
+ priv->is_online = is_online;
+ if (!priv->is_online) {
+ if (loaded && priv->reload_timeout_id) {
+ g_source_remove (priv->reload_timeout_id);
+ priv->reload_timeout_id = 0;
+ }
+ } else {
+ if (loaded)
+ g_idle_add ((GSourceFunc) begin_retrieval_cb, backend);
}
- } else {
- set_mode = cal_mode_to_corba (priv->mode);
}
- if (loaded) {
-
- if (set_mode == AnyMode)
- e_cal_backend_notify_mode (backend,
- ModeNotSupported,
- cal_mode_to_corba (priv->mode));
- else
- e_cal_backend_notify_mode (backend,
- ModeSet,
- set_mode);
- }
-}
-
-static void
-e_cal_backend_http_get_default_object (ECalBackendSync *backend, EDataCal *cal, gchar **object, GError **perror)
-{
- icalcomponent *icalcomp;
- icalcomponent_kind kind;
-
- kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend));
- icalcomp = e_cal_util_new_component (kind);
- *object = icalcomponent_as_ical_string_r (icalcomp);
- icalcomponent_free (icalcomp);
+ if (loaded)
+ e_cal_backend_notify_online (backend, priv->is_online);
}
/* Get_object_component handler for the http backend */
static void
-e_cal_backend_http_get_object (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *rid, gchar **object, GError **error)
+e_cal_backend_http_get_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **object, GError **error)
{
ECalBackendHttp *cbhttp;
ECalBackendHttpPrivate *priv;
@@ -956,7 +904,7 @@ e_cal_backend_http_get_object (ECalBackendSync *backend, EDataCal *cal, const gc
/* Add_timezone handler for the file backend */
static void
-e_cal_backend_http_add_timezone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **error)
+e_cal_backend_http_add_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobj, GError **error)
{
ECalBackendHttp *cbhttp;
ECalBackendHttpPrivate *priv;
@@ -987,40 +935,9 @@ e_cal_backend_http_add_timezone (ECalBackendSync *backend, EDataCal *cal, const
e_cal_backend_store_put_timezone (priv->store, zone);
}
-static void
-e_cal_backend_http_set_default_zone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **error)
-{
- icalcomponent *tz_comp;
- ECalBackendHttp *cbhttp;
- ECalBackendHttpPrivate *priv;
- icaltimezone *zone;
-
- cbhttp = (ECalBackendHttp *) backend;
-
- e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_HTTP (cbhttp), InvalidArg);
- e_return_data_cal_error_if_fail (tzobj != NULL, InvalidArg);
-
- priv = cbhttp->priv;
-
- tz_comp = icalparser_parse_string (tzobj);
- if (!tz_comp) {
- g_propagate_error (error, EDC_ERROR (InvalidObject));
- return;
- }
-
- zone = icaltimezone_new ();
- icaltimezone_set_component (zone, tz_comp);
-
- if (priv->default_zone)
- icaltimezone_free (priv->default_zone, 1);
-
- /* Set the default timezone to it. */
- priv->default_zone = zone;
-}
-
/* Get_objects_in_range handler for the file backend */
static void
-e_cal_backend_http_get_object_list (ECalBackendSync *backend, EDataCal *cal, const gchar *sexp, GList **objects, GError **perror)
+e_cal_backend_http_get_object_list (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *sexp, GSList **objects, GError **perror)
{
ECalBackendHttp *cbhttp;
ECalBackendHttpPrivate *priv;
@@ -1051,7 +968,7 @@ e_cal_backend_http_get_object_list (ECalBackendSync *backend, EDataCal *cal, con
for (l = components; l != NULL; l = g_slist_next (l)) {
if (e_cal_backend_sexp_match_comp (cbsexp, E_CAL_COMPONENT (l->data), E_CAL_BACKEND (backend))) {
- *objects = g_list_append (*objects, e_cal_component_get_as_string (l->data));
+ *objects = g_slist_append (*objects, e_cal_component_get_as_string (l->data));
}
}
@@ -1060,14 +977,13 @@ e_cal_backend_http_get_object_list (ECalBackendSync *backend, EDataCal *cal, con
g_object_unref (cbsexp);
}
-/* get_query handler for the file backend */
static void
-e_cal_backend_http_start_query (ECalBackend *backend, EDataCalView *query)
+e_cal_backend_http_start_view (ECalBackend *backend, EDataCalView *query)
{
ECalBackendHttp *cbhttp;
ECalBackendHttpPrivate *priv;
GSList *components, *l;
- GList *objects = NULL;
+ GSList *objects = NULL;
ECalBackendSExp *cbsexp;
time_t occur_start = -1, occur_end = -1;
gboolean prunning_by_time;
@@ -1079,7 +995,7 @@ e_cal_backend_http_start_query (ECalBackend *backend, EDataCalView *query)
if (!priv->store) {
GError *error = EDC_ERROR (NoSuchCal);
- e_data_cal_view_notify_done (query, error);
+ e_data_cal_view_notify_complete (query, error);
g_error_free (error);
return;
}
@@ -1098,19 +1014,19 @@ e_cal_backend_http_start_query (ECalBackend *backend, EDataCalView *query)
for (l = components; l != NULL; l = g_slist_next (l)) {
if (e_cal_backend_sexp_match_comp (cbsexp, E_CAL_COMPONENT (l->data), E_CAL_BACKEND (backend))) {
- objects = g_list_append (objects, e_cal_component_get_as_string (l->data));
+ objects = g_slist_append (objects, e_cal_component_get_as_string (l->data));
}
}
- e_data_cal_view_notify_objects_added (query, (const GList *) objects);
+ e_data_cal_view_notify_objects_added (query, objects);
g_slist_foreach (components, (GFunc) g_object_unref, NULL);
g_slist_free (components);
- g_list_foreach (objects, (GFunc) g_free, NULL);
- g_list_free (objects);
+ g_slist_foreach (objects, (GFunc) g_free, NULL);
+ g_slist_free (objects);
g_object_unref (cbsexp);
- e_data_cal_view_notify_done (query, NULL /* Success */);
+ e_data_cal_view_notify_complete (query, NULL /* Success */);
}
/***** static icaltimezone *
@@ -1236,7 +1152,7 @@ create_user_free_busy (ECalBackendHttp *cbhttp, const gchar *address, const gcha
vfb,
resolve_tzid,
vcalendar_comp,
- (icaltimezone *) e_cal_backend_store_get_default_timezone (store));
+ icaltimezone_get_utc_timezone ());
}
g_object_unref (obj_sexp);
@@ -1245,8 +1161,8 @@ create_user_free_busy (ECalBackendHttp *cbhttp, const gchar *address, const gcha
/* Get_free_busy handler for the file backend */
static void
-e_cal_backend_http_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GList *users,
- time_t start, time_t end, GList **freebusy, GError **error)
+e_cal_backend_http_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const GSList *users,
+ time_t start, time_t end, GSList **freebusy, GError **error)
{
ECalBackendHttp *cbhttp;
ECalBackendHttpPrivate *priv;
@@ -1269,19 +1185,19 @@ e_cal_backend_http_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GList
if (e_cal_backend_mail_account_get_default (&address, &name)) {
vfb = create_user_free_busy (cbhttp, address, name, start, end);
calobj = icalcomponent_as_ical_string_r (vfb);
- *freebusy = g_list_append (*freebusy, calobj);
+ *freebusy = g_slist_append (*freebusy, calobj);
icalcomponent_free (vfb);
g_free (address);
g_free (name);
}
} else {
- GList *l;
+ const GSList *l;
for (l = users; l != NULL; l = l->next ) {
address = l->data;
if (e_cal_backend_mail_account_is_valid (address, &name)) {
vfb = create_user_free_busy (cbhttp, address, name, start, end);
calobj = icalcomponent_as_ical_string_r (vfb);
- *freebusy = g_list_append (*freebusy, calobj);
+ *freebusy = g_slist_append (*freebusy, calobj);
icalcomponent_free (vfb);
g_free (name);
}
@@ -1289,29 +1205,14 @@ e_cal_backend_http_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GList
}
}
-/* Get_changes handler for the file backend */
-static void
-e_cal_backend_http_get_changes (ECalBackendSync *backend, EDataCal *cal, const gchar *change_id,
- GList **adds, GList **modifies, GList **deletes, GError **perror)
-{
- g_propagate_error (perror, EDC_ERROR (NotSupported));
-}
-
-/* Discard_alarm handler for the file backend */
static void
-e_cal_backend_http_discard_alarm (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *auid, GError **perror)
-{
- /* FIXME */
-}
-
-static void
-e_cal_backend_http_create_object (ECalBackendSync *backend, EDataCal *cal, gchar **calobj, gchar **uid, GError **perror)
+e_cal_backend_http_create_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, gchar **uid, gchar **new_calobj, GError **perror)
{
g_propagate_error (perror, EDC_ERROR (PermissionDenied));
}
static void
-e_cal_backend_http_modify_object (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj,
+e_cal_backend_http_modify_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj,
CalObjModType mod, gchar **old_object, gchar **new_object, GError **perror)
{
g_propagate_error (perror, EDC_ERROR (PermissionDenied));
@@ -1319,7 +1220,7 @@ e_cal_backend_http_modify_object (ECalBackendSync *backend, EDataCal *cal, const
/* Remove_object handler for the file backend */
static void
-e_cal_backend_http_remove_object (ECalBackendSync *backend, EDataCal *cal,
+e_cal_backend_http_remove_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable,
const gchar *uid, const gchar *rid,
CalObjModType mod, gchar **old_object,
gchar **object, GError **perror)
@@ -1331,13 +1232,13 @@ e_cal_backend_http_remove_object (ECalBackendSync *backend, EDataCal *cal,
/* Update_objects handler for the file backend. */
static void
-e_cal_backend_http_receive_objects (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, GError **perror)
+e_cal_backend_http_receive_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GError **perror)
{
g_propagate_error (perror, EDC_ERROR (PermissionDenied));
}
static void
-e_cal_backend_http_send_objects (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, GList **users,
+e_cal_backend_http_send_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GSList **users,
gchar **modified_calobj, GError **perror)
{
*users = NULL;
@@ -1347,21 +1248,6 @@ e_cal_backend_http_send_objects (ECalBackendSync *backend, EDataCal *cal, const
}
static icaltimezone *
-e_cal_backend_http_internal_get_default_timezone (ECalBackend *backend)
-{
- ECalBackendHttp *cbhttp;
- ECalBackendHttpPrivate *priv;
-
- cbhttp = E_CAL_BACKEND_HTTP (backend);
- priv = cbhttp->priv;
-
- if (!priv->store)
- return NULL;
-
- return NULL;
-}
-
-static icaltimezone *
e_cal_backend_http_internal_get_timezone (ECalBackend *backend, const gchar *tzid)
{
ECalBackendHttp *cbhttp;
@@ -1419,33 +1305,22 @@ e_cal_backend_http_class_init (ECalBackendHttpClass *class)
object_class->dispose = e_cal_backend_http_dispose;
object_class->finalize = e_cal_backend_http_finalize;
- sync_class->is_read_only_sync = e_cal_backend_http_is_read_only;
- sync_class->get_cal_address_sync = e_cal_backend_http_get_cal_address;
- sync_class->get_alarm_email_address_sync = e_cal_backend_http_get_alarm_email_address;
- sync_class->get_ldap_attribute_sync = e_cal_backend_http_get_ldap_attribute;
- sync_class->get_static_capabilities_sync = e_cal_backend_http_get_static_capabilities;
- sync_class->open_sync = e_cal_backend_http_open;
- sync_class->refresh_sync = e_cal_backend_http_refresh;
- sync_class->remove_sync = e_cal_backend_http_remove;
- sync_class->create_object_sync = e_cal_backend_http_create_object;
- sync_class->modify_object_sync = e_cal_backend_http_modify_object;
- sync_class->remove_object_sync = e_cal_backend_http_remove_object;
- sync_class->discard_alarm_sync = e_cal_backend_http_discard_alarm;
- sync_class->receive_objects_sync = e_cal_backend_http_receive_objects;
- sync_class->send_objects_sync = e_cal_backend_http_send_objects;
- sync_class->get_default_object_sync = e_cal_backend_http_get_default_object;
- sync_class->get_object_sync = e_cal_backend_http_get_object;
- sync_class->get_object_list_sync = e_cal_backend_http_get_object_list;
- sync_class->add_timezone_sync = e_cal_backend_http_add_timezone;
- sync_class->set_default_zone_sync = e_cal_backend_http_set_default_zone;
- sync_class->get_freebusy_sync = e_cal_backend_http_get_free_busy;
- sync_class->get_changes_sync = e_cal_backend_http_get_changes;
-
- backend_class->is_loaded = e_cal_backend_http_is_loaded;
- backend_class->start_query = e_cal_backend_http_start_query;
- backend_class->get_mode = e_cal_backend_http_get_mode;
- backend_class->set_mode = e_cal_backend_http_set_mode;
-
- backend_class->internal_get_default_timezone = e_cal_backend_http_internal_get_default_timezone;
- backend_class->internal_get_timezone = e_cal_backend_http_internal_get_timezone;
+ sync_class->get_backend_property_sync = e_cal_backend_http_get_backend_property;
+ sync_class->open_sync = e_cal_backend_http_open;
+ sync_class->authenticate_user_sync = e_cal_backend_http_authenticate_user;
+ sync_class->refresh_sync = e_cal_backend_http_refresh;
+ sync_class->remove_sync = e_cal_backend_http_remove;
+ sync_class->create_object_sync = e_cal_backend_http_create_object;
+ sync_class->modify_object_sync = e_cal_backend_http_modify_object;
+ sync_class->remove_object_sync = e_cal_backend_http_remove_object;
+ sync_class->receive_objects_sync = e_cal_backend_http_receive_objects;
+ sync_class->send_objects_sync = e_cal_backend_http_send_objects;
+ sync_class->get_object_sync = e_cal_backend_http_get_object;
+ sync_class->get_object_list_sync = e_cal_backend_http_get_object_list;
+ sync_class->add_timezone_sync = e_cal_backend_http_add_timezone;
+ sync_class->get_free_busy_sync = e_cal_backend_http_get_free_busy;
+
+ backend_class->start_view = e_cal_backend_http_start_view;
+ backend_class->set_online = e_cal_backend_http_set_online;
+ backend_class->internal_get_timezone = e_cal_backend_http_internal_get_timezone;
}
diff --git a/calendar/backends/weather/e-cal-backend-weather.c b/calendar/backends/weather/e-cal-backend-weather.c
index 1886a3b..cb2503b 100644
--- a/calendar/backends/weather/e-cal-backend-weather.c
+++ b/calendar/backends/weather/e-cal-backend-weather.c
@@ -42,7 +42,7 @@ G_DEFINE_TYPE (ECalBackendWeather, e_cal_backend_weather, E_TYPE_CAL_BACKEND_SYN
static gboolean reload_cb (ECalBackendWeather *cbw);
static gboolean begin_retrieval_cb (ECalBackendWeather *cbw);
static ECalComponent* create_weather (ECalBackendWeather *cbw, WeatherInfo *report, gboolean is_forecast);
-static void e_cal_backend_weather_add_timezone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **perror);
+static void e_cal_backend_weather_add_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobj, GError **perror);
/* Private part of the ECalBackendWeather structure */
struct _ECalBackendWeatherPrivate {
@@ -50,14 +50,11 @@ struct _ECalBackendWeatherPrivate {
gchar *uri;
/* Local/remote mode */
- CalMode mode;
+ gboolean is_online;
/* The file cache */
ECalBackendStore *store;
- /* The calendar's default timezone, used for resolving DATE and
- floating DATE-TIME values. */
- icaltimezone *default_zone;
GHashTable *zones;
/* Reload */
@@ -165,7 +162,7 @@ put_component_to_store (ECalBackendWeather *cb,
priv = cb->priv;
e_cal_util_get_component_occur_times (comp, &time_start, &time_end,
- resolve_tzid, cb, priv->default_zone,
+ resolve_tzid, cb, icaltimezone_get_utc_timezone (),
e_cal_backend_get_kind (E_CAL_BACKEND (cb)));
e_cal_backend_store_put_component_with_time_range (priv->store, comp, time_start, time_end);
@@ -253,7 +250,7 @@ begin_retrieval_cb (ECalBackendWeather *cbw)
ECalBackendWeatherPrivate *priv = cbw->priv;
GSource *source;
- if (priv->mode != CAL_MODE_REMOTE)
+ if (!priv->is_online)
return TRUE;
maybe_start_reload_timeout (cbw);
@@ -369,7 +366,7 @@ create_weather (ECalBackendWeather *cbw, WeatherInfo *report, gboolean is_foreca
update_zone = icaltimezone_get_builtin_timezone (location->tz_hint);
if (!update_zone)
- update_zone = priv->default_zone;
+ update_zone = icaltimezone_get_utc_timezone ();
/* Set all-day event's date from forecast data - cannot set is_date,
because in that case no timezone conversion is done */
@@ -455,47 +452,38 @@ create_weather (ECalBackendWeather *cbw, WeatherInfo *report, gboolean is_foreca
return cal_comp;
}
-static void
-e_cal_backend_weather_is_read_only (ECalBackendSync *backend, EDataCal *cal, gboolean *read_only, GError **perror)
-{
- *read_only = TRUE;
-}
-
-static void
-e_cal_backend_weather_get_cal_address (ECalBackendSync *backend, EDataCal *cal, gchar **address, GError **perror)
-{
- /* Weather has no particular email addresses associated with it */
- *address = NULL;
-}
-
-static void
-e_cal_backend_weather_get_alarm_email_address (ECalBackendSync *backend, EDataCal *cal, gchar **address, GError **perror)
-{
- /* Weather has no particular email addresses associated with it */
- *address = NULL;
-}
-
-static void
-e_cal_backend_weather_get_ldap_attribute (ECalBackendSync *backend, EDataCal *cal, gchar **attribute, GError **perror)
-{
- *attribute = NULL;
-}
+static gboolean
+e_cal_backend_weather_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **perror)
+{
+ gboolean processed = TRUE;
+
+ g_return_val_if_fail (prop_name != NULL, FALSE);
+ g_return_val_if_fail (prop_value != NULL, FALSE);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ *prop_value = g_strdup (CAL_STATIC_CAPABILITY_NO_ALARM_REPEAT ","
+ CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS ","
+ CAL_STATIC_CAPABILITY_NO_DISPLAY_ALARMS ","
+ CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS ","
+ CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT ","
+ CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
+ CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
+ CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED);
+ } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
+ g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+ /* Weather has no particular email addresses associated with it */
+ *prop_value = NULL;
+ } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+ g_propagate_error (perror, EDC_ERROR (UnsupportedMethod));
+ } else {
+ processed = FALSE;
+ }
-static void
-e_cal_backend_weather_get_static_capabilities (ECalBackendSync *backend, EDataCal *cal, gchar **capabilities, GError **perror)
-{
- *capabilities = g_strdup (CAL_STATIC_CAPABILITY_NO_ALARM_REPEAT ","
- CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS ","
- CAL_STATIC_CAPABILITY_NO_DISPLAY_ALARMS ","
- CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS ","
- CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT ","
- CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
- CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
- CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED);
+ return processed;
}
static void
-e_cal_backend_weather_open (ECalBackendSync *backend, EDataCal *cal, gboolean only_if_exists, const gchar *username, const gchar *password, GError **perror)
+e_cal_backend_weather_open (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gboolean only_if_exists, GError **perror)
{
ECalBackendWeather *cbw;
ECalBackendWeatherPrivate *priv;
@@ -512,6 +500,9 @@ e_cal_backend_weather_open (ECalBackendSync *backend, EDataCal *cal, gboolean on
g_free (priv->city);
priv->city = g_strdup (strrchr (uri, '/') + 1);
+ e_cal_backend_notify_readonly (E_CAL_BACKEND (backend), TRUE);
+ e_cal_backend_notify_online (E_CAL_BACKEND (backend), priv->is_online);
+
if (!priv->store) {
e_cal_backend_cache_remove (cache_dir, "cache.xml");
priv->store = e_cal_backend_file_store_new (cache_dir);
@@ -520,28 +511,23 @@ e_cal_backend_weather_open (ECalBackendSync *backend, EDataCal *cal, gboolean on
g_propagate_error (perror, EDC_ERROR_EX (OtherError, _("Could not create cache file")));
return;
}
- /* do we require to load this new store*/
- e_cal_backend_store_load (priv->store);
-
- if (priv->default_zone) {
- icalcomponent *icalcomp = icaltimezone_get_component (priv->default_zone);
- icaltimezone *zone = icaltimezone_new ();
-
- icaltimezone_set_component (zone, icalcomponent_new_clone (icalcomp));
- g_hash_table_insert (priv->zones, g_strdup (icaltimezone_get_tzid (zone)), zone);
- }
+ /* do we require to load this new store */
+ e_cal_backend_store_load (priv->store);
+ e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
- if (priv->mode == CAL_MODE_LOCAL)
+ if (!priv->is_online)
return;
if (!priv->begin_retrival_id)
priv->begin_retrival_id = g_idle_add ((GSourceFunc) begin_retrieval_cb, cbw);
}
+
+ e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
}
static void
-e_cal_backend_weather_refresh (ECalBackendSync *backend, EDataCal *cal, GError **perror)
+e_cal_backend_weather_refresh (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **perror)
{
ECalBackendWeather *cbw;
ECalBackendWeatherPrivate *priv;
@@ -562,7 +548,7 @@ e_cal_backend_weather_refresh (ECalBackendSync *backend, EDataCal *cal, GError *
}
static void
-e_cal_backend_weather_remove (ECalBackendSync *backend, EDataCal *cal, GError **perror)
+e_cal_backend_weather_remove (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **perror)
{
ECalBackendWeather *cbw;
ECalBackendWeatherPrivate *priv;
@@ -580,24 +566,13 @@ e_cal_backend_weather_remove (ECalBackendSync *backend, EDataCal *cal, GError **
}
static void
-e_cal_backend_weather_discard_alarm (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *auid, GError **perror)
-{
-}
-
-static void
-e_cal_backend_weather_receive_objects (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, GError **perror)
+e_cal_backend_weather_receive_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GError **perror)
{
g_propagate_error (perror, EDC_ERROR (PermissionDenied));
}
static void
-e_cal_backend_weather_get_default_object (ECalBackendSync *backend, EDataCal *cal, gchar **object, GError **perror)
-{
- g_propagate_error (perror, EDC_ERROR (UnsupportedMethod));
-}
-
-static void
-e_cal_backend_weather_get_object (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *rid, gchar **object, GError **error)
+e_cal_backend_weather_get_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **object, GError **error)
{
ECalBackendWeather *cbw = E_CAL_BACKEND_WEATHER (backend);
ECalBackendWeatherPrivate *priv = cbw->priv;
@@ -617,7 +592,7 @@ e_cal_backend_weather_get_object (ECalBackendSync *backend, EDataCal *cal, const
}
static void
-e_cal_backend_weather_get_object_list (ECalBackendSync *backend, EDataCal *cal, const gchar *sexp_string, GList **objects, GError **perror)
+e_cal_backend_weather_get_object_list (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *sexp_string, GSList **objects, GError **perror)
{
ECalBackendWeather *cbw = E_CAL_BACKEND_WEATHER (backend);
ECalBackendWeatherPrivate *priv = cbw->priv;
@@ -643,7 +618,7 @@ e_cal_backend_weather_get_object_list (ECalBackendSync *backend, EDataCal *cal,
for (l = components; l != NULL; l = g_slist_next (l)) {
if (e_cal_backend_sexp_match_comp (sexp, E_CAL_COMPONENT (l->data), E_CAL_BACKEND (backend)))
- *objects = g_list_append (*objects, e_cal_component_get_as_string (l->data));
+ *objects = g_slist_append (*objects, e_cal_component_get_as_string (l->data));
}
g_slist_foreach (components, (GFunc) g_object_unref, NULL);
@@ -652,7 +627,7 @@ e_cal_backend_weather_get_object_list (ECalBackendSync *backend, EDataCal *cal,
}
static void
-e_cal_backend_weather_add_timezone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **error)
+e_cal_backend_weather_add_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobj, GError **error)
{
ECalBackendWeather *cbw;
ECalBackendWeatherPrivate *priv;
@@ -687,38 +662,7 @@ e_cal_backend_weather_add_timezone (ECalBackendSync *backend, EDataCal *cal, con
}
static void
-e_cal_backend_weather_set_default_zone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **error)
-{
- icalcomponent *tz_comp;
- ECalBackendWeather *cbw;
- ECalBackendWeatherPrivate *priv;
- icaltimezone *zone;
-
- cbw = (ECalBackendWeather *) backend;
-
- e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_WEATHER (cbw), InvalidArg);
- e_return_data_cal_error_if_fail (tzobj != NULL, InvalidArg);
-
- priv = cbw->priv;
-
- tz_comp = icalparser_parse_string (tzobj);
- if (!tz_comp) {
- g_propagate_error (error, EDC_ERROR (InvalidObject));
- return;
- }
-
- zone = icaltimezone_new ();
- icaltimezone_set_component (zone, tz_comp);
-
- if (priv->default_zone)
- icaltimezone_free (priv->default_zone, 1);
-
- /* Set the default timezone to it. */
- priv->default_zone = zone;
-}
-
-static void
-e_cal_backend_weather_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GList *users, time_t start, time_t end, GList **freebusy, GError **perror)
+e_cal_backend_weather_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const GSList *users, time_t start, time_t end, GSList **freebusy, GError **perror)
{
/* Weather doesn't count as busy time */
icalcomponent *vfb = icalcomponent_new_vfreebusy ();
@@ -729,37 +673,18 @@ e_cal_backend_weather_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GL
icalcomponent_set_dtend (vfb, icaltime_from_timet_with_zone (end, FALSE, utc_zone));
calobj = icalcomponent_as_ical_string_r (vfb);
- *freebusy = g_list_append (NULL, calobj);
+ *freebusy = g_slist_append (NULL, calobj);
icalcomponent_free (vfb);
}
static void
-e_cal_backend_weather_get_changes (ECalBackendSync *backend, EDataCal *cal, const gchar *change_id, GList **adds, GList **modifies, GList **deletes, GError **perror)
-{
-}
-
-static gboolean
-e_cal_backend_weather_is_loaded (ECalBackend *backend)
-{
- ECalBackendWeather *cbw;
- ECalBackendWeatherPrivate *priv;
-
- cbw = E_CAL_BACKEND_WEATHER (backend);
- priv = cbw->priv;
-
- if (!priv->store)
- return FALSE;
-
- return TRUE;
-}
-
-static void e_cal_backend_weather_start_query (ECalBackend *backend, EDataCalView *query)
+e_cal_backend_weather_start_view (ECalBackend *backend, EDataCalView *query)
{
ECalBackendWeather *cbw;
ECalBackendWeatherPrivate *priv;
ECalBackendSExp *sexp;
GSList *components, *l;
- GList *objects;
+ GSList *objects;
GError *error;
time_t occur_start = -1, occur_end = -1;
gboolean prunning_by_time;
@@ -769,7 +694,7 @@ static void e_cal_backend_weather_start_query (ECalBackend *backend, EDataCalVie
if (!priv->store) {
error = EDC_ERROR (NoSuchCal);
- e_data_cal_view_notify_done (query, error);
+ e_data_cal_view_notify_complete (query, error);
g_error_free (error);
return;
}
@@ -777,7 +702,7 @@ static void e_cal_backend_weather_start_query (ECalBackend *backend, EDataCalVie
sexp = e_data_cal_view_get_object_sexp (query);
if (!sexp) {
error = EDC_ERROR (InvalidQuery);
- e_data_cal_view_notify_done (query, error);
+ e_data_cal_view_notify_complete (query, error);
g_error_free (error);
return;
}
@@ -790,92 +715,48 @@ static void e_cal_backend_weather_start_query (ECalBackend *backend, EDataCalVie
for (l = components; l != NULL; l = g_slist_next (l)) {
if (e_cal_backend_sexp_match_comp (sexp, E_CAL_COMPONENT (l->data), backend))
- objects = g_list_append (objects, e_cal_component_get_as_string (l->data));
+ objects = g_slist_append (objects, e_cal_component_get_as_string (l->data));
}
if (objects)
- e_data_cal_view_notify_objects_added (query, (const GList *) objects);
+ e_data_cal_view_notify_objects_added (query, objects);
g_slist_foreach (components, (GFunc) g_object_unref, NULL);
g_slist_free (components);
- g_list_foreach (objects, (GFunc) g_free, NULL);
- g_list_free (objects);
+ g_slist_foreach (objects, (GFunc) g_free, NULL);
+ g_slist_free (objects);
g_object_unref (sexp);
- e_data_cal_view_notify_done (query, NULL /* Success */);
-}
-
-static CalMode
-e_cal_backend_weather_get_mode (ECalBackend *backend)
-{
- ECalBackendWeather *cbw;
- ECalBackendWeatherPrivate *priv;
-
- cbw = E_CAL_BACKEND_WEATHER (backend);
- priv = cbw->priv;
-
- return priv->mode;
+ e_data_cal_view_notify_complete (query, NULL /* Success */);
}
static void
-e_cal_backend_weather_set_mode (ECalBackend *backend, CalMode mode)
+e_cal_backend_weather_set_online (ECalBackend *backend, gboolean is_online)
{
ECalBackendWeather *cbw;
ECalBackendWeatherPrivate *priv;
- EDataCalMode set_mode;
gboolean loaded;
cbw = E_CAL_BACKEND_WEATHER (backend);
priv = cbw->priv;
- loaded = e_cal_backend_weather_is_loaded (backend);
-
- if (priv->mode != mode) {
- switch (mode) {
- case CAL_MODE_LOCAL:
- case CAL_MODE_REMOTE:
- priv->mode = mode;
- set_mode = cal_mode_to_corba (mode);
- if (loaded && priv->reload_timeout_id) {
- g_source_remove (priv->reload_timeout_id);
- priv->reload_timeout_id = 0;
- }
- break;
- case CAL_MODE_ANY:
- priv->mode = mode;
- set_mode = cal_mode_to_corba (mode);
- if (loaded && !priv->begin_retrival_id)
- priv->begin_retrival_id = g_idle_add ((GSourceFunc) begin_retrieval_cb, backend);
- break;
- default:
- set_mode = AnyMode;
- break;
+ loaded = e_cal_backend_is_opened (backend);
+
+ if ((priv->is_online ? 1: 0) != (is_online ? 1 : 0)) {
+ priv->is_online = is_online;
+ if (loaded && priv->reload_timeout_id) {
+ g_source_remove (priv->reload_timeout_id);
+ priv->reload_timeout_id = 0;
}
- } else {
- set_mode = cal_mode_to_corba (priv->mode);
}
if (loaded) {
- if (set_mode == AnyMode)
- e_cal_backend_notify_mode (backend,
- ModeNotSupported,
- cal_mode_to_corba (priv->mode));
- else
- e_cal_backend_notify_mode (backend,
- ModeSet,
- set_mode);
+ e_cal_backend_notify_online (backend, priv->is_online);
+ e_cal_backend_notify_readonly (backend, TRUE);
}
}
static icaltimezone *
-e_cal_backend_weather_internal_get_default_timezone (ECalBackend *backend)
-{
- ECalBackendWeather *cbw = E_CAL_BACKEND_WEATHER (backend);
-
- return cbw->priv->default_zone;
-}
-
-static icaltimezone *
e_cal_backend_weather_internal_get_timezone (ECalBackend *backend, const gchar *tzid)
{
icaltimezone *zone;
@@ -940,11 +821,6 @@ e_cal_backend_weather_finalize (GObject *object)
priv->city = NULL;
}
- if (priv->default_zone) {
- icaltimezone_free (priv->default_zone, 1);
- priv->default_zone = NULL;
- }
-
g_free (priv);
cbw->priv = NULL;
@@ -991,28 +867,17 @@ e_cal_backend_weather_class_init (ECalBackendWeatherClass *class)
object_class->finalize = e_cal_backend_weather_finalize;
- sync_class->is_read_only_sync = e_cal_backend_weather_is_read_only;
- sync_class->get_cal_address_sync = e_cal_backend_weather_get_cal_address;
- sync_class->get_alarm_email_address_sync = e_cal_backend_weather_get_alarm_email_address;
- sync_class->get_ldap_attribute_sync = e_cal_backend_weather_get_ldap_attribute;
- sync_class->get_static_capabilities_sync = e_cal_backend_weather_get_static_capabilities;
- sync_class->open_sync = e_cal_backend_weather_open;
- sync_class->refresh_sync = e_cal_backend_weather_refresh;
- sync_class->remove_sync = e_cal_backend_weather_remove;
- sync_class->discard_alarm_sync = e_cal_backend_weather_discard_alarm;
- sync_class->receive_objects_sync = e_cal_backend_weather_receive_objects;
- sync_class->get_default_object_sync = e_cal_backend_weather_get_default_object;
- sync_class->get_object_sync = e_cal_backend_weather_get_object;
- sync_class->get_object_list_sync = e_cal_backend_weather_get_object_list;
- sync_class->add_timezone_sync = e_cal_backend_weather_add_timezone;
- sync_class->set_default_zone_sync = e_cal_backend_weather_set_default_zone;
- sync_class->get_freebusy_sync = e_cal_backend_weather_get_free_busy;
- sync_class->get_changes_sync = e_cal_backend_weather_get_changes;
- backend_class->is_loaded = e_cal_backend_weather_is_loaded;
- backend_class->start_query = e_cal_backend_weather_start_query;
- backend_class->get_mode = e_cal_backend_weather_get_mode;
- backend_class->set_mode = e_cal_backend_weather_set_mode;
-
- backend_class->internal_get_default_timezone = e_cal_backend_weather_internal_get_default_timezone;
- backend_class->internal_get_timezone = e_cal_backend_weather_internal_get_timezone;
+ sync_class->get_backend_property_sync = e_cal_backend_weather_get_backend_property;
+ sync_class->open_sync = e_cal_backend_weather_open;
+ sync_class->refresh_sync = e_cal_backend_weather_refresh;
+ sync_class->remove_sync = e_cal_backend_weather_remove;
+ sync_class->receive_objects_sync = e_cal_backend_weather_receive_objects;
+ sync_class->get_object_sync = e_cal_backend_weather_get_object;
+ sync_class->get_object_list_sync = e_cal_backend_weather_get_object_list;
+ sync_class->add_timezone_sync = e_cal_backend_weather_add_timezone;
+ sync_class->get_free_busy_sync = e_cal_backend_weather_get_free_busy;
+
+ backend_class->start_view = e_cal_backend_weather_start_view;
+ backend_class->set_online = e_cal_backend_weather_set_online;
+ backend_class->internal_get_timezone = e_cal_backend_weather_internal_get_timezone;
}
diff --git a/calendar/libecal/Makefile.am b/calendar/libecal/Makefile.am
index cea385b..1ae10ad 100644
--- a/calendar/libecal/Makefile.am
+++ b/calendar/libecal/Makefile.am
@@ -15,7 +15,7 @@ libecal_INCLUDES = \
libecal_1_2_la_CPPFLAGS = \
$(AM_CPPFLAGS) \
- $(libecal_INCLUDES) \
+ $(libecal_INCLUDES) \
-DG_LOG_DOMAIN=\"libecal\" \
$(LIBICAL_CFLAGS) \
$(EVOLUTION_CALENDAR_CFLAGS)
@@ -23,6 +23,9 @@ libecal_1_2_la_CPPFLAGS = \
libecal_1_2_la_SOURCES = \
$(MARSHAL_GENERATED) \
e-cal.c \
+ e-cal-client.c \
+ e-cal-client-view.c \
+ e-cal-client-view-private.h \
e-cal-component.c \
e-cal-recur.c \
e-cal-time-util.c \
@@ -46,6 +49,8 @@ libecalincludedir = $(privincludedir)/libecal
libecalinclude_HEADERS = \
e-cal.h \
+ e-cal-client.h \
+ e-cal-client-view.h \
e-cal-component.h \
e-cal-recur.h \
e-cal-time-util.h \
diff --git a/calendar/libecal/e-cal-client-view-private.h b/calendar/libecal/e-cal-client-view-private.h
new file mode 100644
index 0000000..8a99f54
--- /dev/null
+++ b/calendar/libecal/e-cal-client-view-private.h
@@ -0,0 +1,35 @@
+/* Evolution calendar - Live view client object
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ * Author: Federico Mena-Quintero <federico ximian com>
+ *
+ * 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.
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef E_CAL_CLIENT_VIEW_PRIVATE_H
+#define E_CAL_CLIENT_VIEW_PRIVATE_H
+
+#include "libecal/e-cal-client-view.h"
+
+G_BEGIN_DECLS
+
+struct _EGdbusCalView;
+struct _ECalClient;
+
+ECalClientView *_e_cal_client_view_new (struct _ECalClient *client, struct _EGdbusCalView *gdbus_calview);
+
+G_END_DECLS
+
+#endif
diff --git a/calendar/libecal/e-cal-client-view.c b/calendar/libecal/e-cal-client-view.c
new file mode 100644
index 0000000..079e72a
--- /dev/null
+++ b/calendar/libecal/e-cal-client-view.c
@@ -0,0 +1,527 @@
+/*-*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* Evolution calendar - Live view client object
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * Authors: Federico Mena-Quintero <federico ximian com>
+ * Ross Burton <ross linux intel com>
+ *
+ * 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.
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n-lib.h>
+
+#include <string.h>
+#include "e-cal-client.h"
+#include "e-cal-client-view.h"
+#include "e-cal-client-view-private.h"
+
+#include "libedataserver/e-gdbus-marshallers.h"
+
+#include "e-gdbus-cal-view.h"
+
+G_DEFINE_TYPE (ECalClientView, e_cal_client_view, G_TYPE_OBJECT);
+
+/* Private part of the ECalClientView structure */
+struct _ECalClientViewPrivate {
+ GDBusProxy *gdbus_calview;
+ ECalClient *client;
+ gboolean running;
+};
+
+/* Property IDs */
+enum props {
+ PROP_0,
+ PROP_VIEW,
+ PROP_CLIENT
+};
+
+/* Signal IDs */
+enum {
+ OBJECTS_ADDED,
+ OBJECTS_MODIFIED,
+ OBJECTS_REMOVED,
+ PROGRESS,
+ COMPLETE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+static GSList *
+build_object_list (const gchar * const *seq)
+{
+ GSList *list;
+ gint i;
+
+ list = NULL;
+ for (i = 0; seq[i]; i++) {
+ icalcomponent *comp;
+
+ comp = icalcomponent_new_from_string ((gchar *)seq[i]);
+ if (!comp)
+ continue;
+
+ list = g_slist_prepend (list, comp);
+ }
+
+ return g_slist_reverse (list);
+}
+
+static GSList *
+build_id_list (const gchar * const *seq)
+{
+ GSList *list;
+ gint i;
+
+ list = NULL;
+ for (i = 0; seq[i]; i++) {
+ ECalComponentId *id;
+ id = g_new (ECalComponentId, 1);
+ id->uid = g_strdup (seq[i]);
+ id->rid = NULL; /* TODO */
+ list = g_slist_prepend (list, id);
+ }
+
+ return g_slist_reverse (list);
+}
+
+static void
+objects_added_cb (EGdbusCalView *gdbus_calview, const gchar * const *objects, ECalClientView *view)
+{
+ GSList *list;
+
+ g_return_if_fail (E_IS_CAL_CLIENT_VIEW (view));
+
+ if (!view->priv->running)
+ return;
+
+ g_object_ref (view);
+
+ list = build_object_list (objects);
+
+ g_signal_emit (G_OBJECT (view), signals[OBJECTS_ADDED], 0, list);
+
+ g_slist_foreach (list, (GFunc) icalcomponent_free, NULL);
+ g_slist_free (list);
+
+ g_object_unref (view);
+}
+
+static void
+objects_modified_cb (EGdbusCalView *gdbus_calview, const gchar * const *objects, ECalClientView *view)
+{
+ GSList *list;
+
+ g_return_if_fail (E_IS_CAL_CLIENT_VIEW (view));
+
+ if (!view->priv->running)
+ return;
+
+ g_object_ref (view);
+
+ list = build_object_list (objects);
+
+ g_signal_emit (G_OBJECT (view), signals[OBJECTS_MODIFIED], 0, list);
+
+ g_slist_foreach (list, (GFunc) icalcomponent_free, NULL);
+ g_slist_free (list);
+
+ g_object_unref (view);
+}
+
+static void
+objects_removed_cb (EGdbusCalView *gdbus_calview, const gchar * const *uids, ECalClientView *view)
+{
+ GSList *list;
+
+ g_return_if_fail (E_IS_CAL_CLIENT_VIEW (view));
+
+ if (!view->priv->running)
+ return;
+
+ g_object_ref (view);
+
+ list = build_id_list (uids);
+
+ g_signal_emit (G_OBJECT (view), signals[OBJECTS_REMOVED], 0, list);
+
+ g_slist_foreach (list, (GFunc) e_cal_component_free_id, NULL);
+ g_slist_free (list);
+
+ g_object_unref (view);
+}
+
+static void
+progress_cb (EGdbusCalView *gdbus_calview, guint percent, const gchar *message, ECalClientView *view)
+{
+ g_return_if_fail (E_IS_CAL_CLIENT_VIEW (view));
+
+ if (!view->priv->running)
+ return;
+
+ g_signal_emit (G_OBJECT (view), signals[PROGRESS], 0, percent, message);
+}
+
+static void
+complete_cb (EGdbusCalView *gdbus_calview, const gchar * const *arg_error, ECalClientView *view)
+{
+ GError *error = NULL;
+
+ g_return_if_fail (E_IS_CAL_CLIENT_VIEW (view));
+
+ if (!view->priv->running)
+ return;
+
+ g_return_if_fail (e_gdbus_templates_decode_error (arg_error, &error));
+
+ g_signal_emit (G_OBJECT (view), signals[COMPLETE], 0, error);
+
+ if (error)
+ g_error_free (error);
+}
+
+/* Object initialization function for the calendar view */
+static void
+e_cal_client_view_init (ECalClientView *view)
+{
+ view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view, E_TYPE_CAL_CLIENT_VIEW, ECalClientViewPrivate);
+ view->priv->running = FALSE;
+}
+
+static void
+cal_client_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+ ECalClientView *view;
+ ECalClientViewPrivate *priv;
+
+ view = E_CAL_CLIENT_VIEW (object);
+ priv = view->priv;
+
+ switch (property_id) {
+ case PROP_VIEW:
+ /* gdbus_calview can be set only once */
+ g_return_if_fail (priv->gdbus_calview == NULL);
+
+ priv->gdbus_calview = g_object_ref (g_value_get_pointer (value));
+ g_signal_connect (priv->gdbus_calview, "objects-added", G_CALLBACK (objects_added_cb), view);
+ g_signal_connect (priv->gdbus_calview, "objects-modified", G_CALLBACK (objects_modified_cb), view);
+ g_signal_connect (priv->gdbus_calview, "objects-removed", G_CALLBACK (objects_removed_cb), view);
+ g_signal_connect (priv->gdbus_calview, "progress", G_CALLBACK (progress_cb), view);
+ g_signal_connect (priv->gdbus_calview, "complete", G_CALLBACK (complete_cb), view);
+ break;
+ case PROP_CLIENT:
+ priv->client = E_CAL_CLIENT (g_value_dup_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+cal_client_view_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+ ECalClientView *view;
+ ECalClientViewPrivate *priv;
+
+ view = E_CAL_CLIENT_VIEW (object);
+ priv = view->priv;
+
+ switch (property_id) {
+ case PROP_VIEW:
+ g_value_set_pointer (value, priv->gdbus_calview);
+ break;
+ case PROP_CLIENT:
+ g_value_set_object (value, priv->client);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+/* Finalize handler for the calendar view */
+static void
+cal_client_view_finalize (GObject *object)
+{
+ ECalClientView *view;
+ ECalClientViewPrivate *priv;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT_VIEW (object));
+
+ view = E_CAL_CLIENT_VIEW (object);
+ priv = view->priv;
+
+ if (priv->gdbus_calview != NULL) {
+ GError *error = NULL;
+
+ g_signal_handlers_disconnect_matched (priv->gdbus_calview, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view);
+ e_gdbus_cal_view_call_dispose_sync (priv->gdbus_calview, NULL, &error);
+ g_object_unref (priv->gdbus_calview);
+ priv->gdbus_calview = NULL;
+
+ if (error) {
+ g_warning ("Failed to dispose cal view: %s", error->message);
+ g_error_free (error);
+ }
+ }
+
+ if (priv->client) {
+ g_object_unref (priv->client);
+ priv->client = NULL;
+ }
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_cal_client_view_parent_class)->finalize (object);
+}
+
+/* Class initialization function for the calendar view */
+static void
+e_cal_client_view_class_init (ECalClientViewClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = (GObjectClass *) klass;
+
+ object_class->set_property = cal_client_view_set_property;
+ object_class->get_property = cal_client_view_get_property;
+ object_class->finalize = cal_client_view_finalize;
+
+ g_type_class_add_private (klass, sizeof (ECalClientViewPrivate));
+
+ g_object_class_install_property (object_class, PROP_VIEW,
+ g_param_spec_pointer ("view", "The GDBus view proxy", NULL,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class, PROP_CLIENT,
+ g_param_spec_object ("client", "The e-cal-client for the view", NULL, E_TYPE_CAL_CLIENT,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+ /**
+ * ECalClientView::objects-added:
+ * @view:: self
+ * @objects: (type GSList) (transfer none) (element-type long):
+ */
+ signals[OBJECTS_ADDED] =
+ g_signal_new ("objects-added",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (ECalClientViewClass, objects_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+ /**
+ * ECalClientView::objects-modified:
+ * @view:: self
+ * @objects: (type GSList) (transfer none) (element-type long):
+ */
+ signals[OBJECTS_MODIFIED] =
+ g_signal_new ("objects-modified",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (ECalClientViewClass, objects_modified),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+ /**
+ * ECalClientView::objects-removed:
+ * @view:: self
+ * @objects: (type GSList) (transfer none) (element-type ECalComponentId):
+ */
+ signals[OBJECTS_REMOVED] =
+ g_signal_new ("objects-removed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (ECalClientViewClass, objects_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+ signals[PROGRESS] =
+ g_signal_new ("progress",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (ECalClientViewClass, progress),
+ NULL, NULL,
+ e_gdbus_marshallers_VOID__UINT_STRING,
+ G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
+
+ signals[COMPLETE] =
+ g_signal_new ("complete",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (ECalClientViewClass, complete),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1, G_TYPE_ERROR);
+}
+
+/**
+ * _e_cal_client_view_new:
+ * @client: An #ECalClient object.
+ * @gdbuc_calview: The GDBus object for the view.
+ *
+ * Creates a new view object by issuing the view creation request to the
+ * calendar server.
+ *
+ * Returns: A newly-created view object, or NULL if the request failed.
+ **/
+ECalClientView *
+_e_cal_client_view_new (ECalClient *client, EGdbusCalView *gdbus_calview)
+{
+ ECalClientView *view;
+
+ view = g_object_new (E_TYPE_CAL_CLIENT_VIEW,
+ "client", client,
+ "view", gdbus_calview,
+ NULL);
+
+ return view;
+}
+
+/**
+ * e_cal_client_view_get_client
+ * @view: A #ECalClientView object.
+ *
+ * Get the #ECalClient associated with this view.
+ *
+ * Returns: the associated client.
+ **/
+ECalClient *
+e_cal_client_view_get_client (ECalClientView *view)
+{
+ g_return_val_if_fail (E_IS_CAL_CLIENT_VIEW (view), NULL);
+
+ return view->priv->client;
+}
+
+/**
+ * e_cal_client_view_is_running:
+ * @view: an #ECalClientView
+ *
+ * Retunrs: Whether view is running. Not running views are ignoring
+ * all events sent from the server.
+ **/
+gboolean
+e_cal_client_view_is_running (ECalClientView *view)
+{
+ g_return_val_if_fail (E_IS_CAL_CLIENT_VIEW (view), FALSE);
+
+ return view->priv->running;
+}
+
+/**
+ * e_cal_client_view_start:
+ * @view: An #ECalClientView object.
+ * @error: A #Gerror
+ *
+ * Starts a live query to the calendar/tasks backend.
+ **/
+void
+e_cal_client_view_start (ECalClientView *view, GError **error)
+{
+ ECalClientViewPrivate *priv;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT_VIEW (view));
+
+ priv = view->priv;
+
+ if (priv->gdbus_calview) {
+ GError *local_error = NULL;
+
+ if (e_gdbus_cal_view_call_start_sync (priv->gdbus_calview, NULL, &local_error))
+ priv->running = TRUE;
+
+ e_client_util_unwrap_dbus_error (local_error, error, NULL, 0, 0, FALSE);
+ } else {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR, _("Cannot start view, D-Bus proxy gone"));
+ }
+}
+
+/**
+ * e_cal_client_view_stop:
+ * @view: An #ECalClientView object.
+ * @error: A #GError
+ *
+ * Stops a live query to the calendar/tasks backend.
+ */
+void
+e_cal_client_view_stop (ECalClientView *view, GError **error)
+{
+ ECalClientViewPrivate *priv;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT_VIEW (view));
+
+ priv = view->priv;
+ priv->running = FALSE;
+
+ if (priv->gdbus_calview) {
+ GError *local_error = NULL;
+
+ e_gdbus_cal_view_call_stop_sync (priv->gdbus_calview, NULL, &local_error);
+
+ e_client_util_unwrap_dbus_error (local_error, error, NULL, 0, 0, FALSE);
+ } else {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR, _("Cannot stop view, D-Bus proxy gone"));
+ }
+}
+
+/**
+ * e_cal_client_view_set_fields_of_interest:
+ * @view: An #ECalClientView object
+ * @fields_of_interest: List of field names in which the client is interested
+ * @error: A #GError
+ *
+ * Client can instruct server to which fields it is interested in only, thus
+ * the server can return less data over the wire. The server can still return
+ * complete objects, this is just a hint to it that the listed fields will
+ * be used only. The UID/RID fields are returned always. Initial views has no fields
+ * of interest and using %NULL for @fields_of_interest will unset any previous
+ * changes.
+ *
+ * Some backends can use summary information of its cache to create artifical
+ * objects, which will omit stored object parsing. If this cannot be done then
+ * it will simply return object as is stored in the cache.
+ **/
+void
+e_cal_client_view_set_fields_of_interest (ECalClientView *view, const GSList *fields_of_interest, GError **error)
+{
+ ECalClientViewPrivate *priv;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT_VIEW (view));
+
+ priv = view->priv;
+
+ if (priv->gdbus_calview) {
+ GError *local_error = NULL;
+ gchar **strv;
+
+ strv = e_client_util_slist_to_strv (fields_of_interest);
+ e_gdbus_cal_view_call_set_fields_of_interest_sync (priv->gdbus_calview, (const gchar * const *) strv, NULL, &local_error);
+ g_strfreev (strv);
+
+ e_client_util_unwrap_dbus_error (local_error, error, NULL, 0, 0, FALSE);
+ } else {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR, _("Cannot set fields of interest, D-Bus proxy gone"));
+ }
+}
diff --git a/calendar/libecal/e-cal-client-view.h b/calendar/libecal/e-cal-client-view.h
new file mode 100644
index 0000000..fe3cf27
--- /dev/null
+++ b/calendar/libecal/e-cal-client-view.h
@@ -0,0 +1,68 @@
+/* Evolution calendar - Live view client object
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ * Author: Federico Mena-Quintero <federico ximian com>
+ *
+ * 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.
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef E_CAL_CLIENT_VIEW_H
+#define E_CAL_CLIENT_VIEW_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_CAL_CLIENT_VIEW (e_cal_client_view_get_type ())
+#define E_CAL_CLIENT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CAL_CLIENT_VIEW, ECalClientView))
+#define E_CAL_CLIENT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CAL_CLIENT_VIEW, ECalClientViewClass))
+#define E_IS_CAL_CLIENT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CAL_CLIENT_VIEW))
+#define E_IS_CAL_CLIENT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CAL_CLIENT_VIEW))
+
+typedef struct _ECalClientView ECalClientView;
+typedef struct _ECalClientViewClass ECalClientViewClass;
+typedef struct _ECalClientViewPrivate ECalClientViewPrivate;
+
+struct _ECalClient;
+
+struct _ECalClientView {
+ GObject object;
+
+ /*< private >*/
+ ECalClientViewPrivate *priv;
+};
+
+struct _ECalClientViewClass {
+ GObjectClass parent_class;
+
+ /* Notification signals */
+ void (* objects_added) (ECalClientView *view, const GSList *objects);
+ void (* objects_modified) (ECalClientView *view, const GSList *objects);
+ void (* objects_removed) (ECalClientView *view, const GSList *uids);
+
+ void (* progress) (ECalClientView *view, gint percent, const gchar *message);
+ void (* complete) (ECalClientView *view, const GError *error);
+};
+
+GType e_cal_client_view_get_type (void);
+struct _ECalClient * e_cal_client_view_get_client (ECalClientView *view);
+gboolean e_cal_client_view_is_running (ECalClientView *view);
+void e_cal_client_view_set_fields_of_interest(ECalClientView *view, const GSList *fields_of_interest, GError **error);
+void e_cal_client_view_start (ECalClientView *view, GError **error);
+void e_cal_client_view_stop (ECalClientView *view, GError **error);
+
+G_END_DECLS
+
+#endif /* E_CAL_CLIENT_VIEW_H */
diff --git a/calendar/libecal/e-cal-client.c b/calendar/libecal/e-cal-client.c
new file mode 100644
index 0000000..ad6b4e8
--- /dev/null
+++ b/calendar/libecal/e-cal-client.c
@@ -0,0 +1,4106 @@
+/*
+ * e-cal-client.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include "libedataserver/e-data-server-util.h"
+#include "libedataserver/e-client-private.h"
+
+#include "libedata-cal/e-data-cal-types.h"
+
+#include "e-cal-client.h"
+#include "e-cal-client-view-private.h"
+#include "e-cal-component.h"
+#include "e-cal-check-timezones.h"
+#include "e-cal-time-util.h"
+
+#include "e-gdbus-cal.h"
+#include "e-gdbus-cal-factory.h"
+#include "e-gdbus-cal-view.h"
+
+struct _ECalClientPrivate
+{
+ /* GDBus data */
+ GDBusProxy *gdbus_cal;
+ guint gone_signal_id;
+
+ ECalClientSourceType source_type;
+ icaltimezone *default_zone;
+ gchar *cache_dir;
+
+ GMutex *zone_cache_lock;
+ GHashTable *zone_cache;
+};
+
+enum {
+ FREE_BUSY_DATA,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE (ECalClient, e_cal_client, E_TYPE_CLIENT)
+
+/**
+ * Well-known calendar backend properties:
+ * @CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS: Contains default calendar's email
+ * address suggested by the backend.
+ * @CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS: Contains default alarm email
+ * address suggested by the backend.
+ * @CAL_BACKEND_PROPERTY_DEFAULT_OBJECT: Contains iCal component string
+ * of an #icalcomponent with the default values for properties needed.
+ * Preferred way of retrieving this property is by
+ * calling e_cal_client_get_default_object().
+ *
+ * See also: @CLIENT_BACKEND_PROPERTY_OPENED, @CLIENT_BACKEND_PROPERTY_OPENING,
+ * @CLIENT_BACKEND_PROPERTY_ONLINE, @CLIENT_BACKEND_PROPERTY_READONLY
+ * @CLIENT_BACKEND_PROPERTY_CACHE_DIR, @CLIENT_BACKEND_PROPERTY_CAPABILITIES
+ **/
+
+/**
+ * e_cal_client_source_type_enum_get_type:
+ *
+ * Registers the #ECalClientSourceTypeEnum type with glib.
+ *
+ * Returns: the ID of the #ECalClientSourceTypeEnum type.
+ */
+GType
+e_cal_client_source_type_enum_get_type (void)
+{
+ static volatile gsize enum_type__volatile = 0;
+
+ if (g_once_init_enter (&enum_type__volatile)) {
+ GType enum_type;
+ static GEnumValue values[] = {
+ { E_CAL_CLIENT_SOURCE_TYPE_EVENTS, "Events", "Events" },
+ { E_CAL_CLIENT_SOURCE_TYPE_TASKS, "Tasks", "Tasks" },
+ { E_CAL_CLIENT_SOURCE_TYPE_MEMOS, "Memos", "Memos" },
+ { E_CAL_CLIENT_SOURCE_TYPE_LAST, "Invalid", "Invalid" },
+ { -1, NULL, NULL}
+ };
+
+ enum_type = g_enum_register_static ("ECalClientSourceTypeEnum", values);
+ g_once_init_leave (&enum_type__volatile, enum_type);
+ }
+
+ return enum_type__volatile;
+}
+
+GQuark
+e_cal_client_error_quark (void)
+{
+ static GQuark q = 0;
+ if (q == 0)
+ q = g_quark_from_static_string ("e-cal-client-error-quark");
+
+ return q;
+}
+
+const gchar *
+e_cal_client_error_to_string (ECalClientError code)
+{
+ switch (code) {
+ case E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR:
+ return C_("CalClientError", "No such calendar");
+ case E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND:
+ return C_("CalClientError", "Object not found");
+ case E_CAL_CLIENT_ERROR_INVALID_OBJECT:
+ return C_("CalClientError", "Invalid object");
+ case E_CAL_CLIENT_ERROR_UNKNOWN_USER:
+ return C_("CalClientError", "Unknown user");
+ case E_CAL_CLIENT_ERROR_OBJECT_ID_ALREADY_EXISTS:
+ return C_("CalClientError", "Object ID already exists");
+ }
+
+ return C_("CalClientError", "Unknown error");
+}
+
+/**
+ * If the specified GError is a remote error, then create a new error
+ * representing the remote error. If the error is anything else, then
+ * leave it alone.
+ */
+static gboolean
+unwrap_dbus_error (GError *error, GError **client_error)
+{
+ #define err(a,b) "org.gnome.evolution.dataserver.Calendar." a, b
+ static struct EClientErrorsList
+ cal_errors[] = {
+ { err ("Success", -1) },
+ { err ("ObjectNotFound", E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND) },
+ { err ("InvalidObject", E_CAL_CLIENT_ERROR_INVALID_OBJECT) },
+ { err ("ObjectIdAlreadyExists", E_CAL_CLIENT_ERROR_OBJECT_ID_ALREADY_EXISTS) },
+ { err ("NoSuchCal", E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR) },
+ { err ("UnknownUser", E_CAL_CLIENT_ERROR_UNKNOWN_USER) },
+ }, cl_errors[] = {
+ { err ("Busy", E_CLIENT_ERROR_BUSY) },
+ { err ("InvalidArg", E_CLIENT_ERROR_INVALID_ARG) },
+ { err ("RepositoryOffline", E_CLIENT_ERROR_REPOSITORY_OFFLINE) },
+ { err ("PermissionDenied", E_CLIENT_ERROR_PERMISSION_DENIED) },
+ { err ("AuthenticationFailed", E_CLIENT_ERROR_AUTHENTICATION_FAILED) },
+ { err ("AuthenticationRequired", E_CLIENT_ERROR_AUTHENTICATION_REQUIRED) },
+ { err ("CouldNotCancel", E_CLIENT_ERROR_COULD_NOT_CANCEL) },
+ { err ("NotSupported", E_CLIENT_ERROR_NOT_SUPPORTED) },
+ { err ("InvalidRange", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("UnsupportedField", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("UnsupportedMethod", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("UnsupportedAuthenticationMethod", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("TLSNotAvailable", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("OfflineUnavailable", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("SearchSizeLimitExceeded", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("SearchTimeLimitExceeded", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("InvalidQuery", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("QueryRefused", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("InvalidServerVersion", E_CLIENT_ERROR_OTHER_ERROR) },
+ { err ("OtherError", E_CLIENT_ERROR_OTHER_ERROR) }
+ };
+ #undef err
+
+ if (error == NULL)
+ return TRUE;
+
+ if (!e_client_util_unwrap_dbus_error (error, client_error, cal_errors, G_N_ELEMENTS (cal_errors), E_CAL_CLIENT_ERROR, TRUE))
+ e_client_util_unwrap_dbus_error (error, client_error, cl_errors, G_N_ELEMENTS (cl_errors), E_CLIENT_ERROR, FALSE);
+
+ return FALSE;
+}
+
+static void
+set_proxy_gone_error (GError **error)
+{
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_DBUS_ERROR, _("D-Bus calendar proxy gone"));
+}
+
+static guint active_cal_clients = 0, cal_connection_closed_id = 0;
+static EGdbusCalFactory *cal_factory_proxy = NULL;
+static GStaticRecMutex cal_factory_proxy_lock = G_STATIC_REC_MUTEX_INIT;
+#define LOCK_FACTORY() g_static_rec_mutex_lock (&cal_factory_proxy_lock)
+#define UNLOCK_FACTORY() g_static_rec_mutex_unlock (&cal_factory_proxy_lock)
+
+static void gdbus_cal_factory_proxy_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, gpointer user_data);
+
+static void
+gdbus_cal_factory_proxy_disconnect (GDBusConnection *connection)
+{
+ LOCK_FACTORY ();
+
+ if (!connection && cal_factory_proxy)
+ connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy));
+
+ if (connection && cal_connection_closed_id) {
+ g_dbus_connection_signal_unsubscribe (connection, cal_connection_closed_id);
+ g_signal_handlers_disconnect_by_func (connection, gdbus_cal_factory_proxy_closed_cb, NULL);
+ }
+
+ if (cal_factory_proxy)
+ g_object_unref (cal_factory_proxy);
+
+ cal_connection_closed_id = 0;
+ cal_factory_proxy = NULL;
+
+ UNLOCK_FACTORY ();
+}
+
+static void
+gdbus_cal_factory_proxy_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, gpointer user_data)
+{
+ GError *err = NULL;
+
+ LOCK_FACTORY ();
+
+ gdbus_cal_factory_proxy_disconnect (connection);
+
+ if (error)
+ unwrap_dbus_error (g_error_copy (error), &err);
+
+ if (err) {
+ g_debug ("GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
+ g_error_free (err);
+ } else if (active_cal_clients) {
+ g_debug ("GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
+ }
+
+ UNLOCK_FACTORY ();
+}
+
+static void
+gdbus_cal_factory_connection_gone_cb (GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data)
+{
+ /* signal subscription takes care of correct parameters,
+ thus just do what is to be done here */
+ gdbus_cal_factory_proxy_closed_cb (connection, TRUE, NULL, user_data);
+}
+
+static gboolean
+gdbus_cal_factory_activate (GError **error)
+{
+ GDBusConnection *connection;
+
+ LOCK_FACTORY ();
+
+ if (G_LIKELY (cal_factory_proxy)) {
+ UNLOCK_FACTORY ();
+ return TRUE;
+ }
+
+ cal_factory_proxy = e_gdbus_cal_factory_proxy_new_for_bus_sync (
+ G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ CALENDAR_DBUS_SERVICE_NAME,
+ "/org/gnome/evolution/dataserver/CalendarFactory",
+ NULL,
+ error);
+
+ if (!cal_factory_proxy) {
+ UNLOCK_FACTORY ();
+ return FALSE;
+ }
+
+ connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy));
+ cal_connection_closed_id = g_dbus_connection_signal_subscribe (connection,
+ NULL, /* sender */
+ "org.freedesktop.DBus", /* interface */
+ "NameOwnerChanged", /* member */
+ "/org/freedesktop/DBus", /* object_path */
+ "org.gnome.evolution.dataserver.Calendar", /* arg0 */
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ gdbus_cal_factory_connection_gone_cb, NULL, NULL);
+
+ g_signal_connect (connection, "closed", G_CALLBACK (gdbus_cal_factory_proxy_closed_cb), NULL);
+
+ UNLOCK_FACTORY ();
+
+ return TRUE;
+}
+
+static void gdbus_cal_client_disconnect (ECalClient *client);
+
+/*
+ * Called when the calendar server dies.
+ */
+static void
+gdbus_cal_client_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, ECalClient *client)
+{
+ GError *err = NULL;
+
+ g_assert (E_IS_CAL_CLIENT (client));
+
+ if (error)
+ unwrap_dbus_error (g_error_copy (error), &err);
+
+ if (err) {
+ g_debug (G_STRLOC ": ECalClient GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
+ g_error_free (err);
+ } else {
+ g_debug (G_STRLOC ": ECalClient GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
+ }
+
+ gdbus_cal_client_disconnect (client);
+
+ e_client_emit_backend_died (E_CLIENT (client));
+}
+
+static void
+gdbus_cal_client_connection_gone_cb (GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data)
+{
+ /* signal subscription takes care of correct parameters,
+ thus just do what is to be done here */
+ gdbus_cal_client_closed_cb (connection, TRUE, NULL, user_data);
+}
+
+static void
+gdbus_cal_client_disconnect (ECalClient *client)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+
+ /* Ensure that everything relevant is NULL */
+ LOCK_FACTORY ();
+
+ if (client->priv->gdbus_cal) {
+ GDBusConnection *connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (client->priv->gdbus_cal));
+
+ g_signal_handlers_disconnect_by_func (connection, gdbus_cal_client_closed_cb, client);
+ g_dbus_connection_signal_unsubscribe (connection, client->priv->gone_signal_id);
+ client->priv->gone_signal_id = 0;
+
+ e_gdbus_cal_call_close_sync (client->priv->gdbus_cal, NULL, NULL);
+ g_object_unref (client->priv->gdbus_cal);
+ client->priv->gdbus_cal = NULL;
+ }
+
+ UNLOCK_FACTORY ();
+}
+
+static void
+backend_error_cb (EGdbusCal *object, const gchar *message, ECalClient *client)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (client));
+ g_return_if_fail (message != NULL);
+
+ e_client_emit_backend_error (E_CLIENT (client), message);
+}
+
+static void
+readonly_cb (EGdbusCal *object, gboolean readonly, ECalClient *client)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (client));
+
+ e_client_set_readonly (E_CLIENT (client), readonly);
+}
+
+static void
+online_cb (EGdbusCal *object, gboolean is_online, ECalClient *client)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (client));
+
+ e_client_set_online (E_CLIENT (client), is_online);
+}
+
+static void
+auth_required_cb (EGdbusCal *object, const gchar * const *credentials_strv, ECalClient *client)
+{
+ ECredentials *credentials;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (client));
+
+ if (credentials_strv)
+ credentials = e_credentials_new_strv (credentials_strv);
+ else
+ credentials = e_credentials_new ();
+
+ e_client_process_authentication (E_CLIENT (client), credentials);
+
+ e_credentials_free (credentials);
+}
+
+static void
+opened_cb (EGdbusCal *object, const gchar * const *error_strv, ECalClient *client)
+{
+ GError *error = NULL;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (client));
+ g_return_if_fail (error_strv != NULL);
+ g_return_if_fail (e_gdbus_templates_decode_error (error_strv, &error));
+
+ e_client_emit_opened (E_CLIENT (client), error);
+
+ if (error)
+ g_error_free (error);
+}
+
+static void
+free_busy_data_cb (EGdbusCal *object, const gchar * const *free_busy_strv, ECalClient *client)
+{
+ GSList *ecalcomps = NULL;
+ gint ii;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (client));
+ g_return_if_fail (free_busy_strv != NULL);
+
+
+ for (ii = 0; free_busy_strv[ii]; ii++) {
+ ECalComponent *comp;
+ icalcomponent *icalcomp;
+ icalcomponent_kind kind;
+
+ icalcomp = icalcomponent_new_from_string (free_busy_strv[ii]);
+ if (!icalcomp)
+ continue;
+
+ kind = icalcomponent_isa (icalcomp);
+ if (kind == ICAL_VFREEBUSY_COMPONENT) {
+ comp = e_cal_component_new ();
+ if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
+ icalcomponent_free (icalcomp);
+ g_object_unref (G_OBJECT (comp));
+ continue;
+ }
+
+ ecalcomps = g_slist_prepend (ecalcomps, comp);
+ } else {
+ icalcomponent_free (icalcomp);
+ }
+ }
+
+ ecalcomps = g_slist_reverse (ecalcomps);
+
+ g_signal_emit (client, signals[FREE_BUSY_DATA], 0, ecalcomps);
+
+ e_client_util_free_object_slist (ecalcomps);
+}
+
+static EDataCalObjType
+convert_type (ECalClientSourceType type)
+{
+ switch (type) {
+ case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
+ return Event;
+ case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
+ return Todo;
+ case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
+ return Journal;
+ default:
+ return AnyType;
+ }
+
+ return AnyType;
+}
+
+/**
+ * e_cal_client_new:
+ * @source: An #ESource pointer
+ * @source_type: source type of the calendar
+ * @error: A #GError pointer
+ *
+ * Creates a new #ECalClient corresponding to the given source. There are
+ * only two operations that are valid on this calendar at this point:
+ * e_client_open(), and e_client_remove().
+ *
+ * Returns: a new but unopened #ECalClient.
+ *
+ * Since: 3.2
+ **/
+ECalClient *
+e_cal_client_new (ESource *source, ECalClientSourceType source_type, GError **error)
+{
+ ECalClient *client;
+ GError *err = NULL;
+ GDBusConnection *connection;
+ gchar *xml, **strv;
+ gchar *path = NULL;
+
+ g_return_val_if_fail (source != NULL, NULL);
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+ g_return_val_if_fail (source_type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS || source_type == E_CAL_CLIENT_SOURCE_TYPE_TASKS || source_type == E_CAL_CLIENT_SOURCE_TYPE_MEMOS, NULL);
+
+ if (!gdbus_cal_factory_activate (&err)) {
+ if (err) {
+ unwrap_dbus_error (err, &err);
+ g_warning ("%s: Failed to run calendar factory: %s", G_STRFUNC, err->message);
+ g_propagate_error (error, err);
+ } else {
+ g_warning ("%s: Failed to run calendar factory: Unknown error", G_STRFUNC);
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_DBUS_ERROR, _("Failed to run calendar factory"));
+ }
+
+ return NULL;
+ }
+
+ xml = e_source_to_standalone_xml (source);
+ if (!xml || !*xml) {
+ g_free (xml);
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG, _("Invalid source"));
+ return NULL;
+ }
+
+ strv = e_gdbus_cal_factory_encode_get_cal (xml, convert_type (source_type));
+ if (!strv) {
+ g_free (xml);
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR, _("Other error"));
+ return NULL;
+ }
+
+ client = g_object_new (E_TYPE_CAL_CLIENT, "source", source, NULL);
+ client->priv->source_type = source_type;
+
+ if (!e_gdbus_cal_factory_call_get_cal_sync (G_DBUS_PROXY (cal_factory_proxy), (const gchar * const *) strv, &path, NULL, &err)) {
+ unwrap_dbus_error (err, &err);
+ g_free (xml);
+ g_strfreev (strv);
+ g_warning ("%s: Cannot get calendar from factory: %s", G_STRFUNC, err ? err->message : "[no error]");
+ if (err)
+ g_propagate_error (error, err);
+ g_object_unref (client);
+
+ return NULL;
+ }
+
+ g_free (xml);
+ g_strfreev (strv);
+
+ client->priv->gdbus_cal = G_DBUS_PROXY (e_gdbus_cal_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy)),
+ G_DBUS_PROXY_FLAGS_NONE,
+ CALENDAR_DBUS_SERVICE_NAME,
+ path,
+ NULL,
+ &err));
+
+ if (!client->priv->gdbus_cal) {
+ g_free (path);
+ unwrap_dbus_error (err, &err);
+ g_warning ("%s: Cannot create calendar proxy: %s", G_STRFUNC, err ? err->message : "Unknown error");
+ if (err)
+ g_propagate_error (error, err);
+
+ g_object_unref (client);
+
+ return NULL;
+ }
+
+ g_free (path);
+
+ connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (client->priv->gdbus_cal));
+ client->priv->gone_signal_id = g_dbus_connection_signal_subscribe (connection,
+ "org.freedesktop.DBus", /* sender */
+ "org.freedesktop.DBus", /* interface */
+ "NameOwnerChanged", /* member */
+ "/org/freedesktop/DBus", /* object_path */
+ "org.gnome.evolution.dataserver.Calendar", /* arg0 */
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ gdbus_cal_client_connection_gone_cb, client, NULL);
+
+ g_signal_connect (connection, "closed", G_CALLBACK (gdbus_cal_client_closed_cb), client);
+
+ g_signal_connect (client->priv->gdbus_cal, "backend_error", G_CALLBACK (backend_error_cb), client);
+ g_signal_connect (client->priv->gdbus_cal, "readonly", G_CALLBACK (readonly_cb), client);
+ g_signal_connect (client->priv->gdbus_cal, "online", G_CALLBACK (online_cb), client);
+ g_signal_connect (client->priv->gdbus_cal, "auth-required", G_CALLBACK (auth_required_cb), client);
+ g_signal_connect (client->priv->gdbus_cal, "opened", G_CALLBACK (opened_cb), client);
+ g_signal_connect (client->priv->gdbus_cal, "free-busy-data", G_CALLBACK (free_busy_data_cb), client);
+
+ return client;
+}
+
+/**
+ * e_cal_client_new_from_uri:
+ * @uri: the URI to load
+ * @source_type: source type of the calendar
+ * @error: A #GError pointer
+ *
+ * Creates a new #ECalClient corresponding to the given uri. See the
+ * documentation for e_cal_client_new() for further information.
+ *
+ * Returns: a new but unopened #ECalClient.
+ *
+ * Since: 3.2
+ **/
+ECalClient *
+e_cal_client_new_from_uri (const gchar *uri, ECalClientSourceType source_type, GError **error)
+{
+ ESourceList *source_list = NULL;
+ ESource *source;
+ ECalClient *client;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ if (!e_cal_client_get_sources (&source_list, source_type, error))
+ return NULL;
+
+ source = e_client_util_get_source_for_uri (source_list, uri);
+ if (!source && g_str_has_prefix (uri, "file://")) {
+ gchar *local_uri;
+
+ local_uri = g_strconcat ("local://", uri + 7, NULL);
+ source = e_client_util_get_source_for_uri (source_list, uri);
+
+ g_free (local_uri);
+ }
+
+ if (!source) {
+ g_object_unref (source_list);
+ g_set_error (error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG, _("Incorrect uri '%s'"), uri);
+
+ return NULL;
+ }
+
+ client = e_cal_client_new (source, source_type, error);
+
+ g_object_unref (source);
+ g_object_unref (source_list);
+
+ return client;
+}
+
+/**
+ * e_cal_client_new_system:
+ * @source_type: source type of the calendar
+ * @error: A #GError pointer
+ *
+ * Creates a new #ECalClient corresponding to the user's system
+ * calendar. See the documentation for e_cal_client_new() for further
+ * information.
+ *
+ * Returns: a new but unopened #ECalClient.
+ *
+ * Since: 3.2
+ **/
+ECalClient *
+e_cal_client_new_system (ECalClientSourceType source_type, GError **error)
+{
+ ESourceList *source_list = NULL;
+ ESource *source;
+ ECalClient *client;
+
+ if (!e_cal_client_get_sources (&source_list, source_type, error))
+ return NULL;
+
+ source = e_client_util_get_system_source (source_list);
+ if (!source) {
+ g_object_unref (source_list);
+ g_set_error_literal (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR, _("Failed to find system calendar"));
+
+ return NULL;
+ }
+
+ client = e_cal_client_new (source, source_type, error);
+
+ g_object_unref (source);
+ g_object_unref (source_list);
+
+ return client;
+}
+
+/**
+ * e_cal_client_new_default:
+ * @source_type: source type of the calendar
+ * @error: return location for a #GError, or %NULL
+ *
+ * Creates a new #ECalClient corresponding to the user's default
+ * calendar. See the documentation for e_cal_client_new() for
+ * further information.
+ *
+ * Returns: a new but unopened #ECalClient
+ *
+ * Since: 3.2
+ **/
+ECalClient *
+e_cal_client_new_default (ECalClientSourceType source_type, GError **error)
+{
+ ESourceList *source_list = NULL;
+ ESource *source;
+ ECalClient *client;
+
+ if (!e_cal_client_get_sources (&source_list, source_type, error))
+ return NULL;
+
+ source = e_source_list_peek_default_source (source_list);
+ if (!source) {
+ g_set_error_literal (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR, _("Calendar does not exist"));
+ g_object_unref (source_list);
+
+ return NULL;
+ }
+
+ client = e_cal_client_new (source, source_type, error);
+
+ g_object_unref (source_list);
+
+ return client;
+}
+
+/**
+ * e_cal_client_set_default:
+ * @client: An #ECalClient pointer
+ * @error: A #GError pointer
+ *
+ * Sets the #ESource of the #ECalClient as the "default" calendar. This is the source
+ * that will be loaded in the e_cal_client_get_default_calendar() call.
+ *
+ * Returns: %TRUE if the setting was stored in libecal's ESourceList, otherwise %FALSE.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_set_default (ECalClient *client, GError **error)
+{
+ ESource *source;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+
+ source = e_client_get_source (E_CLIENT (client));
+ g_return_val_if_fail (source != NULL, FALSE);
+
+ return e_cal_client_set_default_source (source, e_cal_client_get_source_type (client), error);
+}
+
+/**
+ * e_cal_client_set_default_source:
+ * @source: An #ESource pointer
+ * @source_type: source type of the calendar
+ * @error: A #GError pointer
+ *
+ * Sets @source as the "default" calendar. This is the source that
+ * will be loaded in the e_cal_client_get_default_calendar() call.
+ *
+ * Returns: %TRUE if the setting was stored in libecal's ESourceList, otherwise %FALSE.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_set_default_source (ESource *source, ECalClientSourceType source_type, GError **error)
+{
+ ESourceList *source_list = NULL;
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (source != NULL, FALSE);
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+ if (!e_cal_client_get_sources (&source_list, source_type, error))
+ return FALSE;
+
+ res = e_client_util_set_default (source_list, source);
+
+ if (res)
+ res = e_source_list_sync (source_list, error);
+ else
+ g_set_error (error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG,
+ _("There was no source for UID '%s' stored in a source list."), e_source_peek_uid (source));
+
+ g_object_unref (source_list);
+
+ return res;
+}
+
+/**
+ * e_cal_client_get_sources:
+ * @sources: (out): A pointer to an #ESourceList to set
+ * @source_type: source type of calendars
+ * @error: A pointer to a GError to set on error
+ *
+ * Populate @*sources with the list of all sources which have been
+ * added to Evolution.
+ *
+ * Returns: %TRUE if @sources was set, otherwise %FALSE.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_sources (ESourceList **sources, ECalClientSourceType source_type, GError **error)
+{
+ GConfClient *gconf;
+ const gchar *key = NULL;
+
+ g_return_val_if_fail (sources != NULL, FALSE);
+
+ switch (source_type) {
+ case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
+ key = "/apps/evolution/calendar/sources";
+ break;
+ case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
+ key = "/apps/evolution/tasks/sources";
+ break;
+ case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
+ key = "/apps/evolution/memos/sources";
+ break;
+ default:
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG, _("Invalid source type"));
+ return FALSE;
+ }
+
+ g_return_val_if_fail (key != NULL, FALSE);
+
+ gconf = gconf_client_get_default ();
+ *sources = e_source_list_new_for_gconf (gconf, key);
+ g_object_unref (gconf);
+
+ return TRUE;
+}
+
+/**
+ * e_cal_client_get_source_type:
+ * @client: A calendar client.
+ *
+ * Gets the source type of the calendar client.
+ *
+ * Returns: an #ECalClientSourceType value corresponding
+ * to the source type of the calendar client.
+ *
+ * Since: 3.2
+ **/
+ECalClientSourceType
+e_cal_client_get_source_type (ECalClient *client)
+{
+ g_return_val_if_fail (client != NULL, E_CAL_CLIENT_SOURCE_TYPE_LAST);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), E_CAL_CLIENT_SOURCE_TYPE_LAST);
+ g_return_val_if_fail (client->priv != NULL, E_CAL_CLIENT_SOURCE_TYPE_LAST);
+
+ return client->priv->source_type;
+}
+
+/**
+ * e_cal_client_get_local_attachment_store
+ * @client: A calendar client.
+ *
+ * Queries the URL where the calendar attachments are
+ * serialized in the local filesystem. This enable clients
+ * to operate with the reference to attachments rather than the data itself
+ * unless it specifically uses the attachments for open/sending
+ * operations.
+ *
+ * Returns: The URL where the attachments are serialized in the
+ * local filesystem.
+ *
+ * Since: 3.2
+ **/
+const gchar *
+e_cal_client_get_local_attachment_store (ECalClient *client)
+{
+ gchar *cache_dir = NULL;
+ GError *error = NULL;
+
+ g_return_val_if_fail (client != NULL, NULL);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
+ g_return_val_if_fail (client->priv != NULL, NULL);
+
+ if (client->priv->cache_dir || !client->priv->gdbus_cal)
+ return client->priv->cache_dir;
+
+ e_gdbus_cal_call_get_backend_property_sync (client->priv->gdbus_cal, CLIENT_BACKEND_PROPERTY_CACHE_DIR, &cache_dir, NULL, &error);
+
+ if (error == NULL) {
+ client->priv->cache_dir = cache_dir;
+ } else {
+ unwrap_dbus_error (error, &error);
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ return client->priv->cache_dir;
+}
+
+/**
+ * e_cal_client_set_default_timezone:
+ * @client: A calendar client.
+ * @zone: A timezone object.
+ *
+ * Sets the default timezone to use to resolve DATE and floating DATE-TIME
+ * values. This will typically be from the user's timezone setting. Call this
+ * before using any other object fetching functions.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_set_default_timezone (ECalClient *client, /* const */ icaltimezone *zone)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+ g_return_if_fail (zone != NULL);
+
+ icaltimezone_free (client->priv->default_zone, 1);
+ client->priv->default_zone = icaltimezone_copy (zone);
+}
+
+/**
+ * e_cal_client_get_default_timezone:
+ * @client: A calendar client.
+ *
+ * Returns: Default timezone previously set with e_cal_client_set_default_timezone().
+ * Returned pointer is owned by the @client and should not be freed.
+ *
+ * Since: 3.2
+ **/
+/* const */ icaltimezone *
+e_cal_client_get_default_timezone (ECalClient *client)
+{
+ g_return_val_if_fail (client != NULL, NULL);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
+ g_return_val_if_fail (client->priv != NULL, NULL);
+
+ return client->priv->default_zone;
+}
+
+/**
+ * e_cal_client_check_one_alarm_only:
+ * @client: A calendar client.
+ *
+ * Checks if a calendar supports only one alarm per component.
+ *
+ * Returns: TRUE if the calendar allows only one alarm, FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_check_one_alarm_only (ECalClient *client)
+{
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+ return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY);
+}
+
+/**
+ * e_cal_client_check_save_schedules:
+ * @client: A calendar client.
+ *
+ * Checks whether the calendar saves schedules.
+ *
+ * Returns: TRUE if it saves schedules, FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_check_save_schedules (ECalClient *client)
+{
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+ return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
+}
+
+/**
+ * e_cal_client_check_organizer_must_attend:
+ * @client: A calendar client.
+ *
+ * Checks if a calendar forces organizers of meetings to be also attendees.
+ *
+ * Returns: TRUE if the calendar forces organizers to attend meetings,
+ * FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_check_organizer_must_attend (ECalClient *client)
+{
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+ return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ATTEND);
+}
+
+/**
+ * e_cal_get_organizer_must_accept:
+ * @client: A calendar client.
+ *
+ * Checks whether a calendar requires organizer to accept their attendance to
+ * meetings.
+ *
+ * Returns: TRUE if the calendar requires organizers to accept, FALSE
+ * otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_check_organizer_must_accept (ECalClient *client)
+{
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+ return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ACCEPT);
+}
+
+/**
+ * e_cal_client_check_recurrences_no_master:
+ * @client: A calendar client.
+ *
+ * Checks if the calendar has a master object for recurrences.
+ *
+ * Returns: TRUE if the calendar has a master object for recurrences,
+ * FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_check_recurrences_no_master (ECalClient *client)
+{
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+ return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER);
+}
+
+/**
+ * e_cal_client_free_icalcomp_slist:
+ * @icalcomps: slist of icalcomponent objects
+ *
+ * Frees each element of @icalcomps list and the list itself.
+ * Each element is an object of icalcomponent type.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_free_icalcomp_slist (GSList *icalcomps)
+{
+ g_slist_foreach (icalcomps, (GFunc) icalcomponent_free, NULL);
+ g_slist_free (icalcomps);
+}
+
+/**
+ * e_cal_client_free_ecalcomp_slist:
+ * @ecalcomps: list of ECalComponent objects
+ *
+ * Frees each element of @ecalcomps list and the list itself.
+ * Each element is an object of ECalComponent type.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_free_ecalcomp_slist (GSList *ecalcomps)
+{
+ g_slist_foreach (ecalcomps, (GFunc) g_object_unref, NULL);
+ g_slist_free (ecalcomps);
+}
+
+/**
+ * e_cal_client_resolve_tzid_cb:
+ * @tzid: ID of the timezone to resolve.
+ * @data: Closure data for the callback, in this case #ECalClient.
+ *
+ * Resolves TZIDs for the recurrence generator.
+ *
+ * Returns: The timezone identified by the @tzid argument, or %NULL if
+ * it could not be found.
+ */
+icaltimezone *
+e_cal_client_resolve_tzid_cb (const gchar *tzid, gpointer data)
+{
+ ECalClient *client = data;
+ icaltimezone *zone = NULL;
+ GError *error = NULL;
+
+ g_return_val_if_fail (client != NULL, NULL);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
+
+ e_cal_client_get_timezone_sync (client, tzid, &zone, NULL, &error);
+
+ if (error) {
+ g_debug ("%s: Failed to find '%s' timezone: %s", G_STRFUNC, tzid, error->message);
+ g_error_free (error);
+ }
+
+ return zone;
+}
+
+struct comp_instance {
+ ECalComponent *comp;
+ time_t start;
+ time_t end;
+};
+
+struct instances_info {
+ GSList **instances;
+ icaltimezone *start_zone;
+};
+
+/* Called from cal_recur_generate_instances(); adds an instance to the list */
+static gboolean
+add_instance (ECalComponent *comp, time_t start, time_t end, gpointer data)
+{
+ GSList **list;
+ struct comp_instance *ci;
+ struct icaltimetype itt;
+ icalcomponent *icalcomp;
+ struct instances_info *instances_hold;
+
+ instances_hold = data;
+ list = instances_hold->instances;
+
+ ci = g_new (struct comp_instance, 1);
+
+ icalcomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp));
+
+ /* add the instance to the list */
+ ci->comp = e_cal_component_new ();
+ e_cal_component_set_icalcomponent (ci->comp, icalcomp);
+
+ /* set the RECUR-ID for the instance */
+ if (e_cal_util_component_has_recurrences (icalcomp)) {
+ if (!(icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY))) {
+ ECalComponentRange *range;
+ ECalComponentDateTime datetime;
+
+ e_cal_component_get_dtstart (comp, &datetime);
+
+ if (instances_hold->start_zone)
+ itt = icaltime_from_timet_with_zone (start, datetime.value->is_date, instances_hold->start_zone);
+ else {
+ itt = icaltime_from_timet (start, datetime.value->is_date);
+
+ if (datetime.tzid) {
+ g_free ((gchar *) datetime.tzid);
+ datetime.tzid = NULL;
+ }
+ }
+
+ g_free (datetime.value);
+ datetime.value = &itt;
+
+ range = g_new0 (ECalComponentRange, 1);
+ range->type = E_CAL_COMPONENT_RANGE_SINGLE;
+ range->datetime = datetime;
+
+ e_cal_component_set_recurid (ci->comp, range);
+
+ if (datetime.tzid)
+ g_free ((gchar *) datetime.tzid);
+ g_free (range);
+ }
+ }
+
+ ci->start = start;
+ ci->end = end;
+
+ *list = g_slist_prepend (*list, ci);
+
+ return TRUE;
+}
+
+/* Used from g_slist_sort(); compares two struct comp_instance structures */
+static gint
+compare_comp_instance (gconstpointer a, gconstpointer b)
+{
+ const struct comp_instance *cia, *cib;
+ time_t diff;
+
+ cia = a;
+ cib = b;
+
+ diff = cia->start - cib->start;
+ return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
+}
+
+static GSList *
+process_detached_instances (GSList *instances, GSList *detached_instances)
+{
+ struct comp_instance *ci, *cid;
+ GSList *dl, *unprocessed_instances = NULL;
+
+ for (dl = detached_instances; dl != NULL; dl = dl->next) {
+ GSList *il;
+ const gchar *uid;
+ gboolean processed;
+ ECalComponentRange recur_id, instance_recur_id;
+
+ processed = FALSE;
+
+ cid = dl->data;
+ e_cal_component_get_uid (cid->comp, &uid);
+ e_cal_component_get_recurid (cid->comp, &recur_id);
+
+ /* search for coincident instances already expanded */
+ for (il = instances; il != NULL; il = il->next) {
+ const gchar *instance_uid;
+ gint cmp;
+
+ ci = il->data;
+ e_cal_component_get_uid (ci->comp, &instance_uid);
+ e_cal_component_get_recurid (ci->comp, &instance_recur_id);
+ if (strcmp (uid, instance_uid) == 0) {
+ gchar *i_rid = NULL, *d_rid = NULL;
+
+ i_rid = e_cal_component_get_recurid_as_string (ci->comp);
+ d_rid = e_cal_component_get_recurid_as_string (cid->comp);
+
+ if (i_rid && d_rid && strcmp (i_rid, d_rid) == 0) {
+ g_object_unref (ci->comp);
+ ci->comp = g_object_ref (cid->comp);
+ ci->start = cid->start;
+ ci->end = cid->end;
+
+ processed = TRUE;
+ } else {
+ if (!instance_recur_id.datetime.value ||
+ !recur_id.datetime.value) {
+ /*
+ * Prevent obvious segfault by ignoring missing
+ * recurrency ids. Real problem might be elsewhere,
+ * but anything is better than crashing...
+ */
+ g_log (G_LOG_DOMAIN,
+ G_LOG_LEVEL_CRITICAL,
+ "UID %s: instance RECURRENCE-ID %s + detached instance RECURRENCE-ID %s: cannot compare",
+ uid,
+ i_rid,
+ d_rid);
+
+ e_cal_component_free_datetime (&instance_recur_id.datetime);
+ g_free (i_rid);
+ g_free (d_rid);
+ continue;
+ }
+ cmp = icaltime_compare (*instance_recur_id.datetime.value,
+ *recur_id.datetime.value);
+ if ((recur_id.type == E_CAL_COMPONENT_RANGE_THISPRIOR && cmp <= 0) ||
+ (recur_id.type == E_CAL_COMPONENT_RANGE_THISFUTURE && cmp >= 0)) {
+ ECalComponent *comp;
+
+ comp = e_cal_component_new ();
+ e_cal_component_set_icalcomponent (
+ comp,
+ icalcomponent_new_clone (e_cal_component_get_icalcomponent (cid->comp)));
+ e_cal_component_set_recurid (comp, &instance_recur_id);
+
+ /* replace the generated instances */
+ g_object_unref (ci->comp);
+ ci->comp = comp;
+ }
+ }
+ g_free (i_rid);
+ g_free (d_rid);
+ }
+ e_cal_component_free_datetime (&instance_recur_id.datetime);
+ }
+
+ e_cal_component_free_datetime (&recur_id.datetime);
+
+ if (!processed)
+ unprocessed_instances = g_slist_prepend (unprocessed_instances, cid);
+ }
+
+ /* add the unprocessed instances (ie, detached instances with no master object */
+ while (unprocessed_instances != NULL) {
+ cid = unprocessed_instances->data;
+ ci = g_new0 (struct comp_instance, 1);
+ ci->comp = g_object_ref (cid->comp);
+ ci->start = cid->start;
+ ci->end = cid->end;
+ instances = g_slist_append (instances, ci);
+
+ unprocessed_instances = g_slist_remove (unprocessed_instances, cid);
+ }
+
+ return instances;
+}
+
+static void
+generate_instances (ECalClient *client, time_t start, time_t end, const gchar *uid,
+ ECalRecurInstanceFn cb, gpointer cb_data)
+{
+ GSList *objects = NULL;
+ GSList *instances, *detached_instances = NULL;
+ GSList *l;
+ gchar *query;
+ gchar *iso_start, *iso_end;
+ ECalClientPrivate *priv;
+
+ priv = client->priv;
+
+ /* Generate objects */
+ if (uid && *uid) {
+ GError *error = NULL;
+ gint tries = 0;
+
+ try_again:
+ if (!e_cal_client_get_objects_for_uid_sync (client, uid, &objects, NULL, &error)) {
+ if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_BUSY) && tries >= 10) {
+ tries++;
+ g_usleep (500);
+ g_clear_error (&error);
+
+ goto try_again;
+ }
+
+ unwrap_dbus_error (error, &error);
+ g_message ("Failed to get recurrence objects for uid %s \n", error ? error->message : "Unknown error");
+ g_clear_error (&error);
+ return;
+ }
+ } else {
+ iso_start = isodate_from_time_t (start);
+ if (!iso_start)
+ return;
+
+ iso_end = isodate_from_time_t (end);
+ if (!iso_end) {
+ g_free (iso_start);
+ return;
+ }
+
+ query = g_strdup_printf ("(occur-in-time-range? (make-time \"%s\") (make-time \"%s\"))",
+ iso_start, iso_end);
+ g_free (iso_start);
+ g_free (iso_end);
+ if (!e_cal_client_get_object_list_as_comps_sync (client, query, &objects, NULL, NULL)) {
+ g_free (query);
+ return;
+ }
+ g_free (query);
+ }
+
+ instances = NULL;
+
+ for (l = objects; l; l = l->next) {
+ ECalComponent *comp;
+ icaltimezone *default_zone;
+
+ if (priv->default_zone)
+ default_zone = priv->default_zone;
+ else
+ default_zone = icaltimezone_get_utc_timezone ();
+
+ comp = l->data;
+ if (e_cal_component_is_instance (comp)) {
+ struct comp_instance *ci;
+ ECalComponentDateTime dtstart, dtend;
+ icaltimezone *start_zone = NULL, *end_zone = NULL;
+
+ /* keep the detached instances apart */
+ ci = g_new0 (struct comp_instance, 1);
+ ci->comp = comp;
+
+ e_cal_component_get_dtstart (comp, &dtstart);
+ e_cal_component_get_dtend (comp, &dtend);
+
+ /* For DATE-TIME values with a TZID, we use
+ e_cal_resolve_tzid_cb to resolve the TZID.
+ For DATE values and DATE-TIME values without a
+ TZID (i.e. floating times) we use the default
+ timezone. */
+ if (dtstart.tzid && !dtstart.value->is_date) {
+ start_zone = e_cal_client_resolve_tzid_cb (dtstart.tzid, client);
+ if (!start_zone)
+ start_zone = default_zone;
+ } else {
+ start_zone = default_zone;
+ }
+
+ if (dtend.tzid && !dtend.value->is_date) {
+ end_zone = e_cal_client_resolve_tzid_cb (dtend.tzid, client);
+ if (!end_zone)
+ end_zone = default_zone;
+ } else {
+ end_zone = default_zone;
+ }
+
+ ci->start = icaltime_as_timet_with_zone (*dtstart.value, start_zone);
+
+ if (dtend.value)
+ ci->end = icaltime_as_timet_with_zone (*dtend.value, end_zone);
+ else if (icaltime_is_date (*dtstart.value))
+ ci->end = time_day_end (ci->start);
+ else
+ ci->end = ci->start;
+
+ e_cal_component_free_datetime (&dtstart);
+ e_cal_component_free_datetime (&dtend);
+
+ if (ci->start <= end && ci->end >= start) {
+ detached_instances = g_slist_prepend (detached_instances, ci);
+ } else {
+ /* it doesn't fit to our time range, thus skip it */
+ g_object_unref (G_OBJECT (ci->comp));
+ g_free (ci);
+ }
+ } else {
+ ECalComponentDateTime datetime;
+ icaltimezone *start_zone;
+ struct instances_info *instances_hold;
+
+ /* Get the start timezone */
+ e_cal_component_get_dtstart (comp, &datetime);
+ e_cal_client_get_timezone_sync (client, datetime.tzid, &start_zone, NULL, NULL);
+ e_cal_component_free_datetime (&datetime);
+
+ instances_hold = g_new0 (struct instances_info, 1);
+ instances_hold->instances = &instances;
+ instances_hold->start_zone = start_zone;
+
+ e_cal_recur_generate_instances (comp, start, end, add_instance, instances_hold,
+ e_cal_client_resolve_tzid_cb, client,
+ default_zone);
+
+ g_free (instances_hold);
+ g_object_unref (comp);
+ }
+ }
+
+ g_slist_free (objects);
+
+ /* Generate instances and spew them out */
+
+ instances = g_slist_sort (instances, compare_comp_instance);
+ instances = process_detached_instances (instances, detached_instances);
+
+ for (l = instances; l; l = l->next) {
+ struct comp_instance *ci;
+ gboolean result;
+
+ ci = l->data;
+
+ result = (* cb) (ci->comp, ci->start, ci->end, cb_data);
+
+ if (!result)
+ break;
+ }
+
+ /* Clean up */
+
+ for (l = instances; l; l = l->next) {
+ struct comp_instance *ci;
+
+ ci = l->data;
+ g_object_unref (G_OBJECT (ci->comp));
+ g_free (ci);
+ }
+
+ g_slist_free (instances);
+
+ for (l = detached_instances; l; l = l->next) {
+ struct comp_instance *ci;
+
+ ci = l->data;
+ g_object_unref (G_OBJECT (ci->comp));
+ g_free (ci);
+ }
+
+ g_slist_free (detached_instances);
+}
+
+/**
+ * e_cal_generate_instances:
+ * @client: A calendar client.
+ * @start: Start time for query.
+ * @end: End time for query.
+ * @cb: Callback for each generated instance.
+ * @cb_data: Closure data for the callback.
+ *
+ * Does a combination of #e_cal_client_get_object_list () and
+ * #e_cal_client_recur_generate_instances().
+ *
+ * The callback function should do a g_object_ref() of the calendar component
+ * it gets passed if it intends to keep it around, since it will be unref'ed
+ * as soon as the callback returns.
+ **/
+void
+e_cal_client_generate_instances (ECalClient *client, time_t start, time_t end, ECalRecurInstanceFn cb, gpointer cb_data)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (client));
+ g_return_if_fail (e_client_is_opened (E_CLIENT (client)));
+
+ g_return_if_fail (start >= 0);
+ g_return_if_fail (end >= 0);
+ g_return_if_fail (cb != NULL);
+
+ generate_instances (client, start, end, NULL, cb, cb_data);
+}
+
+/**
+ * e_cal_client_generate_instances_for_object:
+ * @client: A calendar client.
+ * @icalcomp: Object to generate instances from.
+ * @start: Start time for query.
+ * @end: End time for query.
+ * @cb: Callback for each generated instance.
+ * @cb_data: Closure data for the callback.
+ *
+ * Does a combination of #e_cal_client_get_object_list () and
+ * #e_cal_client_recur_generate_instances(), like #e_cal_client_generate_instances(), but
+ * for a single object.
+ *
+ * The callback function should do a g_object_ref() of the calendar component
+ * it gets passed if it intends to keep it around, since it will be unref'ed
+ * as soon as the callback returns.
+ **/
+void
+e_cal_client_generate_instances_for_object (ECalClient *client, icalcomponent *icalcomp, time_t start, time_t end, ECalRecurInstanceFn cb, gpointer cb_data)
+{
+ ECalComponent *comp;
+ const gchar *uid;
+ gchar *rid;
+ gboolean result;
+ GSList *instances = NULL;
+ ECalComponentDateTime datetime;
+ icaltimezone *start_zone;
+ struct instances_info *instances_hold;
+ gboolean is_single_instance = FALSE;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (client));
+ g_return_if_fail (e_client_is_opened (E_CLIENT (client)));
+
+ g_return_if_fail (start >= 0);
+ g_return_if_fail (end >= 0);
+ g_return_if_fail (cb != NULL);
+
+ comp = e_cal_component_new ();
+ e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp));
+
+ if (!e_cal_component_has_recurrences (comp))
+ is_single_instance = TRUE;
+
+ /* If the backend stores it as individual instances and does not
+ * have a master object - do not expand */
+ if (is_single_instance || e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER)) {
+ /* return the same instance */
+ result = (* cb) (comp, icaltime_as_timet_with_zone (icalcomponent_get_dtstart (icalcomp), client->priv->default_zone),
+ icaltime_as_timet_with_zone (icalcomponent_get_dtend (icalcomp), client->priv->default_zone), cb_data);
+ g_object_unref (comp);
+ return;
+ }
+
+ e_cal_component_get_uid (comp, &uid);
+ rid = e_cal_component_get_recurid_as_string (comp);
+
+ /* Get the start timezone */
+ e_cal_component_get_dtstart (comp, &datetime);
+ e_cal_client_get_timezone_sync (client, datetime.tzid, &start_zone, NULL, NULL);
+ e_cal_component_free_datetime (&datetime);
+
+ instances_hold = g_new0 (struct instances_info, 1);
+ instances_hold->instances = &instances;
+ instances_hold->start_zone = start_zone;
+
+ /* generate all instances in the given time range */
+ generate_instances (client, start, end, uid, add_instance, instances_hold);
+
+ instances = *(instances_hold->instances);
+ /* now only return back the instances for the given object */
+ result = TRUE;
+ while (instances != NULL) {
+ struct comp_instance *ci;
+ gchar *instance_rid = NULL;
+
+ ci = instances->data;
+
+ if (result) {
+ instance_rid = e_cal_component_get_recurid_as_string (ci->comp);
+
+ if (rid && *rid) {
+ if (instance_rid && *instance_rid && strcmp (rid, instance_rid) == 0)
+ result = (* cb) (ci->comp, ci->start, ci->end, cb_data);
+ } else
+ result = (* cb) (ci->comp, ci->start, ci->end, cb_data);
+ }
+
+ /* remove instance from list */
+ instances = g_slist_remove (instances, ci);
+ g_object_unref (ci->comp);
+ g_free (ci);
+ g_free (instance_rid);
+ }
+
+ /* clean up */
+ g_object_unref (comp);
+ g_free (instances_hold);
+ g_free (rid);
+}
+
+typedef struct _ForeachTZIDCallbackData ForeachTZIDCallbackData;
+struct _ForeachTZIDCallbackData {
+ ECalClient *client;
+ GHashTable *timezone_hash;
+ gboolean success;
+};
+
+/* This adds the VTIMEZONE given by the TZID parameter to the GHashTable in
+ data. */
+static void
+foreach_tzid_callback (icalparameter *param, gpointer cbdata)
+{
+ ForeachTZIDCallbackData *data = cbdata;
+ const gchar *tzid;
+ icaltimezone *zone = NULL;
+ icalcomponent *vtimezone_comp;
+ gchar *vtimezone_as_string;
+
+ /* Get the TZID string from the parameter. */
+ tzid = icalparameter_get_tzid (param);
+ if (!tzid)
+ return;
+
+ /* Check if we've already added it to the GHashTable. */
+ if (g_hash_table_lookup (data->timezone_hash, tzid))
+ return;
+
+ if (!e_cal_client_get_timezone_sync (data->client, tzid, &zone, NULL, NULL) || !zone) {
+ data->success = FALSE;
+ return;
+ }
+
+ /* Convert it to a string and add it to the hash. */
+ vtimezone_comp = icaltimezone_get_component (zone);
+ if (!vtimezone_comp)
+ return;
+
+ vtimezone_as_string = icalcomponent_as_ical_string_r (vtimezone_comp);
+
+ g_hash_table_insert (data->timezone_hash, (gchar *) tzid, vtimezone_as_string);
+}
+
+/* This appends the value string to the GString given in data. */
+static void
+append_timezone_string (gpointer key, gpointer value, gpointer data)
+{
+ GString *vcal_string = data;
+
+ g_string_append (vcal_string, value);
+ g_free (value);
+}
+
+/* This simply frees the hash values. */
+static void
+free_timezone_string (gpointer key, gpointer value, gpointer data)
+{
+ g_free (value);
+}
+
+/**
+ * e_cal_client_get_component_as_string:
+ * @client: A calendar client.
+ * @icalcomp: A calendar component object.
+ *
+ * Gets a calendar component as an iCalendar string, with a toplevel
+ * VCALENDAR component and all VTIMEZONEs needed for the component.
+ *
+ * Returns: the component as a complete iCalendar string, or NULL on
+ * failure. The string should be freed with g_free().
+ *
+ * Since: 3.2
+ **/
+gchar *
+e_cal_client_get_component_as_string (ECalClient *client, icalcomponent *icalcomp)
+{
+ GHashTable *timezone_hash;
+ GString *vcal_string;
+ ForeachTZIDCallbackData cbdata;
+ gchar *obj_string;
+
+ g_return_val_if_fail (client != NULL, NULL);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
+ g_return_val_if_fail (client->priv != NULL, NULL);
+ g_return_val_if_fail (icalcomp != NULL, NULL);
+
+ timezone_hash = g_hash_table_new (g_str_hash, g_str_equal);
+
+ /* Add any timezones needed to the hash. We use a hash since we only
+ want to add each timezone once at most. */
+ cbdata.client = client;
+ cbdata.timezone_hash = timezone_hash;
+ cbdata.success = TRUE;
+ icalcomponent_foreach_tzid (icalcomp, foreach_tzid_callback, &cbdata);
+ if (!cbdata.success) {
+ g_hash_table_foreach (timezone_hash, free_timezone_string, NULL);
+ return NULL;
+ }
+
+ /* Create the start of a VCALENDAR, to add the VTIMEZONES to,
+ and remember its length so we know if any VTIMEZONEs get added. */
+ vcal_string = g_string_new (NULL);
+ g_string_append (vcal_string,
+ "BEGIN:VCALENDAR\n"
+ "PRODID:-//Ximian//NONSGML Evolution Calendar//EN\n"
+ "VERSION:2.0\n"
+ "METHOD:PUBLISH\n");
+
+ /* Now concatenate all the timezone strings. This also frees the
+ timezone strings as it goes. */
+ g_hash_table_foreach (timezone_hash, append_timezone_string, vcal_string);
+
+ /* Get the string for the VEVENT/VTODO. */
+ obj_string = icalcomponent_as_ical_string_r (icalcomp);
+
+ /* If there were any timezones to send, create a complete VCALENDAR,
+ else just send the VEVENT/VTODO string. */
+ g_string_append (vcal_string, obj_string);
+ g_string_append (vcal_string, "END:VCALENDAR\n");
+ g_free (obj_string);
+
+ obj_string = g_string_free (vcal_string, FALSE);
+
+ g_hash_table_destroy (timezone_hash);
+
+ return obj_string;
+}
+
+static void
+cal_client_get_backend_property (EClient *client, const gchar *prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_client_proxy_call_string (client, prop_name, cancellable, callback, user_data, cal_client_get_backend_property,
+ e_gdbus_cal_call_get_backend_property,
+ NULL, NULL, e_gdbus_cal_call_get_backend_property_finish, NULL, NULL);
+}
+
+static gboolean
+cal_client_get_backend_property_finish (EClient *client, GAsyncResult *result, gchar **prop_value, GError **error)
+{
+ return e_client_proxy_call_finish_string (client, result, prop_value, error, cal_client_get_backend_property);
+}
+
+static gboolean
+cal_client_get_backend_property_sync (EClient *client, const gchar *prop_name, gchar **prop_value, GCancellable *cancellable, GError **error)
+{
+ ECalClient *cal_client;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+ cal_client = E_CAL_CLIENT (client);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (cal_client->priv != NULL, FALSE);
+
+ if (!cal_client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ return e_client_proxy_call_sync_string__string (client, prop_name, prop_value, cancellable, error, e_gdbus_cal_call_get_backend_property_sync);
+}
+
+static void
+cal_client_set_backend_property (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar **prop_name_value;
+
+ prop_name_value = e_gdbus_cal_encode_set_backend_property (prop_name, prop_value);
+
+ e_client_proxy_call_strv (client, (const gchar * const *) prop_name_value, cancellable, callback, user_data, cal_client_set_backend_property,
+ e_gdbus_cal_call_set_backend_property,
+ e_gdbus_cal_call_set_backend_property_finish, NULL, NULL, NULL, NULL);
+
+ g_strfreev (prop_name_value);
+}
+
+static gboolean
+cal_client_set_backend_property_finish (EClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (client, result, error, cal_client_set_backend_property);
+}
+
+static gboolean
+cal_client_set_backend_property_sync (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GError **error)
+{
+ ECalClient *cal_client;
+ gboolean res;
+ gchar **prop_name_value;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+ cal_client = E_CAL_CLIENT (client);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (cal_client->priv != NULL, FALSE);
+
+ if (!cal_client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ prop_name_value = e_gdbus_cal_encode_set_backend_property (prop_name, prop_value);
+ res = e_client_proxy_call_sync_strv__void (client, (const gchar * const *) prop_name_value, cancellable, error, e_gdbus_cal_call_set_backend_property_sync);
+ g_strfreev (prop_name_value);
+
+ return res;
+}
+
+static void
+cal_client_open (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_client_proxy_call_boolean (client, only_if_exists, cancellable, callback, user_data, cal_client_open,
+ e_gdbus_cal_call_open,
+ e_gdbus_cal_call_open_finish, NULL, NULL, NULL, NULL);
+}
+
+static gboolean
+cal_client_open_finish (EClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (client, result, error, cal_client_open);
+}
+
+static gboolean
+cal_client_open_sync (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error)
+{
+ ECalClient *cal_client;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+ cal_client = E_CAL_CLIENT (client);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (cal_client->priv != NULL, FALSE);
+
+ if (!cal_client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ return e_client_proxy_call_sync_boolean__void (client, only_if_exists, cancellable, error, e_gdbus_cal_call_open_sync);
+}
+
+static void
+cal_client_remove (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_client_proxy_call_void (client, cancellable, callback, user_data, cal_client_remove,
+ e_gdbus_cal_call_remove,
+ e_gdbus_cal_call_remove_finish, NULL, NULL, NULL, NULL);
+}
+
+static gboolean
+cal_client_remove_finish (EClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (client, result, error, cal_client_remove);
+}
+
+static gboolean
+cal_client_remove_sync (EClient *client, GCancellable *cancellable, GError **error)
+{
+ ECalClient *cal_client;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+ cal_client = E_CAL_CLIENT (client);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (cal_client->priv != NULL, FALSE);
+
+ if (!cal_client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ return e_client_proxy_call_sync_void__void (client, cancellable, error, e_gdbus_cal_call_remove_sync);
+}
+
+static void
+cal_client_refresh (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_client_proxy_call_void (client, cancellable, callback, user_data, cal_client_refresh,
+ e_gdbus_cal_call_refresh,
+ e_gdbus_cal_call_refresh_finish, NULL, NULL, NULL, NULL);
+}
+
+static gboolean
+cal_client_refresh_finish (EClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (client, result, error, cal_client_refresh);
+}
+
+static gboolean
+cal_client_refresh_sync (EClient *client, GCancellable *cancellable, GError **error)
+{
+ ECalClient *cal_client;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+ cal_client = E_CAL_CLIENT (client);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (cal_client->priv != NULL, FALSE);
+
+ if (!cal_client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ return e_client_proxy_call_sync_void__void (client, cancellable, error, e_gdbus_cal_call_refresh_sync);
+}
+
+static gboolean
+complete_string_exchange (gboolean res, gchar *out_string, gchar **result, GError **error)
+{
+ g_return_val_if_fail (result != NULL, FALSE);
+
+ if (res && out_string) {
+ if (*out_string) {
+ *result = out_string;
+ } else {
+ /* empty string is returned as NULL */
+ *result = NULL;
+ g_free (out_string);
+ }
+ } else {
+ *result = NULL;
+ g_free (out_string);
+ res = FALSE;
+
+ if (error && !*error)
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG, e_client_error_to_string (E_CLIENT_ERROR_INVALID_ARG));
+ }
+
+ return res;
+}
+
+/**
+ * e_cal_client_get_default_object:
+ * @client: an #ECalClient
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Retrives an #icalcomponent from the backend that contains the default
+ * values for properties needed. The call is finished
+ * by e_cal_client_get_default_object_finish() from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_get_default_object (ECalClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_client_proxy_call_string (E_CLIENT (client), CAL_BACKEND_PROPERTY_DEFAULT_OBJECT, cancellable, callback, user_data, e_cal_client_get_default_object,
+ e_gdbus_cal_call_get_backend_property,
+ NULL, NULL, e_gdbus_cal_call_get_backend_property_finish, NULL, NULL);
+}
+
+static gboolean
+complete_get_object (gboolean res, gchar *out_string, icalcomponent **icalcomp, GError **error)
+{
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+
+ if (res && out_string) {
+ *icalcomp = icalparser_parse_string (out_string);
+ if (!*icalcomp) {
+ g_set_error_literal (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_INVALID_OBJECT, e_cal_client_error_to_string (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
+ res = FALSE;
+ }
+ } else {
+ *icalcomp = NULL;
+ res = FALSE;
+ }
+
+ g_free (out_string);
+
+ return res;
+}
+
+/**
+ * e_cal_client_get_default_object_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @icalcomp: (out): Return value for the default calendar object.
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_get_default_object() and
+ * sets @icalcomp to an #icalcomponent from the backend that contains
+ * the default values for properties needed. This @icalcomp should be
+ * freed with icalcomponent_free().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_default_object_finish (ECalClient *client, GAsyncResult *result, icalcomponent **icalcomp, GError **error)
+{
+ gboolean res;
+ gchar *out_string = NULL;
+
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+
+ res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &out_string, error, e_cal_client_get_default_object);
+
+ return complete_get_object (res, out_string, icalcomp, error);
+}
+
+/**
+ * e_cal_client_get_default_object_sync:
+ * @client: an #ECalClient
+ * @icalcomp: (out): Return value for the default calendar object.
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Retrives an #icalcomponent from the backend that contains the default
+ * values for properties needed. This @icalcomp should be freed with
+ * icalcomponent_free().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_default_object_sync (ECalClient *client, icalcomponent **icalcomp, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *out_string = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ res = e_client_proxy_call_sync_string__string (E_CLIENT (client), CAL_BACKEND_PROPERTY_DEFAULT_OBJECT, &out_string, cancellable, error, e_gdbus_cal_call_get_backend_property_sync);
+
+ return complete_get_object (res, out_string, icalcomp, error);
+}
+
+/**
+ * e_cal_client_get_object:
+ * @client: an #ECalClient
+ * @uid: Unique identifier for a calendar component.
+ * @rid: Recurrence identifier.
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Queries a calendar for a calendar component object based on its unique
+ * identifier. The call is finished by e_cal_client_get_object_finish()
+ * from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_get_object (ECalClient *client, const gchar *uid, const gchar *rid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar **strv;
+
+ g_return_if_fail (uid != NULL);
+
+ strv = e_gdbus_cal_encode_get_object (uid, rid);
+
+ e_client_proxy_call_strv (E_CLIENT (client), (const gchar * const *) strv, cancellable, callback, user_data, e_cal_client_get_object,
+ e_gdbus_cal_call_get_object,
+ NULL, NULL, e_gdbus_cal_call_get_object_finish, NULL, NULL);
+
+ g_strfreev (strv);
+}
+
+/**
+ * e_cal_client_get_object_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @icalcomp: (out): Return value for the calendar component object.
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_get_object() and
+ * sets @icalcomp to queried component.
+ * This component should be freed with icalcomponent_free().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_object_finish (ECalClient *client, GAsyncResult *result, icalcomponent **icalcomp, GError **error)
+{
+ gboolean res;
+ gchar *out_string = NULL;
+
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+
+ res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &out_string, error, e_cal_client_get_object);
+
+ return complete_get_object (res, out_string, icalcomp, error);;
+}
+
+/**
+ * e_cal_client_get_object_sync:
+ * @client: an #ECalClient
+ * @uid: Unique identifier for a calendar component.
+ * @rid: Recurrence identifier.
+ * @icalcomp: (out): Return value for the calendar component object.
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Queries a calendar for a calendar component object based
+ * on its unique identifier.
+ * This component should be freed with icalcomponent_free().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_object_sync (ECalClient *client, const gchar *uid, const gchar *rid, icalcomponent **icalcomp, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *out_string = NULL, **strv;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ strv = e_gdbus_cal_encode_get_object (uid, rid);
+ res = e_client_proxy_call_sync_strv__string (E_CLIENT (client), (const gchar * const *) strv, &out_string, cancellable, error, e_gdbus_cal_call_get_object_sync);
+ g_strfreev (strv);
+
+ return complete_get_object (res, out_string, icalcomp, error);
+}
+
+/**
+ * e_cal_client_get_objects_for_uid:
+ * @client: an #ECalClient
+ * @uid: Unique identifier for a calendar component
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Queries a calendar for all calendar components with the given unique
+ * ID. This will return any recurring event and all its detached recurrences.
+ * For non-recurring events, it will just return the object with that ID.
+ * The call is finished by e_cal_client_get_objects_for_uid_finish() from
+ * the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_get_objects_for_uid (ECalClient *client, const gchar *uid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar **strv;
+
+ g_return_if_fail (uid != NULL);
+
+ strv = e_gdbus_cal_encode_get_object (uid, "");
+
+ e_client_proxy_call_strv (E_CLIENT (client), (const gchar * const *) strv, cancellable, callback, user_data, e_cal_client_get_objects_for_uid,
+ e_gdbus_cal_call_get_object,
+ NULL, NULL, e_gdbus_cal_call_get_object_finish, NULL, NULL);
+
+ g_strfreev (strv);
+}
+
+static gboolean
+complete_get_objects_for_uid (ECalClientSourceType source_type, gboolean res, gchar *out_string, GSList **ecalcomps, GError **error)
+{
+ icalcomponent *icalcomp = NULL;
+ icalcomponent_kind kind;
+ ECalComponent *comp;
+
+ res = complete_get_object (res, out_string, &icalcomp, error);
+ if (!res || !icalcomp)
+ return FALSE;
+
+ kind = icalcomponent_isa (icalcomp);
+ if ((kind == ICAL_VEVENT_COMPONENT && source_type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS) ||
+ (kind == ICAL_VTODO_COMPONENT && source_type == E_CAL_CLIENT_SOURCE_TYPE_TASKS) ||
+ (kind == ICAL_VJOURNAL_COMPONENT && source_type == E_CAL_CLIENT_SOURCE_TYPE_MEMOS)) {
+ comp = e_cal_component_new ();
+ e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp));
+ *ecalcomps = g_slist_append (NULL, comp);
+ } else if (kind == ICAL_VCALENDAR_COMPONENT) {
+ icalcomponent *subcomp;
+ icalcomponent_kind kind_to_find;
+
+ switch (source_type) {
+ case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
+ kind_to_find = ICAL_VTODO_COMPONENT;
+ break;
+ case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
+ kind_to_find = ICAL_VJOURNAL_COMPONENT;
+ break;
+ case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
+ default:
+ kind_to_find = ICAL_VEVENT_COMPONENT;
+ break;
+ }
+
+ *ecalcomps = NULL;
+ subcomp = icalcomponent_get_first_component (icalcomp, kind_to_find);
+ while (subcomp) {
+ comp = e_cal_component_new ();
+ e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (subcomp));
+ *ecalcomps = g_slist_prepend (*ecalcomps, comp);
+ subcomp = icalcomponent_get_next_component (icalcomp, kind_to_find);
+ }
+
+ *ecalcomps = g_slist_reverse (*ecalcomps);
+ }
+
+ icalcomponent_free (icalcomp);
+
+ return TRUE;
+}
+
+/**
+ * e_cal_client_get_objects_for_uid_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @ecalcomps: (out): Return value for the list of objects obtained from the backend
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_get_objects_for_uid() and
+ * sets @ecalcomps to a list of #ECalComponent-s corresponding to
+ * found components for a given uid of the same type as this client.
+ * This list should be freed with e_cal_client_free_ecalcomp_slist().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_objects_for_uid_finish (ECalClient *client, GAsyncResult *result, GSList **ecalcomps, GError **error)
+{
+ gboolean res;
+ gchar *out_string = NULL;
+
+ g_return_val_if_fail (ecalcomps != NULL, FALSE);
+
+ res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &out_string, error, e_cal_client_get_objects_for_uid);
+
+ return complete_get_objects_for_uid (e_cal_client_get_source_type (client), res, out_string, ecalcomps, error);
+}
+
+/**
+ * e_cal_client_get_objects_for_uid_sync:
+ * @client: an #ECalClient
+ * @uid: Unique identifier for a calendar component
+ * @ecalcomps: (out): Return value for the list of objects obtained from the backend
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Queries a calendar for all calendar components with the given unique
+ * ID. This will return any recurring event and all its detached recurrences.
+ * For non-recurring events, it will just return the object with that ID.
+ * This list should be freed with e_cal_client_free_ecalcomp_slist().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_objects_for_uid_sync (ECalClient *client, const gchar *uid, GSList **ecalcomps, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *out_string = NULL, **strv = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+ g_return_val_if_fail (ecalcomps != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ strv = e_gdbus_cal_encode_get_object (uid, "");
+ res = e_client_proxy_call_sync_strv__string (E_CLIENT (client), (const gchar * const *) strv, &out_string, cancellable, error, e_gdbus_cal_call_get_object_sync);
+ g_strfreev (strv);
+
+ return complete_get_objects_for_uid (e_cal_client_get_source_type (client), res, out_string, ecalcomps, error);
+}
+
+/**
+ * e_cal_client_get_object_list:
+ * @client: an #ECalClient
+ * @sexp: an S-expression representing the query
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Gets a list of objects from the calendar that match the query specified
+ * by the @sexp argument, returning matching objects as a list of #icalcomponent-s.
+ * The call is finished by e_cal_client_get_object_list_finish() from
+ * the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_get_object_list (ECalClient *client, const gchar *sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *gdbus_sexp = NULL;
+
+ g_return_if_fail (sexp != NULL);
+
+ e_client_proxy_call_string (E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), cancellable, callback, user_data, e_cal_client_get_object_list,
+ e_gdbus_cal_call_get_object_list,
+ NULL, NULL, NULL, e_gdbus_cal_call_get_object_list_finish, NULL);
+
+ g_free (gdbus_sexp);
+}
+
+static gboolean
+complete_get_object_list (gboolean res, gchar **out_strv, GSList **icalcomps, GError **error)
+{
+ g_return_val_if_fail (icalcomps != NULL, FALSE);
+
+ *icalcomps = NULL;
+
+ if (res && out_strv) {
+ gint ii;
+ icalcomponent *icalcomp;
+
+ for (ii = 0; out_strv[ii]; ii++) {
+ icalcomp = icalcomponent_new_from_string (out_strv[ii]);
+
+ if (!icalcomp)
+ continue;
+
+ *icalcomps = g_slist_prepend (*icalcomps, icalcomp);
+ }
+
+ *icalcomps = g_slist_reverse (*icalcomps);
+ } else {
+ res = FALSE;
+ }
+
+ g_strfreev (out_strv);
+
+ return res;
+}
+
+/**
+ * e_cal_client_get_object_list_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @icalcomps: (out): list of matching #icalcomponent-s
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_get_object_list() and
+ * sets @icalcomps to a matching list of #icalcomponent-s.
+ * This list should be freed with #e_cal_client_free_icalcomp_slist().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_object_list_finish (ECalClient *client, GAsyncResult *result, GSList **icalcomps, GError **error)
+{
+ gboolean res;
+ gchar **out_strv = NULL;
+
+ g_return_val_if_fail (icalcomps != NULL, FALSE);
+
+ res = e_client_proxy_call_finish_strv (E_CLIENT (client), result, &out_strv, error, e_cal_client_get_object_list);
+
+ return complete_get_object_list (res, out_strv, icalcomps, error);
+}
+
+/**
+ * e_cal_client_get_object_list_sync:
+ * @client: an #ECalClient
+ * @sexp: an S-expression representing the query
+ * @icalcomps: (out): list of matching #icalcomponent-s
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Gets a list of objects from the calendar that match the query specified
+ * by the @sexp argument. The objects will be returned in the @icalcomps
+ * argument, which is a list of #icalcomponent.
+ * This list should be freed with #e_cal_client_free_icalcomp_slist().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_object_list_sync (ECalClient *client, const gchar *sexp, GSList **icalcomps, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar **out_strv = NULL, *gdbus_sexp = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (sexp != NULL, FALSE);
+ g_return_val_if_fail (icalcomps != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ res = e_client_proxy_call_sync_string__strv (E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &out_strv, cancellable, error, e_gdbus_cal_call_get_object_list_sync);
+ g_free (gdbus_sexp);
+
+ return complete_get_object_list (res, out_strv, icalcomps, error);
+}
+
+/**
+ * e_cal_client_get_object_list_as_comps:
+ * @client: an #ECalClient
+ * @sexp: an S-expression representing the query
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Gets a list of objects from the calendar that match the query specified
+ * by the @sexp argument, returning matching objects as a list of #ECalComponent-s.
+ * The call is finished by e_cal_client_get_object_list_as_comps_finish() from
+ * the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_get_object_list_as_comps (ECalClient *client, const gchar *sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *gdbus_sexp = NULL;
+
+ g_return_if_fail (sexp != NULL);
+
+ e_client_proxy_call_string (E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), cancellable, callback, user_data, e_cal_client_get_object_list_as_comps,
+ e_gdbus_cal_call_get_object_list,
+ NULL, NULL, NULL, e_gdbus_cal_call_get_object_list_finish, NULL);
+
+ g_free (gdbus_sexp);
+}
+
+static gboolean
+complete_get_object_list_as_comps (gboolean res, gchar **out_strv, GSList **ecalcomps, GError **error)
+{
+ GSList *icalcomps = NULL;
+
+ g_return_val_if_fail (ecalcomps != NULL, FALSE);
+
+ *ecalcomps = NULL;
+
+ res = complete_get_object_list (res, out_strv, &icalcomps, error);
+
+ if (res) {
+ GSList *iter;
+
+ for (iter = icalcomps; iter; iter = iter->next) {
+ ECalComponent *comp;
+
+ comp = e_cal_component_new ();
+ /* takes ownership of the icalcomp, thus free only the list at the end */
+ if (e_cal_component_set_icalcomponent (comp, iter->data))
+ *ecalcomps = g_slist_prepend (*ecalcomps, comp);
+ else
+ icalcomponent_free (iter->data);
+ }
+
+ g_slist_free (icalcomps);
+
+ *ecalcomps = g_slist_reverse (*ecalcomps);
+ } else {
+ e_cal_client_free_icalcomp_slist (icalcomps);
+ }
+
+ return res;
+}
+
+/**
+ * e_cal_client_get_object_list_as_comps_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @ecalcomps: (out): list of matching #ECalComponent-s
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_get_object_list_as_comps() and
+ * sets @ecalcomps to a matching list of #ECalComponent-s.
+ * This list should be freed with #e_cal_client_free_ecalcomp_slist().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_object_list_as_comps_finish (ECalClient *client, GAsyncResult *result, GSList **ecalcomps, GError **error)
+{
+ gboolean res;
+ gchar **out_strv = NULL;
+
+ g_return_val_if_fail (ecalcomps != NULL, FALSE);
+
+ res = e_client_proxy_call_finish_strv (E_CLIENT (client), result, &out_strv, error, e_cal_client_get_object_list_as_comps);
+
+ return complete_get_object_list_as_comps (res, out_strv, ecalcomps, error);
+}
+
+/**
+ * e_cal_client_get_object_list_as_comps_sync:
+ * @client: an #ECalClient
+ * @sexp: an S-expression representing the query
+ * @ecalcomps: (out): list of matching #ECalComponent-s
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Gets a list of objects from the calendar that match the query specified
+ * by the @sexp argument. The objects will be returned in the @ecalcomps
+ * argument, which is a list of #ECalComponent.
+ * This list should be freed with #e_cal_client_free_ecalcomp_slist().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_object_list_as_comps_sync (ECalClient *client, const gchar *sexp, GSList **ecalcomps, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar **out_strv = NULL, *gdbus_sexp = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (sexp != NULL, FALSE);
+ g_return_val_if_fail (ecalcomps != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ res = e_client_proxy_call_sync_string__strv (E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &out_strv, cancellable, error, e_gdbus_cal_call_get_object_list_sync);
+ g_free (gdbus_sexp);
+
+ return complete_get_object_list_as_comps (res, out_strv, ecalcomps, error);
+}
+
+/**
+ * e_cal_client_get_free_busy:
+ * @client: an #ECalClient
+ * @start: Start time for query
+ * @end: End time for query
+ * @users: List of users to retrieve free/busy information for
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Begins retrieval of free/busy information from the calendar server
+ * as a list of #ECalComponent-s. Connect to "free-busy-data" signal
+ * to receive chunks of free/busy components.
+ * The call is finished by e_cal_client_get_free_busy_finish() from
+ * the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_get_free_busy (ECalClient *client, time_t start, time_t end, const GSList *users, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar **strv;
+
+ g_return_if_fail (start > 0);
+ g_return_if_fail (end > 0);
+ g_return_if_fail (users != NULL);
+
+ strv = e_gdbus_cal_encode_get_free_busy (start, end, users);
+
+ e_client_proxy_call_strv (E_CLIENT (client), (const gchar * const *) strv, cancellable, callback, user_data, e_cal_client_get_free_busy,
+ e_gdbus_cal_call_get_free_busy,
+ e_gdbus_cal_call_get_free_busy_finish, NULL, NULL, NULL, NULL);
+
+ g_strfreev (strv);
+}
+
+/**
+ * e_cal_client_get_free_busy_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_get_free_busy().
+ * All VFREEBUSY #ECalComponent-s were received by "free-busy-data" signal.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_free_busy_finish (ECalClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_cal_client_get_free_busy);
+}
+
+/**
+ * e_cal_client_get_free_busy_sync:
+ * @client: an #ECalClient
+ * @start: Start time for query
+ * @end: End time for query
+ * @users: List of users to retrieve free/busy information for
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Gets free/busy information from the calendar server.
+ * All VFREEBUSY #ECalComponent-s were received by "free-busy-data" signal.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_free_busy_sync (ECalClient *client, time_t start, time_t end, const GSList *users, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar **strv;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (users != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ strv = e_gdbus_cal_encode_get_free_busy (start, end, users);
+ res = e_client_proxy_call_sync_strv__void (E_CLIENT (client), (const gchar * const *) strv, cancellable, error, e_gdbus_cal_call_get_free_busy_sync);
+ g_strfreev (strv);
+
+ return res;
+}
+
+/**
+ * e_cal_client_create_object:
+ * @client: an #ECalClient
+ * @icalcomp: The component to create
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Requests the calendar backend to create the object specified by the @icalcomp
+ * argument. Some backends would assign a specific UID to the newly created object,
+ * but this function does not modify the original @icalcomp if its UID changes.
+ * The call is finished by e_cal_client_create_object_finish() from
+ * the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_create_object (ECalClient *client, /* const */ icalcomponent *icalcomp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *comp_str, *gdbus_comp = NULL;
+
+ g_return_if_fail (icalcomp != NULL);
+
+ comp_str = icalcomponent_as_ical_string_r (icalcomp);
+
+ e_client_proxy_call_string (E_CLIENT (client), e_util_ensure_gdbus_string (comp_str, &gdbus_comp), cancellable, callback, user_data, e_cal_client_create_object,
+ e_gdbus_cal_call_create_object,
+ NULL, NULL, e_gdbus_cal_call_create_object_finish, NULL, NULL);
+
+ g_free (comp_str);
+ g_free (gdbus_comp);
+}
+
+/**
+ * e_cal_client_create_object_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @uid: (out): Return value for the UID assigned to the new component by the calendar backend
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_create_object() and
+ * sets @uid to newly assigned UID for the created object.
+ * This @uid should be freed with g_free().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_create_object_finish (ECalClient *client, GAsyncResult *result, gchar **uid, GError **error)
+{
+ gboolean res;
+ gchar *out_string = NULL;
+
+ g_return_val_if_fail (uid != NULL, FALSE);
+
+ res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &out_string, error, e_cal_client_create_object);
+
+ return complete_string_exchange (res, out_string, uid, error);
+}
+
+/**
+ * e_cal_client_create_object_sync:
+ * @client: an #ECalClient
+ * @icalcomp: The component to create
+ * @uid: (out): Return value for the UID assigned to the new component by the calendar backend
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Requests the calendar backend to create the object specified by the @icalcomp
+ * argument. Some backends would assign a specific UID to the newly created object,
+ * in those cases that UID would be returned in the @uid argument. This function
+ * does not modify the original @icalcomp if its UID changes.
+ * Returned @uid should be freed with g_free().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_create_object_sync (ECalClient *client, /* const */ icalcomponent *icalcomp, gchar **uid, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *comp_str, *gdbus_comp = NULL;
+ gchar *out_string = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ comp_str = icalcomponent_as_ical_string_r (icalcomp);
+
+ res = e_client_proxy_call_sync_string__string (E_CLIENT (client), e_util_ensure_gdbus_string (comp_str, &gdbus_comp), &out_string, cancellable, error, e_gdbus_cal_call_create_object_sync);
+
+ g_free (comp_str);
+ g_free (gdbus_comp);
+
+ return complete_string_exchange (res, out_string, uid, error);
+}
+
+/**
+ * e_cal_client_modify_object:
+ * @client: an #ECalClient
+ * @icalcomp: Component to modify
+ * @mod: Type of modification
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Requests the calendar backend to modify an existing object. If the object
+ * does not exist on the calendar, an error will be returned.
+ *
+ * For recurrent appointments, the @mod argument specifies what to modify,
+ * if all instances (CALOBJ_MOD_ALL), a single instance (CALOBJ_MOD_THIS),
+ * or a specific set of instances (CALOBJ_MOD_THISNADPRIOR and
+ * CALOBJ_MOD_THISANDFUTURE).
+ *
+ * The call is finished by e_cal_client_modify_object_finish() from
+ * the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_modify_object (ECalClient *client, /* const */ icalcomponent *icalcomp, CalObjModType mod, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *comp_str, **strv;
+
+ g_return_if_fail (icalcomp != NULL);
+
+ comp_str = icalcomponent_as_ical_string_r (icalcomp);
+ strv = e_gdbus_cal_encode_modify_object (comp_str, mod);
+
+ e_client_proxy_call_strv (E_CLIENT (client), (const gchar * const *) strv, cancellable, callback, user_data, e_cal_client_modify_object,
+ e_gdbus_cal_call_modify_object,
+ e_gdbus_cal_call_modify_object_finish, NULL, NULL, NULL, NULL);
+
+ g_strfreev (strv);
+ g_free (comp_str);
+}
+
+/**
+ * e_cal_client_modify_object_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_modify_object().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_modify_object_finish (ECalClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_cal_client_modify_object);
+}
+
+/**
+ * e_cal_client_modify_object_sync:
+ * @client: an #ECalClient
+ * @icalcomp: Component to modify
+ * @mod: Type of modification
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Requests the calendar backend to modify an existing object. If the object
+ * does not exist on the calendar, an error will be returned.
+ *
+ * For recurrent appointments, the @mod argument specifies what to modify,
+ * if all instances (CALOBJ_MOD_ALL), a single instance (CALOBJ_MOD_THIS),
+ * or a specific set of instances (CALOBJ_MOD_THISNADPRIOR and
+ * CALOBJ_MOD_THISANDFUTURE).
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_modify_object_sync (ECalClient *client, /* const */ icalcomponent *icalcomp, CalObjModType mod, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *comp_str, **strv;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ comp_str = icalcomponent_as_ical_string_r (icalcomp);
+ strv = e_gdbus_cal_encode_modify_object (comp_str, mod);
+
+ res = e_client_proxy_call_sync_strv__void (E_CLIENT (client), (const gchar * const *) strv, cancellable, error, e_gdbus_cal_call_modify_object_sync);
+
+ g_strfreev (strv);
+ g_free (comp_str);
+
+ return res;
+}
+
+/**
+ * e_cal_client_remove_object:
+ * @client: an #ECalClient
+ * @uid: UID of the object to remove
+ * @rid: Recurrence ID of the specific recurrence to remove
+ * @mod: Type of the removal
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * This function allows the removal of instances of a recurrent
+ * appointment. By using a combination of the @uid, @rid and @mod
+ * arguments, you can remove specific instances. If what you want
+ * is to remove all instances, use #NULL @rid and CALOBJ_MODE_THIS
+ * for the @mod.
+ *
+ * The call is finished by e_cal_client_remove_object_finish() from
+ * the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_remove_object (ECalClient *client, const gchar *uid, const gchar *rid, CalObjModType mod, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar **strv;
+
+ g_return_if_fail (uid != NULL);
+
+ strv = e_gdbus_cal_encode_remove_object (uid, rid, mod);
+
+ e_client_proxy_call_strv (E_CLIENT (client), (const gchar * const *) strv, cancellable, callback, user_data, e_cal_client_remove_object,
+ e_gdbus_cal_call_remove_object,
+ e_gdbus_cal_call_remove_object_finish, NULL, NULL, NULL, NULL);
+
+ g_strfreev (strv);
+}
+
+/**
+ * e_cal_client_remove_object_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_remove_object().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_remove_object_finish (ECalClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_cal_client_remove_object);
+}
+
+/**
+ * e_cal_client_remove_object_sync:
+ * @client: an #ECalClient
+ * @uid: UID of the object to remove
+ * @rid: Recurrence ID of the specific recurrence to remove
+ * @mod: Type of the removal
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * This function allows the removal of instances of a recurrent
+ * appointment. By using a combination of the @uid, @rid and @mod
+ * arguments, you can remove specific instances. If what you want
+ * is to remove all instances, use #NULL @rid and CALOBJ_MODE_THIS
+ * for the @mod.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_remove_object_sync (ECalClient *client, const gchar *uid, const gchar *rid, CalObjModType mod, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar **strv;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ strv = e_gdbus_cal_encode_remove_object (uid, rid, mod);
+
+ res = e_client_proxy_call_sync_strv__void (E_CLIENT (client), (const gchar * const *) strv, cancellable, error, e_gdbus_cal_call_remove_object_sync);
+
+ g_strfreev (strv);
+
+ return res;
+}
+
+/**
+ * e_cal_client_receive_objects:
+ * @client: an #ECalClient
+ * @icalcomp: An #icalcomponent
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Makes the backend receive the set of iCalendar objects specified in the
+ * @icalcomp argument. This is used for iTIP confirmation/cancellation
+ * messages for scheduled meetings.
+ *
+ * The call is finished by e_cal_client_receive_objects_finish() from
+ * the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_receive_objects (ECalClient *client, /* const */ icalcomponent *icalcomp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *comp_str, *gdbus_comp = NULL;
+
+ g_return_if_fail (icalcomp != NULL);
+
+ comp_str = icalcomponent_as_ical_string_r (icalcomp);
+
+ e_client_proxy_call_string (E_CLIENT (client), e_util_ensure_gdbus_string (comp_str, &gdbus_comp), cancellable, callback, user_data, e_cal_client_receive_objects,
+ e_gdbus_cal_call_receive_objects,
+ e_gdbus_cal_call_receive_objects_finish, NULL, NULL, NULL, NULL);
+
+ g_free (comp_str);
+ g_free (gdbus_comp);
+}
+
+/**
+ * e_cal_client_receive_objects_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_receive_objects().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_receive_objects_finish (ECalClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_cal_client_receive_objects);
+}
+
+/**
+ * e_cal_client_receive_objects_sync:
+ * @client: an #ECalClient
+ * @icalcomp: An #icalcomponent
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Makes the backend receive the set of iCalendar objects specified in the
+ * @icalcomp argument. This is used for iTIP confirmation/cancellation
+ * messages for scheduled meetings.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_receive_objects_sync (ECalClient *client, /* const */ icalcomponent *icalcomp, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *comp_str, *gdbus_comp = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ comp_str = icalcomponent_as_ical_string_r (icalcomp);
+
+ res = e_client_proxy_call_sync_string__void (E_CLIENT (client), e_util_ensure_gdbus_string (comp_str, &gdbus_comp), cancellable, error, e_gdbus_cal_call_receive_objects_sync);
+
+ g_free (comp_str);
+ g_free (gdbus_comp);
+
+ return res;
+}
+
+/**
+ * e_cal_client_send_objects:
+ * @client: an #ECalClient
+ * @icalcomp: An icalcomponent to be sent
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Requests a calendar backend to send meeting information stored in @icalcomp.
+ * The backend can modify this component and request a send to particular users.
+ * The call is finished by e_cal_client_send_objects_finish() from
+ * the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_send_objects (ECalClient *client, /* const */ icalcomponent *icalcomp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *comp_str, *gdbus_comp = NULL;
+
+ g_return_if_fail (icalcomp != NULL);
+
+ comp_str = icalcomponent_as_ical_string_r (icalcomp);
+
+ e_client_proxy_call_string (E_CLIENT (client), e_util_ensure_gdbus_string (comp_str, &gdbus_comp), cancellable, callback, user_data, e_cal_client_send_objects,
+ e_gdbus_cal_call_send_objects,
+ NULL, NULL, NULL, e_gdbus_cal_call_send_objects_finish, NULL);
+
+ g_free (comp_str);
+ g_free (gdbus_comp);
+}
+
+static gboolean
+complete_send_objects (gboolean res, gchar **out_strv, GSList **users, icalcomponent **modified_icalcomp, GError **error)
+{
+ g_return_val_if_fail (users != NULL, FALSE);
+ g_return_val_if_fail (modified_icalcomp != NULL, FALSE);
+
+ *users = NULL;
+ *modified_icalcomp = NULL;
+
+ if (res && out_strv) {
+ gchar *calobj = NULL;
+
+ if (e_gdbus_cal_decode_send_objects ((const gchar * const *) out_strv, &calobj, users)) {
+ *modified_icalcomp = icalparser_parse_string (calobj);
+ if (!*modified_icalcomp) {
+ g_set_error_literal (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_INVALID_OBJECT, e_cal_client_error_to_string (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
+ e_client_util_free_string_slist (*users);
+ *users = NULL;
+ res = FALSE;
+ }
+ } else {
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG, e_client_error_to_string (E_CLIENT_ERROR_INVALID_ARG));
+ e_client_util_free_string_slist (*users);
+ *users = NULL;
+ res = FALSE;
+ }
+
+ g_free (calobj);
+ } else {
+ res = FALSE;
+ }
+
+ g_strfreev (out_strv);
+
+ return res;
+}
+
+/**
+ * e_cal_client_send_objects_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @users: (out): List of users to send the @modified_icalcomp to
+ * @modified_icalcomp: (out): Return value for the icalcomponent to be sent
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_send_objects() and
+ * populates @users with a list of users to send @modified_icalcomp to.
+ * The @users list should be freed with e_client_util_free_string_slist() and
+ * the @modified_icalcomp should be freed with icalcomponent_free().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_send_objects_finish (ECalClient *client, GAsyncResult *result, GSList **users, icalcomponent **modified_icalcomp, GError **error)
+{
+ gboolean res;
+ gchar **out_strv = NULL;
+
+ g_return_val_if_fail (users != NULL, FALSE);
+ g_return_val_if_fail (modified_icalcomp != NULL, FALSE);
+
+ res = e_client_proxy_call_finish_strv (E_CLIENT (client), result, &out_strv, error, e_cal_client_send_objects);
+
+ return complete_send_objects (res, out_strv, users, modified_icalcomp, error);
+}
+
+/**
+ * e_cal_client_send_objects_sync:
+ * @client: an #ECalClient
+ * @icalcomp: An icalcomponent to be sent
+ * @users: (out): List of users to send the @modified_icalcomp to
+ * @modified_icalcomp: (out): Return value for the icalcomponent to be sent
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Requests a calendar backend to send meeting information stored in @icalcomp.
+ * The backend can modify this component and request a send to users in the @users list.
+ * The @users list should be freed with e_client_util_free_string_slist() and
+ * the @modified_icalcomp should be freed with icalcomponent_free().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_send_objects_sync (ECalClient *client, /* const */ icalcomponent *icalcomp, GSList **users, icalcomponent **modified_icalcomp, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar **out_strv = NULL, *comp_str, *gdbus_comp = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+ g_return_val_if_fail (users != NULL, FALSE);
+ g_return_val_if_fail (modified_icalcomp != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ comp_str = icalcomponent_as_ical_string_r (icalcomp);
+
+ res = e_client_proxy_call_sync_string__strv (E_CLIENT (client), e_util_ensure_gdbus_string (comp_str, &gdbus_comp), &out_strv, cancellable, error, e_gdbus_cal_call_send_objects_sync);
+
+ g_free (comp_str);
+ g_free (gdbus_comp);
+
+ return complete_send_objects (res, out_strv, users, modified_icalcomp, error);
+}
+
+/**
+ * e_cal_client_get_attachment_uris:
+ * @client: an #ECalClient
+ * @uid: Unique identifier for a calendar component
+ * @rid: Recurrence identifier
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Queries a calendar for a specified component's object attachment uris.
+ * The call is finished by e_cal_client_get_attachment_uris_finish() from
+ * the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_get_attachment_uris (ECalClient *client, const gchar *uid, const gchar *rid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar **strv;
+
+ g_return_if_fail (uid != NULL);
+
+ strv = e_gdbus_cal_encode_get_attachment_uris (uid, rid);
+
+ e_client_proxy_call_strv (E_CLIENT (client), (const gchar * const *) strv, cancellable, callback, user_data, e_cal_client_get_attachment_uris,
+ e_gdbus_cal_call_get_attachment_uris,
+ NULL, NULL, NULL, e_gdbus_cal_call_get_attachment_uris_finish, NULL);
+
+ g_strfreev (strv);
+}
+
+/**
+ * e_cal_client_get_attachment_uris_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @attachment_uris: (out:) Return the list of attachment uris
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_get_attachment_uris() and
+ * sets @attachment_uris to uris for component's attachments.
+ * The list should be freed with e_client_util_free_string_slist().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_attachment_uris_finish (ECalClient *client, GAsyncResult *result, GSList **attachment_uris, GError **error)
+{
+ gboolean res;
+ gchar **out_strv = NULL;
+
+ g_return_val_if_fail (attachment_uris != NULL, FALSE);
+
+ res = e_client_proxy_call_finish_strv (E_CLIENT (client), result, &out_strv, error, e_cal_client_get_attachment_uris);
+
+ if (res && out_strv) {
+ *attachment_uris = e_client_util_strv_to_slist ((const gchar * const *) out_strv);
+ } else {
+ *attachment_uris = NULL;
+ }
+
+ g_strfreev (out_strv);
+
+ return res;
+}
+
+/**
+ * e_cal_client_get_attachment_uris_sync:
+ * @client: an #ECalClient
+ * @uid: Unique identifier for a calendar component
+ * @rid: Recurrence identifier
+ * @attachment_uris: (out:) Return the list of attachment uris
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Queries a calendar for a specified component's object attachment uris.
+ * The list should be freed with e_client_util_free_string_slist().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_attachment_uris_sync (ECalClient *client, const gchar *uid, const gchar *rid, GSList **attachment_uris, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar **strv, **out_strv = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+ g_return_val_if_fail (attachment_uris != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ strv = e_gdbus_cal_encode_get_attachment_uris (uid, rid);
+
+ res = e_client_proxy_call_sync_strv__strv (E_CLIENT (client), (const gchar * const *) strv, &out_strv, cancellable, error, e_gdbus_cal_call_get_attachment_uris_sync);
+
+ g_strfreev (strv);
+
+ if (res && out_strv) {
+ *attachment_uris = e_client_util_strv_to_slist ((const gchar * const *) out_strv);
+ } else {
+ *attachment_uris = NULL;
+ }
+
+ g_strfreev (out_strv);
+
+ return res;
+}
+
+/**
+ * e_cal_client_discard_alarm:
+ * @client: an #ECalClient
+ * @uid: Unique identifier for a calendar component
+ * @rid: Recurrence identifier
+ * @auid: Alarm identifier to remove
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Removes alarm @auid from a given component identified by @uid and @rid.
+ * The call is finished by e_cal_client_discard_alarm_finish() from
+ * the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_discard_alarm (ECalClient *client, const gchar *uid, const gchar *rid, const gchar *auid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar **strv;
+
+ g_return_if_fail (uid != NULL);
+ g_return_if_fail (auid != NULL);
+
+ strv = e_gdbus_cal_encode_discard_alarm (uid, rid, auid);
+
+ e_client_proxy_call_strv (E_CLIENT (client), (const gchar * const *) strv, cancellable, callback, user_data, e_cal_client_discard_alarm,
+ e_gdbus_cal_call_discard_alarm,
+ e_gdbus_cal_call_discard_alarm_finish, NULL, NULL, NULL, NULL);
+
+ g_strfreev (strv);
+}
+
+/**
+ * e_cal_client_discard_alarm_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_discard_alarm().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_discard_alarm_finish (ECalClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_cal_client_discard_alarm);
+}
+
+/**
+ * e_cal_client_discard_alarm_sync:
+ * @client: an #ECalClient
+ * @uid: Unique identifier for a calendar component
+ * @rid: Recurrence identifier
+ * @auid: Alarm identifier to remove
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Removes alarm @auid from a given component identified by @uid and @rid.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_discard_alarm_sync (ECalClient *client, const gchar *uid, const gchar *rid, const gchar *auid, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar **strv;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+ g_return_val_if_fail (auid != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ strv = e_gdbus_cal_encode_discard_alarm (uid, rid, auid);
+
+ res = e_client_proxy_call_sync_strv__void (E_CLIENT (client), (const gchar * const *) strv, cancellable, error, e_gdbus_cal_call_discard_alarm_sync);
+
+ g_strfreev (strv);
+
+ return res;
+}
+
+/**
+ * e_cal_client_get_view:
+ * @client: an #ECalClient
+ * @sexp: an S-expression representing the query.
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Query @client with @sexp, creating an #ECalClientView.
+ * The call is finished by e_cal_client_get_view_finish()
+ * from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_get_view (ECalClient *client, const gchar *sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *gdbus_sexp = NULL;
+
+ g_return_if_fail (sexp != NULL);
+
+ e_client_proxy_call_string (E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), cancellable, callback, user_data, e_cal_client_get_view,
+ e_gdbus_cal_call_get_view,
+ NULL, NULL, e_gdbus_cal_call_get_view_finish, NULL, NULL);
+
+ g_free (gdbus_sexp);
+}
+
+static gboolean
+complete_get_view (ECalClient *client, gboolean res, gchar *view_path, ECalClientView **view, GError **error)
+{
+ g_return_val_if_fail (view != NULL, FALSE);
+
+ if (view_path && res && cal_factory_proxy) {
+ EGdbusCalView *gdbus_calview;
+ GError *local_error = NULL;
+
+ gdbus_calview = e_gdbus_cal_view_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy)),
+ G_DBUS_PROXY_FLAGS_NONE,
+ CALENDAR_DBUS_SERVICE_NAME,
+ view_path,
+ NULL,
+ &local_error);
+
+ if (gdbus_calview) {
+ *view = _e_cal_client_view_new (client, gdbus_calview);
+ g_object_unref (gdbus_calview);
+ } else {
+ *view = NULL;
+ res = FALSE;
+ }
+
+ if (local_error)
+ unwrap_dbus_error (local_error, error);
+ } else {
+ *view = NULL;
+ res = FALSE;
+ }
+
+ if (!*view && error && !*error)
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_DBUS_ERROR, _("Cannot get connection to view"));
+
+ g_free (view_path);
+
+ return res;
+}
+
+/**
+ * e_cal_client_get_view_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @view: (out) an #ECalClientView
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_get_view().
+ * If successful, then the @view is set to newly allocated #ECalClientView,
+ * which should be freed with g_object_unref().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_view_finish (ECalClient *client, GAsyncResult *result, ECalClientView **view, GError **error)
+{
+ gboolean res;
+ gchar *view_path = NULL;
+
+ g_return_val_if_fail (view != NULL, FALSE);
+
+ res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &view_path, error, e_cal_client_get_view);
+
+ return complete_get_view (client, res, view_path, view, error);
+}
+
+/**
+ * e_cal_client_get_view_sync:
+ * @client: an #ECalClient
+ * @sexp: an S-expression representing the query.
+ * @view: (out) an #ECalClientView
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Query @client with @sexp, creating an #ECalClientView.
+ * If successful, then the @view is set to newly allocated #ECalClientView,
+ * which should be freed with g_object_unref().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_view_sync (ECalClient *client, const gchar *sexp, ECalClientView **view, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *gdbus_sexp = NULL;
+ gchar *view_path = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (sexp != NULL, FALSE);
+ g_return_val_if_fail (view != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ res = e_client_proxy_call_sync_string__string (E_CLIENT (client), e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &view_path, cancellable, error, e_gdbus_cal_call_get_view_sync);
+
+ g_free (gdbus_sexp);
+
+ return complete_get_view (client, res, view_path, view, error);
+}
+
+static icaltimezone *
+cal_client_get_timezone_from_cache (ECalClient *client, const gchar *tzid)
+{
+ icaltimezone *zone = NULL;
+
+ g_return_val_if_fail (client != NULL, NULL);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
+ g_return_val_if_fail (client->priv != NULL, NULL);
+ g_return_val_if_fail (tzid != NULL, NULL);
+ g_return_val_if_fail (client->priv->zone_cache != NULL, NULL);
+ g_return_val_if_fail (client->priv->zone_cache_lock != NULL, NULL);
+
+ if (!*tzid)
+ return NULL;
+
+ g_mutex_lock (client->priv->zone_cache_lock);
+ if (g_str_equal (tzid, "UTC")) {
+ zone = icaltimezone_get_utc_timezone ();
+ } else {
+ /* See if we already have it in the cache. */
+ zone = g_hash_table_lookup (client->priv->zone_cache, tzid);
+ }
+
+ if (!zone) {
+ /*
+ * Try to replace the original time zone with a more complete
+ * and/or potentially updated system time zone. Note that this
+ * also applies to TZIDs which match system time zones exactly:
+ * they are extracted via icaltimezone_get_builtin_timezone_from_tzid()
+ * below without a roundtrip to the backend.
+ */
+ const gchar *systzid = e_cal_match_tzid (tzid);
+ if (systzid) {
+ /*
+ * Use built-in time zone *and* rename it:
+ * if the caller is asking for a TZID=FOO,
+ * then likely because it has an event with
+ * such a TZID. Returning a different TZID
+ * would lead to broken VCALENDARs in the
+ * caller.
+ */
+ icaltimezone *syszone = icaltimezone_get_builtin_timezone_from_tzid (systzid);
+ if (syszone) {
+ gboolean found = FALSE;
+ icalcomponent *icalcomp = NULL;
+ icalproperty *prop;
+
+ icalcomp = icalcomponent_new_clone (icaltimezone_get_component (syszone));
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_ANY_PROPERTY);
+ while (!found && prop) {
+ if (icalproperty_isa (prop) == ICAL_TZID_PROPERTY) {
+ icalproperty_set_value_from_string (prop, tzid, "NO");
+ found = TRUE;
+ }
+
+ prop = icalcomponent_get_next_property (icalcomp, ICAL_ANY_PROPERTY);
+ }
+
+ if (icalcomp) {
+ zone = icaltimezone_new ();
+ if (!icaltimezone_set_component (zone, icalcomp)) {
+ icalcomponent_free (icalcomp);
+ icaltimezone_free (zone, 1);
+ zone = NULL;
+ } else {
+ g_hash_table_insert (client->priv->zone_cache, g_strdup (icaltimezone_get_tzid (zone)), zone);
+ }
+ }
+ }
+ }
+ }
+
+ g_mutex_unlock (client->priv->zone_cache_lock);
+
+ return zone;
+}
+
+static gboolean
+cal_client_get_timezone_from_cache_finish (ECalClient *client, GAsyncResult *result, icaltimezone **zone, GError **error)
+{
+ GSimpleAsyncResult *simple;
+ GError *local_error = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (result != NULL, FALSE);
+ g_return_val_if_fail (zone != NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), cal_client_get_timezone_from_cache), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, &local_error)) {
+ e_client_unwrap_dbus_error (E_CLIENT (client), local_error, error);
+ return FALSE;
+ }
+
+ *zone = g_simple_async_result_get_op_res_gpointer (simple);
+
+ return *zone != NULL;
+}
+
+/**
+ * e_cal_client_get_timezone:
+ * @client: an #ECalClient
+ * @tzid: ID of the timezone to retrieve
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Retrieves a timezone object from the calendar backend.
+ * The call is finished by e_cal_client_get_timezone_finish() from
+ * the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_get_timezone (ECalClient *client, const gchar *tzid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gchar *gdbus_tzid = NULL;
+ icaltimezone *zone;
+
+ g_return_if_fail (tzid != NULL);
+
+ zone = cal_client_get_timezone_from_cache (client, tzid);
+ if (zone) {
+ GCancellable *use_cancellable = cancellable;
+ guint32 opid;
+
+ if (!use_cancellable)
+ use_cancellable = g_cancellable_new ();
+
+ opid = e_client_register_op (E_CLIENT (client), use_cancellable);
+ if (opid) {
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data, cal_client_get_timezone_from_cache);
+ g_simple_async_result_set_op_res_gpointer (simple, zone, NULL);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ }
+
+ if (use_cancellable != cancellable)
+ g_object_unref (use_cancellable);
+ } else {
+ e_client_proxy_call_string (E_CLIENT (client), e_util_ensure_gdbus_string (tzid, &gdbus_tzid), cancellable, callback, user_data, e_cal_client_get_timezone,
+ e_gdbus_cal_call_get_timezone,
+ NULL, NULL, e_gdbus_cal_call_get_timezone_finish, NULL, NULL);
+
+ g_free (gdbus_tzid);
+ }
+}
+
+static gboolean
+complete_get_timezone (ECalClient *client, gboolean res, gchar *out_string, icaltimezone **zone, GError **error)
+{
+ g_return_val_if_fail (zone != NULL, FALSE);
+
+ *zone = NULL;
+
+ if (res && out_string) {
+ icalcomponent *icalcomp;
+
+ icalcomp = icalparser_parse_string (out_string);
+ if (icalcomp) {
+ *zone = icaltimezone_new ();
+ if (!icaltimezone_set_component (*zone, icalcomp)) {
+ icaltimezone_free (*zone, 1);
+ icalcomponent_free (icalcomp);
+ res = FALSE;
+ g_set_error_literal (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_INVALID_OBJECT, e_cal_client_error_to_string (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
+ } else {
+ g_mutex_lock (client->priv->zone_cache_lock);
+ g_hash_table_insert (client->priv->zone_cache, g_strdup (icaltimezone_get_tzid (*zone)), *zone);
+ g_mutex_unlock (client->priv->zone_cache_lock);
+ }
+ } else {
+ res = FALSE;
+ g_set_error_literal (error, E_CAL_CLIENT_ERROR, E_CAL_CLIENT_ERROR_INVALID_OBJECT, e_cal_client_error_to_string (E_CAL_CLIENT_ERROR_INVALID_OBJECT));
+ }
+ } else {
+ res = FALSE;
+ }
+
+ g_free (out_string);
+
+ return res;
+}
+
+/**
+ * e_cal_client_get_timezone_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @zone: (out): Return value for the timezone
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_get_timezone() and
+ * sets @zone to a retrieved timezone object from the calendar backend.
+ * This object is owned by the @client, thus do not free it.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_timezone_finish (ECalClient *client, GAsyncResult *result, icaltimezone **zone, GError **error)
+{
+ gboolean res;
+ gchar *out_string = NULL;
+
+ g_return_val_if_fail (zone != NULL, FALSE);
+
+ if (g_simple_async_result_get_source_tag (G_SIMPLE_ASYNC_RESULT (result)) == cal_client_get_timezone_from_cache) {
+ res = cal_client_get_timezone_from_cache_finish (client, result, zone, error);
+ } else {
+ res = e_client_proxy_call_finish_string (E_CLIENT (client), result, &out_string, error, e_cal_client_get_timezone);
+ res = complete_get_timezone (client, res, out_string, zone, error);
+ }
+
+ return res;
+}
+
+/**
+ * e_cal_client_get_timezone_sync:
+ * @client: an #ECalClient
+ * @tzid: ID of the timezone to retrieve
+ * @zone: (out): Return value for the timezone
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Retrieves a timezone object from the calendar backend.
+ * This object is owned by the @client, thus do not free it.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_timezone_sync (ECalClient *client, const gchar *tzid, icaltimezone **zone, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ gchar *gdbus_tzid = NULL, *out_string = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (tzid != NULL, FALSE);
+ g_return_val_if_fail (zone != NULL, FALSE);
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ *zone = cal_client_get_timezone_from_cache (client, tzid);
+ if (*zone)
+ return TRUE;
+
+ res = e_client_proxy_call_sync_string__string (E_CLIENT (client), e_util_ensure_gdbus_string (tzid, &gdbus_tzid), &out_string, cancellable, error, e_gdbus_cal_call_get_timezone_sync);
+
+ g_free (gdbus_tzid);
+
+ return complete_get_timezone (client, res, out_string, zone, error);
+}
+
+/**
+ * e_cal_client_add_timezone:
+ * @client: an #ECalClient
+ * @zone: The timezone to add
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Add a VTIMEZONE object to the given calendar client.
+ * The call is finished by e_cal_client_add_timezone_finish() from
+ * the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_add_timezone (ECalClient *client, /* const */ icaltimezone *zone, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ icalcomponent *icalcomp;
+ gchar *zone_str, *gdbus_zone = NULL;
+
+ g_return_if_fail (zone != NULL);
+
+ if (zone == icaltimezone_get_utc_timezone ())
+ return;
+
+ icalcomp = icaltimezone_get_component (zone);
+ g_return_if_fail (icalcomp != NULL);
+
+ zone_str = icalcomponent_as_ical_string_r (icalcomp);
+
+ e_client_proxy_call_string (E_CLIENT (client), e_util_ensure_gdbus_string (zone_str, &gdbus_zone), cancellable, callback, user_data, e_cal_client_add_timezone,
+ e_gdbus_cal_call_add_timezone,
+ e_gdbus_cal_call_add_timezone_finish, NULL, NULL, NULL, NULL);
+
+ g_free (zone_str);
+ g_free (gdbus_zone);
+}
+
+/**
+ * e_cal_client_add_timezone_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_add_timezone().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_add_timezone_finish (ECalClient *client, GAsyncResult *result, GError **error)
+{
+ return e_client_proxy_call_finish_void (E_CLIENT (client), result, error, e_cal_client_add_timezone);
+}
+
+/**
+ * e_cal_client_add_timezone_sync:
+ * @client: an #ECalClient
+ * @zone: The timezone to add
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Add a VTIMEZONE object to the given calendar client.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_add_timezone_sync (ECalClient *client, /* const */ icaltimezone *zone, GCancellable *cancellable, GError **error)
+{
+ gboolean res;
+ icalcomponent *icalcomp;
+ gchar *zone_str, *gdbus_zone = NULL;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (zone != NULL, FALSE);
+
+ if (zone == icaltimezone_get_utc_timezone ())
+ return TRUE;
+
+ icalcomp = icaltimezone_get_component (zone);
+ if (!icalcomp) {
+ g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG, e_client_error_to_string (E_CLIENT_ERROR_INVALID_ARG));
+ return FALSE;
+ }
+
+ if (!client->priv->gdbus_cal) {
+ set_proxy_gone_error (error);
+ return FALSE;
+ }
+
+ zone_str = icalcomponent_as_ical_string_r (icalcomp);
+
+ res = e_client_proxy_call_sync_string__void (E_CLIENT (client), e_util_ensure_gdbus_string (zone_str, &gdbus_zone), cancellable, error, e_gdbus_cal_call_add_timezone_sync);
+
+ g_free (zone_str);
+ g_free (gdbus_zone);
+
+ return res;
+}
+
+static GDBusProxy *
+cal_client_get_dbus_proxy (EClient *client)
+{
+ ECalClient *cal_client;
+
+ g_return_val_if_fail (client != NULL, NULL);
+
+ cal_client = E_CAL_CLIENT (client);
+ g_return_val_if_fail (cal_client != NULL, NULL);
+ g_return_val_if_fail (cal_client->priv != NULL, NULL);
+
+ return cal_client->priv->gdbus_cal;
+}
+
+static void
+cal_client_unwrap_dbus_error (EClient *client, GError *dbus_error, GError **out_error)
+{
+ unwrap_dbus_error (dbus_error, out_error);
+}
+
+static void
+cal_client_handle_authentication (EClient *client, const ECredentials *credentials)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ gchar **strv;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (credentials != NULL);
+
+ cal_client = E_CAL_CLIENT (client);
+ g_return_if_fail (cal_client != NULL);
+ g_return_if_fail (cal_client->priv != NULL);
+
+ if (!cal_client->priv->gdbus_cal)
+ return;
+
+ strv = e_credentials_to_strv (credentials);
+ g_return_if_fail (strv != NULL);
+
+ e_gdbus_cal_call_authenticate_user_sync (cal_client->priv->gdbus_cal, (const gchar * const *) strv, NULL, &error);
+
+ g_strfreev (strv);
+
+ if (error) {
+ g_debug ("%s: Failed to authenticate user: %s", G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+}
+
+static gchar *
+cal_client_retrieve_capabilities (EClient *client)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ gchar *capabilities = NULL;
+
+ g_return_val_if_fail (client != NULL, NULL);
+
+ cal_client = E_CAL_CLIENT (client);
+ g_return_val_if_fail (cal_client != NULL, NULL);
+ g_return_val_if_fail (cal_client->priv != NULL, NULL);
+
+ if (!cal_client->priv->gdbus_cal)
+ return NULL;
+
+ e_gdbus_cal_call_get_backend_property_sync (cal_client->priv->gdbus_cal, CLIENT_BACKEND_PROPERTY_CAPABILITIES, &capabilities, NULL, &error);
+
+ if (error) {
+ g_debug ("%s: Failed to retrieve capabilitites: %s", G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+
+ return capabilities;
+}
+
+static void
+free_zone_cb (gpointer zone)
+{
+ icaltimezone_free (zone, 1);
+}
+
+static void
+e_cal_client_init (ECalClient *client)
+{
+ LOCK_FACTORY ();
+ active_cal_clients++;
+ UNLOCK_FACTORY ();
+
+ client->priv = G_TYPE_INSTANCE_GET_PRIVATE (client, E_TYPE_CAL_CLIENT, ECalClientPrivate);
+ client->priv->source_type = E_CAL_CLIENT_SOURCE_TYPE_LAST;
+ client->priv->default_zone = icaltimezone_copy (icaltimezone_get_utc_timezone ());
+ client->priv->cache_dir = NULL;
+ client->priv->zone_cache_lock = g_mutex_new ();
+ client->priv->zone_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_zone_cb);
+}
+
+static void
+cal_client_dispose (GObject *object)
+{
+ EClient *client;
+
+ client = E_CLIENT (object);
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (client->priv != NULL);
+
+ e_client_cancel_all (client);
+
+ gdbus_cal_client_disconnect (E_CAL_CLIENT (client));
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_cal_client_parent_class)->dispose (object);
+}
+
+static void
+cal_client_finalize (GObject *object)
+{
+ ECalClient *client;
+ ECalClientPrivate *priv;
+
+ client = E_CAL_CLIENT (object);
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (client->priv != NULL);
+
+ priv = client->priv;
+
+ g_free (priv->cache_dir);
+ priv->cache_dir = NULL;
+
+ if (priv->default_zone)
+ icaltimezone_free (priv->default_zone, 1);
+ priv->default_zone = NULL;
+
+ g_mutex_lock (priv->zone_cache_lock);
+ g_hash_table_destroy (priv->zone_cache);
+ priv->zone_cache = NULL;
+ g_mutex_unlock (priv->zone_cache_lock);
+ g_mutex_free (priv->zone_cache_lock);
+ priv->zone_cache_lock = NULL;
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_cal_client_parent_class)->finalize (object);
+
+ LOCK_FACTORY ();
+ active_cal_clients--;
+ if (!active_cal_clients)
+ gdbus_cal_factory_proxy_disconnect (NULL);
+ UNLOCK_FACTORY ();
+}
+
+static void
+e_cal_client_class_init (ECalClientClass *klass)
+{
+ GObjectClass *object_class;
+ EClientClass *client_class;
+
+ g_type_class_add_private (klass, sizeof (ECalClientPrivate));
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = cal_client_dispose;
+ object_class->finalize = cal_client_finalize;
+
+ client_class = E_CLIENT_CLASS (klass);
+ client_class->get_dbus_proxy = cal_client_get_dbus_proxy;
+ client_class->unwrap_dbus_error = cal_client_unwrap_dbus_error;
+ client_class->handle_authentication = cal_client_handle_authentication;
+ client_class->retrieve_capabilities = cal_client_retrieve_capabilities;
+ client_class->get_backend_property = cal_client_get_backend_property;
+ client_class->get_backend_property_finish = cal_client_get_backend_property_finish;
+ client_class->get_backend_property_sync = cal_client_get_backend_property_sync;
+ client_class->set_backend_property = cal_client_set_backend_property;
+ client_class->set_backend_property_finish = cal_client_set_backend_property_finish;
+ client_class->set_backend_property_sync = cal_client_set_backend_property_sync;
+ client_class->open = cal_client_open;
+ client_class->open_finish = cal_client_open_finish;
+ client_class->open_sync = cal_client_open_sync;
+ client_class->remove = cal_client_remove;
+ client_class->remove_finish = cal_client_remove_finish;
+ client_class->remove_sync = cal_client_remove_sync;
+ client_class->refresh = cal_client_refresh;
+ client_class->refresh_finish = cal_client_refresh_finish;
+ client_class->refresh_sync = cal_client_refresh_sync;
+
+ signals[FREE_BUSY_DATA] = g_signal_new (
+ "free-busy-data",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (ECalClientClass, free_busy_data),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
+}
diff --git a/calendar/libecal/e-cal-client.h b/calendar/libecal/e-cal-client.h
new file mode 100644
index 0000000..8f2f726
--- /dev/null
+++ b/calendar/libecal/e-cal-client.h
@@ -0,0 +1,193 @@
+/*
+ * e-cal-client.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_CAL_CLIENT_H
+#define E_CAL_CLIENT_H
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <libedataserver/e-client.h>
+#include <libecal/e-cal-client-view.h>
+#include <libecal/e-cal-recur.h>
+#include <libecal/e-cal-util.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_CAL_CLIENT (e_cal_client_get_type ())
+#define E_CAL_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_CAL_CLIENT, ECalClient))
+#define E_CAL_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), E_TYPE_CAL_CLIENT, ECalClientClass))
+#define E_IS_CAL_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_CAL_CLIENT))
+#define E_IS_CAL_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_CAL_CLIENT))
+#define E_CAL_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_CAL_CLIENT, ECalClientClass))
+
+#define CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS "cal-email-address"
+#define CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS "alarm-email-address"
+#define CAL_BACKEND_PROPERTY_DEFAULT_OBJECT "default-object"
+
+typedef enum {
+ E_CAL_CLIENT_SOURCE_TYPE_EVENTS,
+ E_CAL_CLIENT_SOURCE_TYPE_TASKS,
+ E_CAL_CLIENT_SOURCE_TYPE_MEMOS,
+ E_CAL_CLIENT_SOURCE_TYPE_LAST
+} ECalClientSourceType;
+
+GType e_cal_client_source_type_enum_get_type (void);
+
+#define E_CAL_CLIENT_ERROR e_cal_client_error_quark ()
+
+GQuark e_cal_client_error_quark (void) G_GNUC_CONST;
+
+typedef enum {
+ E_CAL_CLIENT_ERROR_NO_SUCH_CALENDAR,
+ E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND,
+ E_CAL_CLIENT_ERROR_INVALID_OBJECT,
+ E_CAL_CLIENT_ERROR_UNKNOWN_USER,
+ E_CAL_CLIENT_ERROR_OBJECT_ID_ALREADY_EXISTS
+} ECalClientError;
+
+const gchar *e_cal_client_error_to_string (ECalClientError code);
+
+typedef struct _ECalClient ECalClient;
+typedef struct _ECalClientClass ECalClientClass;
+typedef struct _ECalClientPrivate ECalClientPrivate;
+
+struct _ECalClient {
+ EClient parent;
+
+ /*< private >*/
+ ECalClientPrivate *priv;
+};
+
+struct _ECalClientClass {
+ EClientClass parent;
+
+ /* Signals */
+ void (* free_busy_data) (ECalClient *client, const GSList *free_busy_ecalcomps);
+};
+
+GType e_cal_client_get_type (void);
+
+/* Creating a new calendar */
+ECalClient * e_cal_client_new (ESource *source, ECalClientSourceType source_type, GError **error);
+ECalClient * e_cal_client_new_from_uri (const gchar *uri, ECalClientSourceType source_type, GError **error);
+ECalClient * e_cal_client_new_system (ECalClientSourceType source_type, GError **error);
+ECalClient * e_cal_client_new_default (ECalClientSourceType source_type, GError **error);
+
+/* Calendar discovery */
+gboolean e_cal_client_set_default (ECalClient *client, GError **error);
+gboolean e_cal_client_set_default_source (ESource *source, ECalClientSourceType source_type, GError **error);
+gboolean e_cal_client_get_sources (ESourceList **sources, ECalClientSourceType source_type, GError **error);
+
+/* Calendar properties not managed by EClient */
+ECalClientSourceType e_cal_client_get_source_type (ECalClient *client);
+const gchar * e_cal_client_get_local_attachment_store (ECalClient *client);
+void e_cal_client_set_default_timezone (ECalClient *client, /* const */ icaltimezone *zone);
+/*const*/ icaltimezone *e_cal_client_get_default_timezone (ECalClient *client);
+
+/* Check predefined capabilities */
+gboolean e_cal_client_check_one_alarm_only (ECalClient *client);
+gboolean e_cal_client_check_save_schedules (ECalClient *client);
+gboolean e_cal_client_check_organizer_must_attend(ECalClient *client);
+gboolean e_cal_client_check_organizer_must_accept(ECalClient *client);
+gboolean e_cal_client_check_recurrences_no_master(ECalClient *client);
+
+/* Utility functions */
+void e_cal_client_free_icalcomp_slist (GSList *icalcomps);
+void e_cal_client_free_ecalcomp_slist (GSList *ecalcomps);
+
+icaltimezone * e_cal_client_resolve_tzid_cb (const gchar *tzid, gpointer data);
+void e_cal_client_generate_instances (ECalClient *client, time_t start, time_t end, ECalRecurInstanceFn cb, gpointer cb_data);
+void e_cal_client_generate_instances_for_object (ECalClient *client, icalcomponent *icalcomp, time_t start, time_t end, ECalRecurInstanceFn cb, gpointer cb_data);
+gchar * e_cal_client_get_component_as_string (ECalClient *client, icalcomponent *icalcomp);
+
+/* Calendar methods */
+void e_cal_client_get_default_object (ECalClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_get_default_object_finish (ECalClient *client, GAsyncResult *result, icalcomponent **icalcomp, GError **error);
+gboolean e_cal_client_get_default_object_sync (ECalClient *client, icalcomponent **icalcomp, GCancellable *cancellable, GError **error);
+
+void e_cal_client_refresh (ECalClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_refresh_finish (ECalClient *client, GAsyncResult *result, GError **error);
+gboolean e_cal_client_refresh_sync (ECalClient *client, GCancellable *cancellable, GError **error);
+
+void e_cal_client_get_object (ECalClient *client, const gchar *uid, const gchar *rid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_get_object_finish (ECalClient *client, GAsyncResult *result, icalcomponent **icalcomp, GError **error);
+gboolean e_cal_client_get_object_sync (ECalClient *client, const gchar *uid, const gchar *rid, icalcomponent **icalcomp, GCancellable *cancellable, GError **error);
+
+void e_cal_client_get_objects_for_uid (ECalClient *client, const gchar *uid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_get_objects_for_uid_finish (ECalClient *client, GAsyncResult *result, GSList **ecalcomps, GError **error);
+gboolean e_cal_client_get_objects_for_uid_sync (ECalClient *client, const gchar *uid, GSList **ecalcomps, GCancellable *cancellable, GError **error);
+
+void e_cal_client_get_object_list (ECalClient *client, const gchar *sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_get_object_list_finish (ECalClient *client, GAsyncResult *result, GSList **icalcomps, GError **error);
+gboolean e_cal_client_get_object_list_sync (ECalClient *client, const gchar *sexp, GSList **icalcomps, GCancellable *cancellable, GError **error);
+
+void e_cal_client_get_object_list_as_comps (ECalClient *client, const gchar *sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_get_object_list_as_comps_finish (ECalClient *client, GAsyncResult *result, GSList **ecalcomps, GError **error);
+gboolean e_cal_client_get_object_list_as_comps_sync (ECalClient *client, const gchar *sexp, GSList **ecalcomps, GCancellable *cancellable, GError **error);
+
+void e_cal_client_get_free_busy (ECalClient *client, time_t start, time_t end, const GSList *users, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_get_free_busy_finish (ECalClient *client, GAsyncResult *result, GError **error);
+gboolean e_cal_client_get_free_busy_sync (ECalClient *client, time_t start, time_t end, const GSList *users, GCancellable *cancellable, GError **error);
+
+void e_cal_client_create_object (ECalClient *client, /* const */ icalcomponent *icalcomp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_create_object_finish (ECalClient *client, GAsyncResult *result, gchar **uid, GError **error);
+gboolean e_cal_client_create_object_sync (ECalClient *client, /* const */ icalcomponent *icalcomp, gchar **uid, GCancellable *cancellable, GError **error);
+
+void e_cal_client_modify_object (ECalClient *client, /* const */ icalcomponent *icalcomp, CalObjModType mod, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_modify_object_finish (ECalClient *client, GAsyncResult *result, GError **error);
+gboolean e_cal_client_modify_object_sync (ECalClient *client, /* const */ icalcomponent *icalcomp, CalObjModType mod, GCancellable *cancellable, GError **error);
+
+void e_cal_client_remove_object (ECalClient *client, const gchar *uid, const gchar *rid, CalObjModType mod, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_remove_object_finish (ECalClient *client, GAsyncResult *result, GError **error);
+gboolean e_cal_client_remove_object_sync (ECalClient *client, const gchar *uid, const gchar *rid, CalObjModType mod, GCancellable *cancellable, GError **error);
+
+void e_cal_client_receive_objects (ECalClient *client, /* const */ icalcomponent *icalcomp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_receive_objects_finish (ECalClient *client, GAsyncResult *result, GError **error);
+gboolean e_cal_client_receive_objects_sync (ECalClient *client, /* const */ icalcomponent *icalcomp, GCancellable *cancellable, GError **error);
+
+void e_cal_client_send_objects (ECalClient *client, /* const */ icalcomponent *icalcomp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_send_objects_finish (ECalClient *client, GAsyncResult *result, GSList **users, icalcomponent **modified_icalcomp, GError **error);
+gboolean e_cal_client_send_objects_sync (ECalClient *client, /* const */ icalcomponent *icalcomp, GSList **users, icalcomponent **modified_icalcomp, GCancellable *cancellable, GError **error);
+
+void e_cal_client_get_attachment_uris (ECalClient *client, const gchar *uid, const gchar *rid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_get_attachment_uris_finish (ECalClient *client, GAsyncResult *result, GSList **attachment_uris, GError **error);
+gboolean e_cal_client_get_attachment_uris_sync (ECalClient *client, const gchar *uid, const gchar *rid, GSList **attachment_uris, GCancellable *cancellable, GError **error);
+
+void e_cal_client_discard_alarm (ECalClient *client, const gchar *uid, const gchar *rid, const gchar *auid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_discard_alarm_finish (ECalClient *client, GAsyncResult *result, GError **error);
+gboolean e_cal_client_discard_alarm_sync (ECalClient *client, const gchar *uid, const gchar *rid, const gchar *auid, GCancellable *cancellable, GError **error);
+
+void e_cal_client_get_view (ECalClient *client, const gchar *sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_get_view_finish (ECalClient *client, GAsyncResult *result, ECalClientView **view, GError **error);
+gboolean e_cal_client_get_view_sync (ECalClient *client, const gchar *sexp, ECalClientView **view, GCancellable *cancellable, GError **error);
+
+void e_cal_client_get_timezone (ECalClient *client, const gchar *tzid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_get_timezone_finish (ECalClient *client, GAsyncResult *result, icaltimezone **zone, GError **error);
+gboolean e_cal_client_get_timezone_sync (ECalClient *client, const gchar *tzid, icaltimezone **zone, GCancellable *cancellable, GError **error);
+
+void e_cal_client_add_timezone (ECalClient *client, /* const */ icaltimezone *zone, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_cal_client_add_timezone_finish (ECalClient *client, GAsyncResult *result, GError **error);
+gboolean e_cal_client_add_timezone_sync (ECalClient *client, /* const */ icaltimezone *zone, GCancellable *cancellable, GError **error);
+
+G_END_DECLS
+
+#endif /* E_CAL_CLIENT_H */
diff --git a/calendar/libecal/e-cal-types.h b/calendar/libecal/e-cal-types.h
index a9dca51..bd9be80 100644
--- a/calendar/libecal/e-cal-types.h
+++ b/calendar/libecal/e-cal-types.h
@@ -28,6 +28,8 @@ G_BEGIN_DECLS
+#ifndef E_CAL_DISABLE_DEPRECATED
+
#define E_CALENDAR_ERROR e_calendar_error_quark()
GQuark e_calendar_error_quark (void) G_GNUC_CONST;
@@ -68,7 +70,6 @@ typedef enum {
E_CALENDAR_STATUS_NOT_SUPPORTED
} ECalendarStatus;
-#ifndef E_CAL_DISABLE_DEPRECATED
#define E_CALENDAR_STATUS_CORBA_EXCEPTION E_CALENDAR_STATUS_DBUS_EXCEPTION
#endif
diff --git a/calendar/libecal/e-cal-view.c b/calendar/libecal/e-cal-view.c
index 98f6df7..0ca1437 100644
--- a/calendar/libecal/e-cal-view.c
+++ b/calendar/libecal/e-cal-view.c
@@ -30,13 +30,13 @@
#include "e-cal.h"
#include "e-cal-view.h"
#include "e-cal-view-private.h"
-#include "e-gdbus-egdbuscalview.h"
+#include "e-gdbus-cal-view.h"
G_DEFINE_TYPE (ECalView, e_cal_view, G_TYPE_OBJECT);
/* Private part of the ECalView structure */
struct _ECalViewPrivate {
- EGdbusCalView *gdbus_calview;
+ GDBusProxy *gdbus_calview;
ECal *client;
};
@@ -155,7 +155,7 @@ objects_removed_cb (EGdbusCalView *gdbus_calview, const gchar * const *uids, ECa
}
static void
-progress_cb (EGdbusCalView *gdbus_calview, const gchar *message, guint percent, ECalView *view)
+progress_cb (EGdbusCalView *gdbus_calview, guint percent, const gchar *message, ECalView *view)
{
g_return_if_fail (E_IS_CAL_VIEW (view));
@@ -163,15 +163,22 @@ progress_cb (EGdbusCalView *gdbus_calview, const gchar *message, guint percent,
}
static void
-done_cb (EGdbusCalView *gdbus_calview, /* ECalendarStatus */ guint status, const gchar *message, ECalView *view)
+complete_cb (EGdbusCalView *gdbus_calview, const gchar * const *arg_error, ECalView *view)
{
+ GError *error = NULL;
+
g_return_if_fail (E_IS_CAL_VIEW (view));
+ g_return_if_fail (e_gdbus_templates_decode_error (arg_error, &error));
+
#ifndef E_CAL_DISABLE_DEPRECATED
- g_signal_emit (G_OBJECT (view), signals[VIEW_DONE], 0, status);
+ g_signal_emit (G_OBJECT (view), signals[VIEW_DONE], 0, error ? error->code : 0);
#endif
- g_signal_emit (G_OBJECT (view), signals[VIEW_COMPLETE], 0, status, message);
+ g_signal_emit (G_OBJECT (view), signals[VIEW_COMPLETE], 0, error ? error->code : 0, error ? error->message : "");
+
+ if (error)
+ g_error_free (error);
}
/* Object initialization function for the calendar view */
@@ -201,7 +208,7 @@ e_cal_view_set_property (GObject *object, guint property_id, const GValue *value
g_signal_connect (priv->gdbus_calview, "objects-modified", G_CALLBACK (objects_modified_cb), view);
g_signal_connect (priv->gdbus_calview, "objects-removed", G_CALLBACK (objects_removed_cb), view);
g_signal_connect (priv->gdbus_calview, "progress", G_CALLBACK (progress_cb), view);
- g_signal_connect (priv->gdbus_calview, "done", G_CALLBACK (done_cb), view);
+ g_signal_connect (priv->gdbus_calview, "complete", G_CALLBACK (complete_cb), view);
break;
case PROP_CLIENT:
priv->client = E_CAL (g_value_dup_object (value));
@@ -261,7 +268,10 @@ e_cal_view_finalize (GObject *object)
}
}
- g_object_unref (priv->client);
+ if (priv->client) {
+ g_object_unref (priv->client);
+ priv->client = NULL;
+ }
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_cal_view_parent_class)->finalize (object);
@@ -358,7 +368,7 @@ e_cal_view_class_init (ECalViewClass *klass)
}
/**
- * _e_cal_view_new:
+ * _e_cal_view_new_for_ecal:
* @client: An #ECal object.
* @gdbuc_calview: The GDBus object for the view.
*
@@ -366,14 +376,16 @@ e_cal_view_class_init (ECalViewClass *klass)
* calendar server.
*
* Returns: A newly-created view object, or NULL if the request failed.
+ *
+ * Deprecated: 3.2: Use #ECalClientView
**/
ECalView *
-_e_cal_view_new (ECal *client, EGdbusCalView *gdbus_calview)
+_e_cal_view_new (ECal *ecal, EGdbusCalView *gdbus_calview)
{
ECalView *view;
view = g_object_new (E_TYPE_CAL_VIEW,
- "client", client,
+ "client", ecal,
"view", gdbus_calview,
NULL);
@@ -389,6 +401,8 @@ _e_cal_view_new (ECal *client, EGdbusCalView *gdbus_calview)
* Returns: the associated client.
*
* Since: 2.22
+ *
+ * Deprecated: 3.2: Use #ECalClientView
*/
ECal *
e_cal_view_get_client (ECalView *view)
@@ -405,6 +419,8 @@ e_cal_view_get_client (ECalView *view)
* Starts a live query to the calendar/tasks backend.
*
* Since: 2.22
+ *
+ * Deprecated: 3.2: Use #ECalClientView
*/
void
e_cal_view_start (ECalView *view)
@@ -441,6 +457,8 @@ e_cal_view_start (ECalView *view)
* Stops a live query to the calendar/tasks backend.
*
* Since: 2.32
+ *
+ * Deprecated: 3.2: Use #ECalClientView
*/
void
e_cal_view_stop (ECalView *view)
diff --git a/calendar/libecal/e-cal-view.h b/calendar/libecal/e-cal-view.h
index 0a3a5a0..a090a1c 100644
--- a/calendar/libecal/e-cal-view.h
+++ b/calendar/libecal/e-cal-view.h
@@ -21,6 +21,8 @@
#ifndef E_CAL_VIEW_H
#define E_CAL_VIEW_H
+#ifndef E_CAL_DISABLE_DEPRECATED
+
#include <glib-object.h>
#include <libecal/e-cal-types.h>
@@ -35,6 +37,7 @@ G_BEGIN_DECLS
typedef struct _ECalView ECalView;
typedef struct _ECalViewClass ECalViewClass;
typedef struct _ECalViewPrivate ECalViewPrivate;
+
struct _ECal;
struct _ECalView {
@@ -61,9 +64,12 @@ struct _ECalViewClass {
GType e_cal_view_get_type (void);
struct _ECal *e_cal_view_get_client (ECalView *view);
+
void e_cal_view_start (ECalView *view);
void e_cal_view_stop (ECalView *view);
G_END_DECLS
+#endif /* E_CAL_DISABLE_DEPRECATED */
+
#endif
diff --git a/calendar/libecal/e-cal.c b/calendar/libecal/e-cal.c
index b7d0e70..0dd0e10 100644
--- a/calendar/libecal/e-cal.c
+++ b/calendar/libecal/e-cal.c
@@ -28,6 +28,8 @@
* The old signal "cal-opened" is deprecated since 3.0 and is replaced with
* its equivalent "cal_opened_ex", which has a detailed #GError structure
* as a parameter, instead of a status code only.
+ *
+ * Deprecated: 3.2: Use #ECalClient instead.
*/
#ifdef HAVE_CONFIG_H
@@ -40,6 +42,7 @@
#include <libical/ical.h>
#include <libedataserver/e-url.h>
+#include <libedataserver/e-credentials.h>
#include <libedataserver/e-data-server-util.h>
#include <glib-object.h>
@@ -52,9 +55,15 @@
#include "e-cal-view-private.h"
#include "e-cal.h"
-#include "e-gdbus-egdbuscalfactory.h"
-#include "e-gdbus-egdbuscal.h"
-#include "e-gdbus-egdbuscalview.h"
+#include "e-gdbus-cal.h"
+#include "e-gdbus-cal-view.h"
+#include "e-gdbus-cal-factory.h"
+
+#define CLIENT_BACKEND_PROPERTY_CACHE_DIR "cache-dir"
+#define CLIENT_BACKEND_PROPERTY_CAPABILITIES "capabilities"
+#define CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS "cal-email-address"
+#define CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS "alarm-email-address"
+#define CAL_BACKEND_PROPERTY_DEFAULT_OBJECT "default-object"
static guint active_cals = 0, cal_connection_closed_id = 0;
static EGdbusCalFactory *cal_factory_proxy = NULL;
@@ -77,7 +86,7 @@ static void e_cal_finalize (GObject *object);
/* Private part of the ECal structure */
struct _ECalPrivate {
- EGdbusCal *gdbus_cal;
+ GDBusProxy *gdbus_cal;
guint gone_signal_id;
/* Load state to avoid multiple loads */
@@ -99,6 +108,7 @@ struct _ECalPrivate {
gchar *capabilities;
gint mode;
+ gboolean requires_auth;
gboolean read_only;
@@ -119,6 +129,9 @@ struct _ECalPrivate {
/* For locking the operation while localling cache values like
static capabilities, cal address etc. */
GStaticRecMutex cache_lock;
+
+ GList **free_busy_data;
+ GMutex *free_busy_data_lock;
};
@@ -217,6 +230,7 @@ get_status_from_error (const GError *error)
ECalendarStatus err_code;
} errors[] = {
{ err ("Success", E_CALENDAR_STATUS_OK) },
+ { err ("Busy", E_CALENDAR_STATUS_BUSY) },
{ err ("RepositoryOffline", E_CALENDAR_STATUS_REPOSITORY_OFFLINE) },
{ err ("PermissionDenied", E_CALENDAR_STATUS_PERMISSION_DENIED) },
{ err ("InvalidRange", E_CALENDAR_STATUS_OTHER_ERROR) },
@@ -305,6 +319,8 @@ unwrap_gerror (GError **error)
* Registers the #ECalSourceTypeEnum type with glib.
*
* Returns: the ID of the #ECalSourceTypeEnum type.
+ *
+ * Deprecated: 3.2: Use e_cal_client_source_type_enum_get_type() instead.
*/
GType
e_cal_source_type_enum_get_type (void)
@@ -334,6 +350,8 @@ e_cal_source_type_enum_get_type (void)
* Registers the #ECalSetModeStatusEnum type with glib.
*
* Returns: the ID of the #ECalSetModeStatusEnum type.
+ *
+ * Deprecated: 3.2: This type has been dropped completely.
*/
GType
e_cal_set_mode_status_enum_get_type (void)
@@ -362,6 +380,8 @@ e_cal_set_mode_status_enum_get_type (void)
* Registers the #CalModeEnum type with glib.
*
* Returns: the ID of the #CalModeEnum type.
+ *
+ * Deprecated: 3.2: This type has been dropped completely.
*/
GType
cal_mode_enum_get_type (void)
@@ -401,6 +421,7 @@ convert_type (ECalSourceType type)
return AnyType;
}
+
static void
e_cal_init (ECal *ecal)
{
@@ -424,6 +445,7 @@ e_cal_init (ECal *ecal)
priv->gdbus_cal = NULL;
priv->timezones = g_hash_table_new (g_str_hash, g_str_equal);
priv->default_zone = icaltimezone_get_utc_timezone ();
+ priv->free_busy_data_lock = g_mutex_new ();
g_static_rec_mutex_init (&priv->cache_lock);
}
@@ -559,10 +581,20 @@ e_cal_finalize (GObject *object)
priv->capabilities = NULL;
}
+ if (priv->free_busy_data) {
+ g_mutex_lock (priv->free_busy_data_lock);
+ g_list_foreach (*priv->free_busy_data, (GFunc) g_object_unref, NULL);
+ g_list_free (*priv->free_busy_data);
+ *priv->free_busy_data = NULL;
+ priv->free_busy_data = NULL;
+ g_mutex_unlock (priv->free_busy_data_lock);
+ }
+
g_hash_table_foreach (priv->timezones, free_timezone, NULL);
g_hash_table_destroy (priv->timezones);
priv->timezones = NULL;
g_static_rec_mutex_free (&priv->cache_lock);
+ g_mutex_free (priv->free_busy_data_lock);
(* G_OBJECT_CLASS (parent_class)->finalize) (object);
@@ -729,6 +761,176 @@ e_cal_activate (GError **error)
return TRUE;
}
+static gchar *
+build_proxy_pass_key (ECal *ecal, const gchar * parent_user)
+{
+ gchar *euri_str;
+ const gchar *uri;
+ EUri *euri;
+
+ uri = e_cal_get_uri (ecal);
+
+ euri = e_uri_new (uri);
+ g_free (euri->user);
+ euri->user = g_strdup (parent_user);
+
+ euri_str = e_uri_to_string (euri, FALSE);
+
+ e_uri_free (euri);
+ return euri_str;
+}
+
+static gchar *
+build_pass_key (ECal *ecal)
+{
+ gchar *euri_str;
+ const gchar *uri;
+ EUri *euri;
+
+ uri = e_cal_get_uri (ecal);
+
+ euri = e_uri_new (uri);
+ euri_str = e_uri_to_string (euri, FALSE);
+
+ e_uri_free (euri);
+ return euri_str;
+}
+
+static void async_open_report_result (ECal *ecal, const GError *error);
+
+static void
+authenticate_user_ready_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECal *cal = user_data;
+ GError *error = NULL;
+
+ g_return_if_fail (cal != NULL);
+
+ if (!e_gdbus_cal_call_authenticate_user_finish (G_DBUS_PROXY (source_object), result, &error))
+ cal->priv->load_state = E_CAL_LOAD_NOT_LOADED;
+ else
+ cal->priv->load_state = E_CAL_LOAD_LOADED;
+
+ if (cal->priv->requires_auth && !error) {
+ cal->priv->load_state = E_CAL_LOAD_NOT_LOADED;
+ g_set_error_literal (&error, E_CALENDAR_ERROR, E_CALENDAR_STATUS_AUTHENTICATION_FAILED, e_cal_get_error_message (E_CALENDAR_STATUS_AUTHENTICATION_FAILED));
+ }
+
+ unwrap_gerror (&error);
+ async_open_report_result (cal, error);
+
+ if (error)
+ g_error_free (error);
+}
+
+static gboolean
+call_authenticate_user (ECal *cal, gboolean async, GError **error)
+{
+ gchar *username = NULL, *password = NULL;
+ ECredentials *credentials = NULL;
+ ECalPrivate *priv;
+
+ g_return_val_if_fail (cal != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL (cal), FALSE);
+
+ priv = cal->priv;
+
+ if (!priv->gdbus_cal) {
+ E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
+ }
+
+ /* see if the backend needs authentication */
+ if ((priv->mode != CAL_MODE_LOCAL) && (e_source_get_property (priv->source, "auth") || priv->requires_auth)) {
+ gchar *prompt, *key, *auth_type = NULL;
+ gchar *parent_user;
+
+ priv->load_state = E_CAL_LOAD_AUTHENTICATING;
+
+ if (priv->auth_func == NULL) {
+ priv->load_state = E_CAL_LOAD_NOT_LOADED;
+ E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED, error);
+ }
+
+ username = e_source_get_duped_property (priv->source, "username");
+ if (!username) {
+ priv->load_state = E_CAL_LOAD_NOT_LOADED;
+ E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED, error);
+ }
+
+ prompt = g_strdup_printf (_("Enter password for %s (user %s)"),
+ e_source_peek_name (priv->source), username);
+
+ auth_type = e_source_get_duped_property (priv->source, "auth-type");
+ if (auth_type)
+ key = build_pass_key (cal);
+ else {
+ parent_user = e_source_get_duped_property (priv->source, "parent_id_name");
+ if (parent_user) {
+ key = build_proxy_pass_key (cal, parent_user);
+ /*
+ This password prompt will be prompted rarely. Since the key that is passed to
+ the auth_func corresponds to the parent user.
+ */
+ prompt = g_strdup_printf (_("Enter password for %s to enable proxy for user %s"), e_source_peek_name (priv->source), parent_user);
+ g_free (parent_user);
+ } else
+ key = g_strdup (e_cal_get_uri (cal));
+ }
+ g_free (auth_type);
+
+ if (!key) {
+ priv->load_state = E_CAL_LOAD_NOT_LOADED;
+ g_free (username);
+ E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED, error);
+ }
+
+ password = priv->auth_func (cal, prompt, key, priv->auth_user_data);
+
+ if (!password) {
+ priv->load_state = E_CAL_LOAD_NOT_LOADED;
+ g_free (username);
+ E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED, error);
+ }
+
+ g_free (prompt);
+ g_free (key);
+ }
+
+ if (username)
+ credentials = e_credentials_new_args (
+ E_CREDENTIALS_KEY_USERNAME, username,
+ E_CREDENTIALS_KEY_PASSWORD, password,
+ NULL);
+ else
+ priv->load_state = E_CAL_LOAD_NOT_LOADED;
+
+ g_free (username);
+ e_credentials_util_safe_free_string (password);
+
+ if (credentials) {
+ gchar **strv = e_credentials_to_strv (credentials);
+
+ if (async) {
+ cal->priv->requires_auth = FALSE;
+ e_gdbus_cal_call_authenticate_user (cal->priv->gdbus_cal, (const gchar * const *) strv, NULL, authenticate_user_ready_cb, cal);
+ } else if (e_gdbus_cal_call_authenticate_user_sync (cal->priv->gdbus_cal, (const gchar * const *) strv, NULL, error))
+ priv->load_state = E_CAL_LOAD_LOADED;
+ else
+ priv->load_state = E_CAL_LOAD_NOT_LOADED;
+
+ g_strfreev (strv);
+ e_credentials_free (credentials);
+
+ if (error && *error)
+ unwrap_gerror (error);
+ } else if (priv->requires_auth) {
+ priv->load_state = E_CAL_LOAD_NOT_LOADED;
+ g_set_error_literal (error, E_CALENDAR_ERROR, E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED, e_cal_get_error_message (E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED));
+ }
+
+ return credentials && (!error || !*error);
+}
+
static gboolean
reopen_with_auth (gpointer data)
{
@@ -750,11 +952,62 @@ reopen_with_auth (gpointer data)
}
static void
-auth_required_cb (EGdbusCal *gdbus_cal, ECal *cal)
+auth_required_cb (EGdbusCal *gdbus_cal, const gchar * const *credentials_strv, ECal *cal)
+{
+ ECalPrivate *priv;
+ g_return_if_fail (E_IS_CAL (cal));
+
+ priv = cal->priv;
+
+ priv->requires_auth = TRUE;
+
+ if (priv->load_state != E_CAL_LOAD_AUTHENTICATING)
+ g_idle_add (reopen_with_auth, (gpointer) cal);
+}
+
+static void
+free_busy_data_cb (EGdbusCal *gdbus_cal, const gchar * const *free_busy_strv, ECal *cal)
{
+ ECalPrivate *priv;
+
g_return_if_fail (E_IS_CAL (cal));
- g_idle_add (reopen_with_auth, (gpointer) cal);
+ priv = cal->priv;
+
+ g_mutex_lock (priv->free_busy_data_lock);
+
+ if (priv->free_busy_data) {
+ gint ii;
+ GList *list = *priv->free_busy_data;
+
+ for (ii = 0; free_busy_strv[ii]; ii++) {
+ ECalComponent *comp;
+ icalcomponent *icalcomp;
+ icalcomponent_kind kind;
+
+ icalcomp = icalcomponent_new_from_string (free_busy_strv[ii]);
+ if (!icalcomp)
+ continue;
+
+ kind = icalcomponent_isa (icalcomp);
+ if (kind == ICAL_VFREEBUSY_COMPONENT) {
+ comp = e_cal_component_new ();
+ if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
+ icalcomponent_free (icalcomp);
+ g_object_unref (G_OBJECT (comp));
+ continue;
+ }
+
+ list = g_list_append (list, comp);
+ } else {
+ icalcomponent_free (icalcomp);
+ }
+ }
+
+ *priv->free_busy_data = list;
+ }
+
+ g_mutex_unlock (priv->free_busy_data_lock);
}
typedef struct
@@ -805,13 +1058,12 @@ readonly_cb (EGdbusCal *gdbus_cal, gboolean read_only, ECal *cal)
}
static void
-mode_cb (EGdbusCal *gdbus_cal, EDataCalMode mode, ECal *cal)
+online_cb (EGdbusCal *gdbus_cal, gboolean is_online, ECal *cal)
{
g_return_if_fail (E_IS_CAL (cal));
- g_return_if_fail (mode & AnyMode);
g_signal_emit (G_OBJECT (cal), e_cal_signals[CAL_SET_MODE],
- 0, E_CALENDAR_STATUS_OK, mode);
+ 0, E_CALENDAR_STATUS_OK, is_online ? Remote : Local);
}
/*
@@ -832,8 +1084,8 @@ set_local_attachment_store (ECal *ecal)
gchar *cache_dir = NULL;
GError *error = NULL;
- e_gdbus_cal_call_get_cache_dir_sync (
- ecal->priv->gdbus_cal, &cache_dir, NULL, &error);
+ e_gdbus_cal_call_get_backend_property_sync (
+ ecal->priv->gdbus_cal, CLIENT_BACKEND_PROPERTY_CACHE_DIR, &cache_dir, NULL, &error);
if (error == NULL)
ecal->priv->local_attachment_store = cache_dir;
@@ -854,13 +1106,15 @@ set_local_attachment_store (ECal *ecal)
*
* Returns: A newly-created calendar client, or NULL if the client could
* not be constructed because it could not contact the calendar server.
+ *
+ * Deprecated: 3.2: Use e_cal_client_new() instead.
**/
ECal *
e_cal_new (ESource *source, ECalSourceType type)
{
ECal *ecal;
ECalPrivate *priv;
- gchar *path, *xml;
+ gchar *path, *xml, **strv;
GError *error = NULL;
GDBusConnection *connection;
@@ -883,7 +1137,9 @@ e_cal_new (ESource *source, ECalSourceType type)
priv->type = type;
xml = e_source_to_standalone_xml (priv->source);
- if (!e_gdbus_cal_factory_call_get_cal_sync (cal_factory_proxy, xml, convert_type (priv->type), &path, NULL, &error)) {
+ strv = e_gdbus_cal_factory_encode_get_cal (xml, convert_type (priv->type));
+ if (!e_gdbus_cal_factory_call_get_cal_sync (G_DBUS_PROXY (cal_factory_proxy), (const gchar * const *) strv, &path, NULL, &error)) {
+ g_strfreev (strv);
g_free (xml);
unwrap_gerror (&error);
g_warning ("Cannot get cal from factory: %s", error ? error->message : "Unknown error");
@@ -892,14 +1148,15 @@ e_cal_new (ESource *source, ECalSourceType type)
g_object_unref (ecal);
return NULL;
}
+ g_strfreev (strv);
g_free (xml);
- priv->gdbus_cal = e_gdbus_cal_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy)),
+ priv->gdbus_cal = G_DBUS_PROXY (e_gdbus_cal_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy)),
G_DBUS_PROXY_FLAGS_NONE,
CALENDAR_DBUS_SERVICE_NAME,
path,
NULL,
- &error);
+ &error));
if (!priv->gdbus_cal) {
g_free (path);
@@ -925,7 +1182,8 @@ e_cal_new (ESource *source, ECalSourceType type)
g_signal_connect (priv->gdbus_cal, "auth-required", G_CALLBACK (auth_required_cb), ecal);
g_signal_connect (priv->gdbus_cal, "backend-error", G_CALLBACK (backend_error_cb), ecal);
g_signal_connect (priv->gdbus_cal, "readonly", G_CALLBACK (readonly_cb), ecal);
- g_signal_connect (priv->gdbus_cal, "mode", G_CALLBACK (mode_cb), ecal);
+ g_signal_connect (priv->gdbus_cal, "online", G_CALLBACK (online_cb), ecal);
+ g_signal_connect (priv->gdbus_cal, "free-busy-data", G_CALLBACK (free_busy_data_cb), ecal);
/* Set the local attachment store path for the calendar */
set_local_attachment_store (ecal);
@@ -1010,6 +1268,8 @@ check_uri (ESource *source, gpointer uri)
*
* Returns: A newly-created calendar client, or NULL if the client could
* not be constructed because it could not contact the calendar server.
+ *
+ * Deprecated: 3.2: Use e_cal_client_new_from_uri() instead.
**/
ECal *
e_cal_new_from_uri (const gchar *uri, ECalSourceType type)
@@ -1090,6 +1350,8 @@ get_local_source (ECalSourceType type)
*
* Returns: A newly-created calendar client, or %NULL if the client could
* not be constructed.
+ *
+ * Deprecated: 3.2: Use e_cal_client_new_system() instead.
*/
ECal *
e_cal_new_system_calendar (void)
@@ -1106,6 +1368,8 @@ e_cal_new_system_calendar (void)
*
* Returns: A newly-created calendar client, or %NULL if the client could
* not be constructed.
+ *
+ * Deprecated: 3.2: Use e_cal_client_new_system() instead.
*/
ECal *
e_cal_new_system_tasks (void)
@@ -1122,6 +1386,8 @@ e_cal_new_system_tasks (void)
*
* Returns: A newly-created calendar client, or %NULL if the client could
* not be constructed.
+ *
+ * Deprecated: 3.2: Use e_cal_client_new_system() instead.
*/
ECal *
e_cal_new_system_memos (void)
@@ -1154,6 +1420,8 @@ e_cal_new_system_memos (void)
* const gchar *prompt,
* const gchar *key,
* gpointer user_data)
+ *
+ * Deprecated: 3.2: Use EClient::authenticate() signal on an #ECalClient instead.
*/
void
e_cal_set_auth_func (ECal *ecal, ECalAuthFunc func, gpointer data)
@@ -1165,41 +1433,6 @@ e_cal_set_auth_func (ECal *ecal, ECalAuthFunc func, gpointer data)
ecal->priv->auth_user_data = data;
}
-static gchar *
-build_proxy_pass_key (ECal *ecal, const gchar * parent_user)
-{
- gchar *euri_str;
- const gchar *uri;
- EUri *euri;
-
- uri = e_cal_get_uri (ecal);
-
- euri = e_uri_new (uri);
- g_free (euri->user);
- euri->user = g_strdup (parent_user);
-
- euri_str = e_uri_to_string (euri, FALSE);
-
- e_uri_free (euri);
- return euri_str;
-}
-
-static gchar *
-build_pass_key (ECal *ecal)
-{
- gchar *euri_str;
- const gchar *uri;
- EUri *euri;
-
- uri = e_cal_get_uri (ecal);
-
- euri = e_uri_new (uri);
- euri_str = e_uri_to_string (euri, FALSE);
-
- e_uri_free (euri);
- return euri_str;
-}
-
static void
async_open_report_result (ECal *ecal, const GError *error)
{
@@ -1220,7 +1453,6 @@ async_open_report_result (ECal *ecal, const GError *error)
#else
} else {
#endif
- e_gdbus_cal_call_is_read_only_sync (ecal->priv->gdbus_cal, NULL, NULL);
}
#ifndef E_CAL_DISABLE_DEPRECATED
@@ -1229,14 +1461,43 @@ async_open_report_result (ECal *ecal, const GError *error)
g_signal_emit (G_OBJECT (ecal), e_cal_signals[CAL_OPENED_EX], 0, error);
}
+static gboolean
+reschedule_authenticate_cb (gpointer user_data)
+{
+ GError *error = NULL;
+ ECal *ecal = user_data;
+
+ g_return_val_if_fail (ecal && E_IS_CAL (ecal), FALSE);
+
+ if (g_main_depth () > 1)
+ return TRUE;
+
+ if (call_authenticate_user (ecal, TRUE, &error))
+ return FALSE;
+
+ unwrap_gerror (&error);
+ async_open_report_result (ecal, error);
+
+ if (error)
+ g_error_free (error);
+
+ return FALSE;
+}
+
static void
-async_open_ready_cb (EGdbusCal *gdbus_cal, GAsyncResult *res, ECal *ecal)
+async_open_ready_cb (GDBusProxy *gdbus_cal, GAsyncResult *res, ECal *ecal)
{
GError *error = NULL;
g_return_if_fail (ecal && E_IS_CAL (ecal));
- e_gdbus_cal_call_open_finish (gdbus_cal, res, &error);
+ if (e_gdbus_cal_call_open_finish (gdbus_cal, res, &error)) {
+ if (g_main_depth () > 1) {
+ g_idle_add (reschedule_authenticate_cb, ecal);
+ return;
+ } else if (call_authenticate_user (ecal, TRUE, &error))
+ return;
+ }
unwrap_gerror (&error);
@@ -1254,7 +1515,6 @@ open_calendar (ECal *ecal, gboolean only_if_exists, GError **error,
gboolean needs_auth, gboolean async)
{
ECalPrivate *priv;
- gchar *username = NULL, *auth_type = NULL, *password = NULL;
g_return_val_if_fail (error != NULL, FALSE);
@@ -1267,11 +1527,9 @@ open_calendar (ECal *ecal, gboolean only_if_exists, GError **error,
return TRUE;
}
- /* see if the backend needs authentication */
- if ( (priv->mode != CAL_MODE_LOCAL) && e_source_get_property (priv->source, "auth")) {
- gchar *prompt, *key;
- gchar *parent_user;
+ priv->load_state = E_CAL_LOAD_LOADING;
+ if ((priv->mode != CAL_MODE_LOCAL) && e_source_get_property (priv->source, "auth")) {
priv->load_state = E_CAL_LOAD_AUTHENTICATING;
if (priv->auth_func == NULL) {
@@ -1282,8 +1540,7 @@ open_calendar (ECal *ecal, gboolean only_if_exists, GError **error,
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED, error);
}
- username = e_source_get_duped_property (priv->source, "username");
- if (!username) {
+ if (!e_source_get_property (priv->source, "username")) {
priv->load_state = E_CAL_LOAD_NOT_LOADED;
#ifndef E_CAL_DISABLE_DEPRECATED
*status = E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED;
@@ -1291,89 +1548,29 @@ open_calendar (ECal *ecal, gboolean only_if_exists, GError **error,
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED, error);
}
- prompt = g_strdup_printf (_("Enter password for %s (user %s)"),
- e_source_peek_name (priv->source), username);
-
- auth_type = e_source_get_duped_property (priv->source, "auth-type");
- if (auth_type)
- key = build_pass_key (ecal);
- else {
- parent_user = e_source_get_duped_property (priv->source, "parent_id_name");
- if (parent_user) {
- key = build_proxy_pass_key (ecal, parent_user);
- /*
- This password prompt will be prompted rarely. Since the key that is passed to
- the auth_func corresponds to the parent user.
- */
- prompt = g_strdup_printf (_("Enter password for %s to enable proxy for user %s"), e_source_peek_name (priv->source), parent_user);
- g_free (parent_user);
- } else
- key = g_strdup (e_cal_get_uri (ecal));
- }
- g_free (auth_type);
-
- if (!key) {
- priv->load_state = E_CAL_LOAD_NOT_LOADED;
- #ifndef E_CAL_DISABLE_DEPRECATED
- *status = E_CALENDAR_STATUS_URI_NOT_LOADED;
- #endif
- E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED, error);
- }
-
- password = priv->auth_func (ecal, prompt, key, priv->auth_user_data);
-
- if (!password) {
- priv->load_state = E_CAL_LOAD_NOT_LOADED;
- #ifndef E_CAL_DISABLE_DEPRECATED
- *status = E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED;
- #endif
- E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED, error);
- }
-
- g_free (prompt);
- g_free (key);
+ needs_auth = TRUE;
}
- priv->load_state = E_CAL_LOAD_LOADING;
-
#ifndef E_CAL_DISABLE_DEPRECATED
*status = E_CALENDAR_STATUS_OK;
#endif
if (!async) {
- gchar *gdbus_username = NULL, *gdbus_password = NULL;
-
- if (!e_gdbus_cal_call_open_sync (priv->gdbus_cal, only_if_exists, e_util_ensure_gdbus_string (username, &gdbus_username), e_util_ensure_gdbus_string (password, &gdbus_password), NULL, error)) {
+ if (!e_gdbus_cal_call_open_sync (priv->gdbus_cal, only_if_exists, NULL, error)) {
#ifndef E_CAL_DISABLE_DEPRECATED
*status = E_CALENDAR_STATUS_DBUS_EXCEPTION;
#endif
+ } else if (needs_auth && !call_authenticate_user (ecal, FALSE, error)) {
+ #ifndef E_CAL_DISABLE_DEPRECATED
+ *status = error && *error ? (*error)->code : E_CALENDAR_STATUS_AUTHENTICATION_FAILED;
+ #endif
}
if (!*error)
priv->load_state = E_CAL_LOAD_LOADED;
-
- g_free (gdbus_username);
- g_free (gdbus_password);
} else {
- gchar *gdbus_username = NULL, *gdbus_password = NULL;
-
- e_gdbus_cal_call_open (priv->gdbus_cal, only_if_exists, e_util_ensure_gdbus_string (username, &gdbus_username), e_util_ensure_gdbus_string (password, &gdbus_password), NULL, (GAsyncReadyCallback) async_open_ready_cb, ecal);
-
- g_free (gdbus_username);
- g_free (gdbus_password);
+ e_gdbus_cal_call_open (priv->gdbus_cal, only_if_exists, NULL, (GAsyncReadyCallback) async_open_ready_cb, ecal);
}
- g_free (password);
- g_free (username);
-
- if (!*error) {
- if (!async) {
- GError *err = NULL;
-
- e_gdbus_cal_call_is_read_only_sync (ecal->priv->gdbus_cal, NULL, &err);
-
- if (err)
- g_error_free (err);
- }
- } else {
+ if (*error) {
unwrap_gerror (error);
priv->load_state = E_CAL_LOAD_NOT_LOADED;
}
@@ -1397,6 +1594,8 @@ open_calendar (ECal *ecal, gboolean only_if_exists, GError **error,
* New signal deprecates the old "cal_opened" signal.
*
* Returns: TRUE on success, FALSE on failure to issue the open request.
+ *
+ * Deprecated: 3.2: Use e_client_open_sync() on an #ECalClient object instead.
**/
gboolean
e_cal_open (ECal *ecal, gboolean only_if_exists, GError **error)
@@ -1478,6 +1677,9 @@ async_report_idle (ECal *ecal, GError *error)
* Because this operation runs in another thread, any authentication
* callback set on the calendar will be called from this other thread.
* See #e_cal_set_auth_func() for details.
+ *
+ * Deprecated: 3.2: Use e_client_open()/e_client_open_finish()
+ * on an #ECalClient object instead.
**/
void
e_cal_open_async (ECal *ecal, gboolean only_if_exists)
@@ -1526,6 +1728,8 @@ e_cal_open_async (ECal *ecal, gboolean only_if_exists)
* Returns: TRUE if calendar supports refresh and it was invoked, FALSE otherwise.
*
* Since: 2.30
+ *
+ * Deprecated: 3.2: Use e_cal_client_refresh_sync() instead.
**/
gboolean
e_cal_refresh (ECal *ecal, GError **error)
@@ -1551,6 +1755,8 @@ e_cal_refresh (ECal *ecal, GError **error)
* Removes a calendar.
*
* Returns: TRUE if the calendar was removed, FALSE if there was an error.
+ *
+ * Deprecated: 3.2: Use e_client_remove_sync() on an #ECalClient object instead.
*/
gboolean
e_cal_remove (ECal *ecal, GError **error)
@@ -1591,6 +1797,8 @@ build_uri_list (GNOME_Evolution_Calendar_StringSeq *seq)
* Retrieves a list of all calendar clients for the given mode.
*
* Returns: list of uris.
+ *
+ * Deprecated: 3.2: This function has been dropped completely.
*/
GList *
e_cal_uri_list (ECal *ecal, CalMode mode)
@@ -1642,6 +1850,8 @@ e_cal_uri_list (ECal *ecal, CalMode mode)
*
* Returns: an #ECalSourceType value corresponding to the type
* of the calendar client.
+ *
+ * Deprecated: 3.2: Use e_cal_client_get_source_type() instead.
*/
ECalSourceType
e_cal_get_source_type (ECal *ecal)
@@ -1665,6 +1875,8 @@ e_cal_get_source_type (ECal *ecal)
* Returns: A #ECalLoadState value indicating whether the client has
* not been loaded with #e_cal_open yet, whether it is being
* loaded, or whether it is already loaded.
+ *
+ * Deprecated: 3.2: Use e_client_is_opened() on an #ECalClient instead.
**/
ECalLoadState
e_cal_get_load_state (ECal *ecal)
@@ -1686,6 +1898,8 @@ e_cal_get_load_state (ECal *ecal)
*
* Returns: The source of the calendar that is already loaded or is being
* loaded, or NULL if the ecal has not started a load request yet.
+ *
+ * Deprecated: 3.2: Use e_client_get_source() on an #ECalClient object instead.
**/
ESource *
e_cal_get_source (ECal *ecal)
@@ -1707,6 +1921,8 @@ e_cal_get_source (ECal *ecal)
*
* Returns: The URI of the calendar that is already loaded or is being
* loaded, or NULL if the client has not started a load request yet.
+ *
+ * Deprecated: 3.2: Use e_client_get_uri() on an #ECalClient object instead.
**/
const gchar *
e_cal_get_uri (ECal *ecal)
@@ -1732,6 +1948,8 @@ e_cal_get_uri (ECal *ecal)
*
* Returns: The URL where the attachments are serialized in the
* local filesystem.
+ *
+ * Deprecated: 3.2: Use e_cal_client_get_local_attachment_store() instead.
**/
const gchar *
e_cal_get_local_attachment_store (ECal *ecal)
@@ -1756,6 +1974,8 @@ e_cal_get_local_attachment_store (ECal *ecal)
* is specified, on exit, in the @read_only argument.
*
* Returns: TRUE if the call was successful, FALSE if there was an error.
+ *
+ * Deprecated: 3.2: Use e_cal_client_is_readonly() on an #ECalClient object instead.
*/
gboolean
e_cal_is_read_only (ECal *ecal, gboolean *read_only, GError **error)
@@ -1781,6 +2001,9 @@ e_cal_is_read_only (ECal *ecal, gboolean *read_only, GError **error)
*
* Returns: TRUE if the operation was successful, FALSE if there
* was an error.
+ *
+ * Deprecated: 3.2: Use e_client_get_backend_property_sync()
+ * with #CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS instead.
**/
gboolean
e_cal_get_cal_address (ECal *ecal, gchar **cal_address, GError **error)
@@ -1801,7 +2024,7 @@ e_cal_get_cal_address (ECal *ecal, gchar **cal_address, GError **error)
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
}
- if (!e_gdbus_cal_call_get_cal_address_sync (priv->gdbus_cal, &priv->cal_address, NULL, error)) {
+ if (!e_gdbus_cal_call_get_backend_property_sync (priv->gdbus_cal, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS, &priv->cal_address, NULL, error)) {
UNLOCK_CACHE ();
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
}
@@ -1823,6 +2046,9 @@ e_cal_get_cal_address (ECal *ecal, gchar **cal_address, GError **error)
*
* Returns: TRUE if the operation was successful, FALSE if there was
* an error while contacting the backend.
+ *
+ * Deprecated: 3.2: Use e_client_get_backend_property_sync()
+ * with #CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS instead.
*/
gboolean
e_cal_get_alarm_email_address (ECal *ecal, gchar **alarm_address, GError **error)
@@ -1839,7 +2065,7 @@ e_cal_get_alarm_email_address (ECal *ecal, gchar **alarm_address, GError **error
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
}
- if (!e_gdbus_cal_call_get_alarm_email_address_sync (priv->gdbus_cal, alarm_address, NULL, error)) {
+ if (!e_gdbus_cal_call_get_backend_property_sync (priv->gdbus_cal, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS, alarm_address, NULL, error)) {
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
}
@@ -1856,6 +2082,8 @@ e_cal_get_alarm_email_address (ECal *ecal, gchar **alarm_address, GError **error
*
* Returns: TRUE if the call was successful, FALSE if there was an
* error contacting the backend.
+ *
+ * Deprecated: 3.2: This function has been dropped completely.
*/
gboolean
e_cal_get_ldap_attribute (ECal *ecal, gchar **ldap_attribute, GError **error)
@@ -1868,19 +2096,11 @@ e_cal_get_ldap_attribute (ECal *ecal, gchar **ldap_attribute, GError **error)
e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
*ldap_attribute = NULL;
- if (priv->load_state != E_CAL_LOAD_LOADED) {
- E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
- }
-
- if (!e_gdbus_cal_call_get_ldap_attribute_sync (priv->gdbus_cal, ldap_attribute, NULL, error)) {
- E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
- }
-
- return TRUE;
+ E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_NOT_SUPPORTED, error);
}
static gboolean
-load_static_capabilities (ECal *ecal, GError **error)
+load_capabilities (ECal *ecal, GError **error)
{
ECalPrivate *priv;
@@ -1898,7 +2118,7 @@ load_static_capabilities (ECal *ecal, GError **error)
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
}
- if (!e_gdbus_cal_call_get_scheduling_information_sync (priv->gdbus_cal, &priv->capabilities, NULL, error)) {
+ if (!e_gdbus_cal_call_get_backend_property_sync (priv->gdbus_cal, CLIENT_BACKEND_PROPERTY_CAPABILITIES, &priv->capabilities, NULL, error)) {
UNLOCK_CACHE ();
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
}
@@ -1916,7 +2136,7 @@ check_capability (ECal *ecal, const gchar *cap)
priv = ecal->priv;
/* FIXME Check result */
- load_static_capabilities (ecal, NULL);
+ load_capabilities (ecal, NULL);
if (priv->capabilities && strstr (priv->capabilities, cap))
return TRUE;
@@ -1930,6 +2150,8 @@ check_capability (ECal *ecal, const gchar *cap)
* Checks if a calendar supports only one alarm per component.
*
* Returns: TRUE if the calendar allows only one alarm, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_check_one_alarm_only() instead.
*/
gboolean
e_cal_get_one_alarm_only (ECal *ecal)
@@ -1948,6 +2170,8 @@ e_cal_get_one_alarm_only (ECal *ecal)
*
* Returns: TRUE if the calendar forces organizers to attend meetings,
* FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_check_organizer_must_attend() instead.
*/
gboolean
e_cal_get_organizer_must_attend (ECal *ecal)
@@ -1966,6 +2190,8 @@ e_cal_get_organizer_must_attend (ECal *ecal)
*
* Returns: TRUE if the calendar has a master object for recurrences,
* FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_check_recurrences_no_master() instead.
*/
gboolean
e_cal_get_recurrences_no_master (ECal *ecal)
@@ -1984,6 +2210,8 @@ e_cal_get_recurrences_no_master (ECal *ecal)
* Queries the calendar for static capabilities.
*
* Returns: TRUE if the capability is supported, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_client_check_capability() on an #ECalClient object instead.
*/
gboolean
e_cal_get_static_capability (ECal *ecal, const gchar *cap)
@@ -2001,6 +2229,8 @@ e_cal_get_static_capability (ECal *ecal, const gchar *cap)
* Checks whether the calendar saves schedules.
*
* Returns: TRUE if it saves schedules, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_check_save_schedules() instead.
*/
gboolean
e_cal_get_save_schedules (ECal *ecal)
@@ -2020,6 +2250,8 @@ e_cal_get_save_schedules (ECal *ecal)
*
* Returns: TRUE if the calendar requires organizers to accept, FALSE
* otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_check_organizer_must_accept() instead.
*/
gboolean
e_cal_get_organizer_must_accept (ECal *ecal)
@@ -2039,6 +2271,8 @@ e_cal_get_organizer_must_accept (ECal *ecal)
* Returns: TRUE if the calendar supports refreshing, FALSE otherwise.
*
* Since: 2.30
+ *
+ * Deprecated: 3.2: Use e_client_check_refresh_supported() instead.
*/
gboolean
e_cal_get_refresh_supported (ECal *ecal)
@@ -2057,12 +2291,13 @@ e_cal_get_refresh_supported (ECal *ecal)
* Switches online/offline mode on the calendar.
*
* Returns: TRUE if the switch was successful, FALSE if there was an error.
+ *
+ * Deprecated: 3.2: This function has been dropped completely.
*/
gboolean
e_cal_set_mode (ECal *ecal, CalMode mode)
{
ECalPrivate *priv;
- GError *error = NULL;
g_return_val_if_fail (ecal != NULL, FALSE);
g_return_val_if_fail (E_IS_CAL (ecal), FALSE);
@@ -2072,15 +2307,9 @@ e_cal_set_mode (ECal *ecal, CalMode mode)
g_return_val_if_fail (priv->gdbus_cal, FALSE);
g_return_val_if_fail (priv->load_state == E_CAL_LOAD_LOADED, FALSE);
- if (!e_gdbus_cal_call_set_mode_sync (priv->gdbus_cal, mode, NULL, &error)) {
- unwrap_gerror (&error);
- g_printerr ("%s: %s\n", G_STRFUNC, error ? error->message : "Unknown error");
- if (error)
- g_error_free (error);
- return FALSE;
- }
+ g_debug ("%s: This function is not supported since 3.2", G_STRFUNC);
- return TRUE;
+ return FALSE;
}
/* This is used in the callback which fetches all the timezones needed for an
@@ -2104,6 +2333,8 @@ struct _ECalGetTimezonesData {
* values for properties needed.
*
* Returns: TRUE if the call was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_get_default_object_sync() instead.
*/
gboolean
e_cal_get_default_object (ECal *ecal, icalcomponent **icalcomp, GError **error)
@@ -2122,7 +2353,7 @@ e_cal_get_default_object (ECal *ecal, icalcomponent **icalcomp, GError **error)
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
}
- if (!e_gdbus_cal_call_get_default_object_sync (priv->gdbus_cal, &object, NULL, error)) {
+ if (!e_gdbus_cal_call_get_backend_property_sync (priv->gdbus_cal, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT, &object, NULL, error)) {
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
}
@@ -2154,6 +2385,8 @@ e_cal_get_default_object (ECal *ecal, icalcomponent **icalcomp, GError **error)
* identifier and gets the attachments for the component.
*
* Returns: TRUE if the call was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_get_attachment_uris_sync() instead.
**/
gboolean
e_cal_get_attachments_for_comp (ECal *ecal, const gchar *uid, const gchar *rid, GSList **list, GError **error)
@@ -2161,7 +2394,7 @@ e_cal_get_attachments_for_comp (ECal *ecal, const gchar *uid, const gchar *rid,
ECalPrivate *priv;
ECalendarStatus status;
gchar **list_array;
- gchar *gdbus_uid = NULL, *gdbus_rid = NULL;
+ gchar **strv;
e_return_error_if_fail (uid != NULL, E_CALENDAR_STATUS_INVALID_ARG);
e_return_error_if_fail (list != NULL, E_CALENDAR_STATUS_INVALID_ARG);
@@ -2174,15 +2407,14 @@ e_cal_get_attachments_for_comp (ECal *ecal, const gchar *uid, const gchar *rid,
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
}
- if (!e_gdbus_cal_call_get_attachment_list_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (uid, &gdbus_uid), e_util_ensure_gdbus_string (rid, &gdbus_rid), &list_array, NULL, error)) {
- g_free (gdbus_uid);
- g_free (gdbus_rid);
+ strv = e_gdbus_cal_encode_get_attachment_uris (uid, rid);
+ if (!e_gdbus_cal_call_get_attachment_uris_sync (priv->gdbus_cal, (const gchar * const *) strv, &list_array, NULL, error)) {
+ g_strfreev (strv);
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
}
- g_free (gdbus_uid);
- g_free (gdbus_rid);
+ g_strfreev (strv);
if (list_array) {
gchar **string;
@@ -2209,13 +2441,15 @@ e_cal_get_attachments_for_comp (ECal *ecal, const gchar *uid, const gchar *rid,
* identifier.
*
* Returns: TRUE if the call was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_get_object_sync() instead.
**/
gboolean
e_cal_get_object (ECal *ecal, const gchar *uid, const gchar *rid, icalcomponent **icalcomp, GError **error)
{
ECalPrivate *priv;
ECalendarStatus status;
- gchar *object = NULL, *gdbus_uid = NULL, *gdbus_rid = NULL;
+ gchar *object = NULL, **strv;
icalcomponent *tmp_icalcomp;
icalcomponent_kind kind;
@@ -2230,15 +2464,14 @@ e_cal_get_object (ECal *ecal, const gchar *uid, const gchar *rid, icalcomponent
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
}
- if (!e_gdbus_cal_call_get_object_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (uid, &gdbus_uid), e_util_ensure_gdbus_string (rid, &gdbus_rid), &object, NULL, error)) {
- g_free (gdbus_uid);
- g_free (gdbus_rid);
+ strv = e_gdbus_cal_encode_get_object (uid, rid);
+ if (!e_gdbus_cal_call_get_object_sync (priv->gdbus_cal, (const gchar * const *) strv, &object, NULL, error)) {
+ g_strfreev (strv);
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
}
- g_free (gdbus_uid);
- g_free (gdbus_rid);
+ g_strfreev (strv);
status = E_CALENDAR_STATUS_OK;
tmp_icalcomp = icalparser_parse_string (object);
@@ -2294,13 +2527,15 @@ e_cal_get_object (ECal *ecal, const gchar *uid, const gchar *rid, icalcomponent
* For non-recurring events, it will just return the object with that ID.
*
* Returns: TRUE if the call was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_get_objects_for_uid_sync() instead.
**/
gboolean
e_cal_get_objects_for_uid (ECal *ecal, const gchar *uid, GList **objects, GError **error)
{
ECalPrivate *priv;
ECalendarStatus status;
- gchar *object = NULL, *gdbus_uid = NULL;
+ gchar *object = NULL, **strv;
e_return_error_if_fail (uid != NULL, E_CALENDAR_STATUS_INVALID_ARG);
e_return_error_if_fail (objects != NULL, E_CALENDAR_STATUS_INVALID_ARG);
@@ -2313,13 +2548,14 @@ e_cal_get_objects_for_uid (ECal *ecal, const gchar *uid, GList **objects, GError
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
}
- if (!e_gdbus_cal_call_get_object_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (uid, &gdbus_uid), "", &object, NULL, error)) {
- g_free (gdbus_uid);
+ strv = e_gdbus_cal_encode_get_object (uid, "");
+ if (!e_gdbus_cal_call_get_object_sync (priv->gdbus_cal, (const gchar * const *) strv, &object, NULL, error)) {
+ g_strfreev (strv);
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
}
- g_free (gdbus_uid);
+ g_strfreev (strv);
status = E_CALENDAR_STATUS_OK;
{
@@ -2384,6 +2620,8 @@ e_cal_get_objects_for_uid (ECal *ecal, const gchar *uid, GList **objects, GError
*
* Returns: The timezone identified by the @tzid argument, or %NULL if
* it could not be found.
+ *
+ * Deprecated: 3.2: Use e_cal_client_resolve_tzid_cb() instead.
*/
icaltimezone*
e_cal_resolve_tzid_cb (const gchar *tzid, gpointer data)
@@ -2414,13 +2652,13 @@ e_cal_resolve_tzid_cb (const gchar *tzid, gpointer data)
* compute the changes done.
*
* Returns: TRUE if the call was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: This function has been dropped completely.
*/
gboolean
e_cal_get_changes (ECal *ecal, const gchar *change_id, GList **changes, GError **error)
{
ECalPrivate *priv;
- gchar **additions = NULL, **modifications = NULL, **removals = NULL;
- gchar *gdbus_change_id = NULL;
e_return_error_if_fail (changes != NULL, E_CALENDAR_STATUS_INVALID_ARG);
e_return_error_if_fail (change_id != NULL, E_CALENDAR_STATUS_INVALID_ARG);
@@ -2429,71 +2667,7 @@ e_cal_get_changes (ECal *ecal, const gchar *change_id, GList **changes, GError *
e_return_error_if_fail (priv->gdbus_cal, E_CALENDAR_STATUS_REPOSITORY_OFFLINE);
*changes = NULL;
- if (priv->load_state != E_CAL_LOAD_LOADED) {
- E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
- }
-
- if (!e_gdbus_cal_call_get_changes_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (change_id, &gdbus_change_id), &additions, &modifications, &removals, NULL, error)) {
- g_free (gdbus_change_id);
-
- E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
- }
-
- g_free (gdbus_change_id);
-
- /* TODO: Be more elegant and split this into a function */
- /* Mostly copied from the old e-cal-listener.c */
- if ((additions)&&(modifications)&&(removals)) {
- gint i;
- gchar **list = NULL, **l;
- ECalChangeType change_type = E_CAL_CHANGE_ADDED;
- icalcomponent *icalcomp;
- ECalChange *change;
-
- for (i = 0; i < 3; i++) {
- switch (i) {
- case 0:
- change_type = E_CAL_CHANGE_ADDED;
- list = additions;
- break;
- case 1:
- change_type = E_CAL_CHANGE_MODIFIED;
- list = modifications;
- break;
- case 2:
- change_type = E_CAL_CHANGE_DELETED;
- list = removals;
- }
-
- for (l = list; *l; l++) {
- icalcomp = icalparser_parse_string (*l);
- if (!icalcomp)
- continue;
- change = g_new (ECalChange, 1);
- change->comp = e_cal_component_new ();
- if (!e_cal_component_set_icalcomponent (change->comp, icalcomp)) {
- icalcomponent_free (icalcomp);
- g_object_unref (G_OBJECT (change->comp));
- g_free (change);
- continue;
- }
- change->type = change_type;
- *changes = g_list_append (*changes, change);
- }
- }
-
- g_strfreev (additions);
- g_strfreev (modifications);
- g_strfreev (removals);
- } else {
- g_strfreev (additions);
- g_strfreev (modifications);
- g_strfreev (removals);
-
- E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OTHER_ERROR, error);
- }
-
- E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
+ E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_NOT_SUPPORTED, error);
}
/**
@@ -2501,6 +2675,8 @@ e_cal_get_changes (ECal *ecal, const gchar *change_id, GList **changes, GError *
* @list: List of changes to be freed.
*
* Free a list of changes as returned by #e_cal_get_changes.
+ *
+ * Deprecated: 3.2: Use () instead.
*/
void
e_cal_free_change_list (GList *list)
@@ -2534,6 +2710,8 @@ e_cal_free_change_list (GList *list)
* should be freed by using the #e_cal_free_object_list function.
*
* Returns: TRUE if the operation was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_get_object_list_sync() instead.
**/
gboolean
e_cal_get_object_list (ECal *ecal, const gchar *query, GList **objects, GError **error)
@@ -2589,6 +2767,8 @@ e_cal_get_object_list (ECal *ecal, const gchar *query, GList **objects, GError *
* argument, which is a list of #ECalComponent.
*
* Returns: TRUE if the operation was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_get_object_list_as_comps_sync() instead.
*/
gboolean
e_cal_get_object_list_as_comp (ECal *ecal, const gchar *query, GList **objects, GError **error)
@@ -2623,6 +2803,8 @@ e_cal_get_object_list_as_comp (ECal *ecal, const gchar *query, GList **objects,
* @objects: List of objects to be freed.
*
* Frees a list of objects as returned by #e_cal_get_object_list.
+ *
+ * Deprecated: 3.2: Use e_cal_client_free_icalcomp_slist() instead.
*/
void
e_cal_free_object_list (GList *objects)
@@ -2635,40 +2817,6 @@ e_cal_free_object_list (GList *objects)
g_list_free (objects);
}
-static GList *
-build_free_busy_list (const gchar **seq)
-{
- GList *list = NULL;
- gint i;
-
- /* Create the list in reverse order */
- for (i = 0; seq[i]; i++) {
- ECalComponent *comp;
- icalcomponent *icalcomp;
- icalcomponent_kind kind;
-
- icalcomp = icalcomponent_new_from_string ((gchar *) seq[i]);
- if (!icalcomp)
- continue;
-
- kind = icalcomponent_isa (icalcomp);
- if (kind == ICAL_VFREEBUSY_COMPONENT) {
- comp = e_cal_component_new ();
- if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
- icalcomponent_free (icalcomp);
- g_object_unref (G_OBJECT (comp));
- continue;
- }
-
- list = g_list_append (list, comp);
- } else {
- icalcomponent_free (icalcomp);
- }
- }
-
- return list;
-}
-
/**
* e_cal_get_free_busy
* @ecal: A calendar client.
@@ -2681,16 +2829,17 @@ build_free_busy_list (const gchar **seq)
* Gets free/busy information from the calendar server.
*
* Returns: TRUE if the operation was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_get_free_busy_sync() instead.
*/
gboolean
e_cal_get_free_busy (ECal *ecal, GList *users, time_t start, time_t end,
GList **freebusy, GError **error)
{
ECalPrivate *priv;
- gchar **users_list;
- gchar **freebusy_array = NULL;
+ gchar **strv;
+ GSList *susers;
GList *l;
- gint i;
e_return_error_if_fail (users != NULL, E_CALENDAR_STATUS_INVALID_ARG);
e_return_error_if_fail (freebusy != NULL, E_CALENDAR_STATUS_INVALID_ARG);
@@ -2703,22 +2852,33 @@ e_cal_get_free_busy (ECal *ecal, GList *users, time_t start, time_t end,
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
}
- users_list = g_new0 (gchar *, g_list_length (users) + 1);
- for (l = users, i = 0; l; l = l->next, i++)
- users_list[i] = e_util_utf8_make_valid (l->data);
+ susers = NULL;
+ for (l = users; l; l = l->next) {
+ susers = g_slist_prepend (susers, l->data);
+ }
+ susers = g_slist_reverse (susers);
+ strv = e_gdbus_cal_encode_get_free_busy (start, end, susers);
+ g_slist_free (susers);
+
+ g_mutex_lock (priv->free_busy_data_lock);
+ priv->free_busy_data = freebusy;
+ g_mutex_unlock (priv->free_busy_data_lock);
+
+ if (!e_gdbus_cal_call_get_free_busy_sync (priv->gdbus_cal, (const gchar * const *) strv, NULL, error)) {
+ g_strfreev (strv);
+ g_mutex_lock (priv->free_busy_data_lock);
+ priv->free_busy_data = NULL;
+ g_mutex_unlock (priv->free_busy_data_lock);
- if (!e_gdbus_cal_call_get_free_busy_sync (priv->gdbus_cal, (const gchar * const *) users_list, start, end, &freebusy_array, NULL, error)) {
- g_strfreev (users_list);
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
}
- g_strfreev (users_list);
+ g_strfreev (strv);
- if (freebusy_array) {
- *freebusy = build_free_busy_list ((const gchar **) freebusy_array);
- g_strfreev (freebusy_array);
- E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
- } else
- E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OTHER_ERROR, error);
+ g_mutex_lock (priv->free_busy_data_lock);
+ priv->free_busy_data = NULL;
+ g_mutex_unlock (priv->free_busy_data_lock);
+
+ E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
}
struct comp_instance {
@@ -3112,6 +3272,8 @@ try_again:
* The callback function should do a g_object_ref() of the calendar component
* it gets passed if it intends to keep it around, since it will be unref'ed
* as soon as the callback returns.
+ *
+ * Deprecated: 3.2: Use e_cal_client_generate_instances() instead.
**/
void
e_cal_generate_instances (ECal *ecal, time_t start, time_t end,
@@ -3148,6 +3310,8 @@ e_cal_generate_instances (ECal *ecal, time_t start, time_t end,
* The callback function should do a g_object_ref() of the calendar component
* it gets passed if it intends to keep it around, since it will be unref'ed
* as soon as the callback returns.
+ *
+ * Deprecated: 3.2: Use e_cal_client_generate_instances_for_object() instead.
**/
void
e_cal_generate_instances_for_object (ECal *ecal, icalcomponent *icalcomp,
@@ -3275,6 +3439,8 @@ build_component_alarms_list (ECal *ecal, GList *object_list, time_t start, time_
* using the #e_cal_free_alarms() function, or by freeing each element
* separately with #e_cal_component_alarms_free() and then freeing the list with
* #g_slist_free().
+ *
+ * Deprecated: 3.2: This function has been dropped completely.
**/
GSList *
e_cal_get_alarms_in_range (ECal *ecal, time_t start, time_t end)
@@ -3330,6 +3496,8 @@ e_cal_get_alarms_in_range (ECal *ecal, time_t start, time_t end)
*
* Frees a list of #ECalComponentAlarms structures as returned by
* e_cal_get_alarms_in_range().
+ *
+ * Deprecated: 3.2: This function has been dropped completely.
**/
void
e_cal_free_alarms (GSList *comp_alarms)
@@ -3363,6 +3531,8 @@ e_cal_free_alarms (GSList *comp_alarms)
* specified range of time.
*
* Returns: TRUE on success, FALSE if the object was not found.
+ *
+ * Deprecated: 3.2: This function has been dropped completely.
**/
gboolean
e_cal_get_alarms_for_object (ECal *ecal, const ECalComponentId *id,
@@ -3418,13 +3588,13 @@ e_cal_get_alarms_for_object (ECal *ecal, const ECalComponentId *id,
* the file backend does, ignore the operation.
*
* Returns: TRUE if the operation was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_discard_alarm_sync() instead.
*/
gboolean
e_cal_discard_alarm (ECal *ecal, ECalComponent *comp, const gchar *auid, GError **error)
{
ECalPrivate *priv;
- const gchar *uid = NULL;
- gchar *gdbus_uid = NULL, *gdbus_auid = NULL;
e_return_error_if_fail (ecal != NULL, E_CALENDAR_STATUS_INVALID_ARG);
e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
@@ -3438,19 +3608,7 @@ e_cal_discard_alarm (ECal *ecal, ECalComponent *comp, const gchar *auid, GError
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
}
- e_cal_component_get_uid (comp, &uid);
-
- if (!e_gdbus_cal_call_discard_alarm_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (uid, &gdbus_uid), e_util_ensure_gdbus_string (auid, &gdbus_auid), NULL, error)) {
- g_free (gdbus_uid);
- g_free (gdbus_auid);
-
- E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
- }
-
- g_free (gdbus_uid);
- g_free (gdbus_auid);
-
- E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
+ E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_NOT_SUPPORTED, error);
}
typedef struct _ForeachTZIDCallbackData ForeachTZIDCallbackData;
@@ -3612,6 +3770,8 @@ e_cal_get_component_as_string_internal (ECal *ecal,
*
* Returns: the component as a complete iCalendar string, or NULL on
* failure. The string should be freed after use.
+ *
+ * Deprecated: 3.2: Use e_cal_client_get_component_as_string() instead.
**/
gchar *
e_cal_get_component_as_string (ECal *ecal, icalcomponent *icalcomp)
@@ -3631,6 +3791,8 @@ e_cal_get_component_as_string (ECal *ecal, icalcomponent *icalcomp)
* in those cases that UID would be returned in the @uid argument.
*
* Returns: TRUE if the operation was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_create_object_sync() instead.
*/
gboolean
e_cal_create_object (ECal *ecal, icalcomponent *icalcomp, gchar **uid, GError **error)
@@ -3689,12 +3851,14 @@ e_cal_create_object (ECal *ecal, icalcomponent *icalcomp, gchar **uid, GError **
* CALOBJ_MOD_THISANDFUTURE).
*
* Returns: TRUE if the operation was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_modify_object_sync() instead.
*/
gboolean
e_cal_modify_object (ECal *ecal, icalcomponent *icalcomp, CalObjModType mod, GError **error)
{
ECalPrivate *priv;
- gchar *obj, *gdbus_obj = NULL;
+ gchar *obj, **strv;
e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
e_return_error_if_fail (icalcomp, E_CALENDAR_STATUS_INVALID_ARG);
@@ -3708,15 +3872,16 @@ e_cal_modify_object (ECal *ecal, icalcomponent *icalcomp, CalObjModType mod, GEr
}
obj = icalcomponent_as_ical_string_r (icalcomp);
- if (!e_gdbus_cal_call_modify_object_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (obj, &gdbus_obj), mod, NULL, error)) {
+ strv = e_gdbus_cal_encode_modify_object (obj, mod);
+ if (!e_gdbus_cal_call_modify_object_sync (priv->gdbus_cal, (const gchar * const *) strv, NULL, error)) {
g_free (obj);
- g_free (gdbus_obj);
+ g_strfreev (strv);
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
}
g_free (obj);
- g_free (gdbus_obj);
+ g_strfreev (strv);
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
}
@@ -3739,13 +3904,15 @@ e_cal_modify_object (ECal *ecal, icalcomponent *icalcomp, CalObjModType mod, GEr
* are removed.
*
* Returns: TRUE if the operation was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_remove_object_sync() instead.
*/
gboolean
e_cal_remove_object_with_mod (ECal *ecal, const gchar *uid,
const gchar *rid, CalObjModType mod, GError **error)
{
ECalPrivate *priv;
- gchar *gdbus_uid = NULL, *gdbus_rid = NULL;
+ gchar **strv;
e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
e_return_error_if_fail (uid, E_CALENDAR_STATUS_INVALID_ARG);
@@ -3757,15 +3924,14 @@ e_cal_remove_object_with_mod (ECal *ecal, const gchar *uid,
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
}
- if (!e_gdbus_cal_call_remove_object_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (uid, &gdbus_uid), e_util_ensure_gdbus_string (rid, &gdbus_rid), mod, NULL, error)) {
- g_free (gdbus_uid);
- g_free (gdbus_rid);
+ strv = e_gdbus_cal_encode_remove_object (uid, rid, mod);
+ if (!e_gdbus_cal_call_remove_object_sync (priv->gdbus_cal, (const gchar * const *) strv, NULL, error)) {
+ g_strfreev (strv);
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
}
- g_free (gdbus_uid);
- g_free (gdbus_rid);
+ g_strfreev (strv);
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
}
@@ -3781,6 +3947,8 @@ e_cal_remove_object_with_mod (ECal *ecal, const gchar *uid,
* signal.
*
* Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_remove_object_sync() instead, with rid set to NULL and mod set to CALOBJ_MOD_THIS.
**/
gboolean
e_cal_remove_object (ECal *ecal, const gchar *uid, GError **error)
@@ -3802,6 +3970,8 @@ e_cal_remove_object (ECal *ecal, const gchar *uid, GError **error)
* messages for scheduled meetings.
*
* Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_receive_objects_sync() instead.
*/
gboolean
e_cal_receive_objects (ECal *ecal, icalcomponent *icalcomp, GError **error)
@@ -3846,14 +4016,16 @@ e_cal_receive_objects (ECal *ecal, icalcomponent *icalcomp, GError **error)
* of users.
*
* Returns: TRUE if the operation was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_send_objects_sync() instead.
*/
gboolean
e_cal_send_objects (ECal *ecal, icalcomponent *icalcomp, GList **users, icalcomponent **modified_icalcomp, GError **error)
{
ECalPrivate *priv;
ECalendarStatus status;
- gchar **users_array = NULL;
- gchar *object = NULL, *obj, *gdbus_obj = NULL;
+ gchar **out_array = NULL;
+ gchar *obj, *gdbus_obj = NULL;
e_return_error_if_fail (users != NULL, E_CALENDAR_STATUS_INVALID_ARG);
e_return_error_if_fail (modified_icalcomp != NULL, E_CALENDAR_STATUS_INVALID_ARG);
@@ -3870,7 +4042,7 @@ e_cal_send_objects (ECal *ecal, icalcomponent *icalcomp, GList **users, icalcomp
}
obj = icalcomponent_as_ical_string_r (icalcomp);
- if (!e_gdbus_cal_call_send_objects_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (obj, &gdbus_obj), &users_array, &object, NULL, error)) {
+ if (!e_gdbus_cal_call_send_objects_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (obj, &gdbus_obj), &out_array, NULL, error)) {
g_free (obj);
g_free (gdbus_obj);
@@ -3881,15 +4053,24 @@ e_cal_send_objects (ECal *ecal, icalcomponent *icalcomp, GList **users, icalcomp
g_free (gdbus_obj);
status = E_CALENDAR_STATUS_OK;
- if (users_array) {
- gchar **user;
+ if (out_array) {
+ GSList *susers = NULL, *iter;
+ gchar *object = NULL;
+
+ e_return_error_if_fail (e_gdbus_cal_decode_send_objects ((const gchar * const *) out_array, &object, &susers), E_CALENDAR_STATUS_OTHER_ERROR);
+
*modified_icalcomp = icalparser_parse_string (object);
if (!(*modified_icalcomp))
status = E_CALENDAR_STATUS_INVALID_OBJECT;
- for (user = users_array; *user; user++)
- *users = g_list_append (*users, g_strdup (*user));
- g_strfreev (users_array);
+ *users = NULL;
+ for (iter = susers; iter; iter = iter->next) {
+ *users = g_list_append (*users, iter->data);
+ }
+ /* do not call g_free() on item's data of susers, it's moved to *users */
+ g_slist_free (susers);
+ g_strfreev (out_array);
+ g_free (object);
} else
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OTHER_ERROR, error);
@@ -3906,6 +4087,8 @@ e_cal_send_objects (ECal *ecal, icalcomponent *icalcomp, GList **users, icalcomp
* Retrieves a timezone object from the calendar backend.
*
* Returns: TRUE if the operation was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_get_timezone_sync() instead.
*/
gboolean
e_cal_get_timezone (ECal *ecal, const gchar *tzid, icaltimezone **zone, GError **error)
@@ -4027,6 +4210,8 @@ e_cal_get_timezone (ECal *ecal, const gchar *tzid, icaltimezone **zone, GError *
* Add a VTIMEZONE object to the given calendar.
*
* Returns: TRUE if successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_add_timezone_sync() instead.
*/
gboolean
e_cal_add_timezone (ECal *ecal, icaltimezone *izone, GError **error)
@@ -4083,6 +4268,8 @@ e_cal_add_timezone (ECal *ecal, icaltimezone *izone, GError **error)
*
* Returns: A query object that will emit notification signals as calendar
* components are added and removed from the query in the server.
+ *
+ * Deprecated: 3.2: Use e_cal_client_get_view_sync() instead.
**/
gboolean
e_cal_get_query (ECal *ecal, const gchar *sexp, ECalView **query, GError **error)
@@ -4103,7 +4290,7 @@ e_cal_get_query (ECal *ecal, const gchar *sexp, ECalView **query, GError **error
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error);
}
- if (!e_gdbus_cal_call_get_query_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &query_path, NULL, error)) {
+ if (!e_gdbus_cal_call_get_view_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (sexp, &gdbus_sexp), &query_path, NULL, error)) {
g_free (gdbus_sexp);
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
@@ -4143,13 +4330,13 @@ e_cal_get_query (ECal *ecal, const gchar *sexp, ECalView **query, GError **error
* the calendar.
*
* Returns: TRUE if the operation was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_set_default_timezone() instead.
*/
gboolean
e_cal_set_default_timezone (ECal *ecal, icaltimezone *zone, GError **error)
{
ECalPrivate *priv;
- icalcomponent *icalcomp = NULL;
- gchar *tzobj, *gdbus_tzobj = NULL;
e_return_error_if_fail (E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
e_return_error_if_fail (zone, E_CALENDAR_STATUS_INVALID_ARG);
@@ -4161,25 +4348,10 @@ e_cal_set_default_timezone (ECal *ecal, icaltimezone *zone, GError **error)
return TRUE;
/* FIXME Adding it to the server to change the tzid */
- icalcomp = icaltimezone_get_component (zone);
- if (!icalcomp) {
+ if (!icaltimezone_get_component (zone)) {
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_INVALID_ARG, error);
}
- /* convert icaltimezone into a string */
- tzobj = icalcomponent_as_ical_string_r (icalcomp);
-
- /* call the backend */
- if (!e_gdbus_cal_call_set_default_timezone_sync (priv->gdbus_cal, e_util_ensure_gdbus_string (tzobj, &gdbus_tzobj), NULL, error)) {
- g_free (tzobj);
- g_free (gdbus_tzobj);
-
- E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_DBUS_EXCEPTION, error);
- }
-
- g_free (tzobj);
- g_free (gdbus_tzobj);
-
priv->default_zone = zone;
E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error);
@@ -4192,6 +4364,8 @@ e_cal_set_default_timezone (ECal *ecal, icaltimezone *zone, GError **error)
* Gets an error message for the given status code.
*
* Returns: the error message.
+ *
+ * Deprecated: 3.2: Use e_cal_client_error_to_string() instead.
*/
const gchar *
e_cal_get_error_message (ECalendarStatus status)
@@ -4257,6 +4431,9 @@ e_cal_get_error_message (ECalendarStatus status)
* Opens the default calendar.
*
* Returns: TRUE if it opened correctly, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_new_default_calendar() instead
+ * and open it on your own.
*/
gboolean
e_cal_open_default (ECal **ecal,
@@ -4318,6 +4495,8 @@ e_cal_open_default (ECal **ecal,
* Sets a calendar as the default one.
*
* Returns: TRUE if the operation was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_set_default() instead.
*/
gboolean
e_cal_set_default (ECal *ecal, GError **error)
@@ -4387,6 +4566,8 @@ set_default_source (ESourceList *sources, ESource *source, GError **error)
* Sets the default source for the specified @type.
*
* Returns: TRUE if the operation was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_set_default_source() instead.
*/
gboolean
e_cal_set_default_source (ESource *source, ECalSourceType type, GError **error)
@@ -4422,6 +4603,8 @@ get_sources (ESourceList **sources, const gchar *key, GError **error)
* Gets the list of sources defined in the configuration for the given @type.
*
* Returns: TRUE if the operation was successful, FALSE otherwise.
+ *
+ * Deprecated: 3.2: Use e_cal_client_get_sources() instead.
*/
gboolean
e_cal_get_sources (ESourceList **sources, ECalSourceType type, GError **error)
diff --git a/calendar/libecal/e-cal.h b/calendar/libecal/e-cal.h
index ea599d5..a1dc014 100644
--- a/calendar/libecal/e-cal.h
+++ b/calendar/libecal/e-cal.h
@@ -22,6 +22,8 @@
#ifndef E_CAL_H
#define E_CAL_H
+#ifndef E_CAL_DISABLE_DEPRECATED
+
#include <glib-object.h>
#include "libedataserver/e-source-list.h"
#include "libedataserver/e-source.h"
@@ -70,6 +72,14 @@ typedef enum {
E_CAL_LOAD_LOADED
} ECalLoadState;
+#ifndef E_CAL_DISABLE_DEPRECATED
+typedef enum {
+ Local = 1 << 0,
+ Remote = 1 << 1,
+ AnyMode = 0x07
+} EDataCalMode;
+#endif
+
struct _ECal {
GObject object;
@@ -215,4 +225,6 @@ gboolean e_cal_get_attachments_for_comp (ECal *ecal, const gchar *uid, const gch
G_END_DECLS
+#endif /* E_CAL_DISABLE_DEPRECATED */
+
#endif
diff --git a/calendar/libedata-cal/e-cal-backend-sexp.c b/calendar/libedata-cal/e-cal-backend-sexp.c
index 729285f..2908037 100644
--- a/calendar/libedata-cal/e-cal-backend-sexp.c
+++ b/calendar/libedata-cal/e-cal-backend-sexp.c
@@ -382,9 +382,7 @@ func_occur_in_time_range (ESExp *esexp, gint argc, ESExpResult **argv, gpointer
end = argv[1]->value.time;
/* See if the object occurs in the specified time range */
- default_zone = e_cal_backend_internal_get_default_timezone (ctx->backend);
- if (!default_zone)
- default_zone = icaltimezone_get_utc_timezone ();
+ default_zone = icaltimezone_get_utc_timezone ();
ctx->occurs = FALSE;
e_cal_recur_generate_instances (ctx->comp, start, end,
@@ -883,9 +881,7 @@ func_has_alarms_in_range (ESExp *esexp, gint argc, ESExpResult **argv, gpointer
end = argv[1]->value.time;
/* See if the object has alarms in the given time range */
- default_zone = e_cal_backend_internal_get_default_timezone (ctx->backend);
- if (!default_zone)
- default_zone = icaltimezone_get_utc_timezone ();
+ default_zone = icaltimezone_get_utc_timezone ();
alarms = e_cal_util_generate_alarms_for_comp (ctx->comp, start, end,
omit, resolve_tzid,
diff --git a/calendar/libedata-cal/e-cal-backend-sync.c b/calendar/libedata-cal/e-cal-backend-sync.c
index 8264719..5c06864 100644
--- a/calendar/libedata-cal/e-cal-backend-sync.c
+++ b/calendar/libedata-cal/e-cal-backend-sync.c
@@ -21,15 +21,25 @@ struct _ECalBackendSyncPrivate {
gboolean mutex_lock;
};
-#define LOCK_WRAPPER(func, args) \
- g_assert (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->func); \
- if (backend->priv->mutex_lock) \
- g_mutex_lock (backend->priv->sync_mutex); \
- (* E_CAL_BACKEND_SYNC_GET_CLASS (backend)->func) args; \
- if (backend->priv->mutex_lock) \
- g_mutex_unlock (backend->priv->sync_mutex); \
-
-static GObjectClass *parent_class;
+#define LOCK_WRAPPER(func, args) G_STMT_START { \
+ gboolean locked = backend->priv->mutex_lock; \
+ e_return_data_cal_error_if_fail (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->func, NotSupported); \
+ if (locked) \
+ g_mutex_lock (backend->priv->sync_mutex); \
+ (* E_CAL_BACKEND_SYNC_GET_CLASS (backend)->func) args; \
+ if (locked) \
+ g_mutex_unlock (backend->priv->sync_mutex); \
+ } G_STMT_END
+
+#define LOCK_WRAPPER_RET_VAL(func, args) G_STMT_START { \
+ gboolean locked = backend->priv->mutex_lock; \
+ e_return_data_cal_error_val_if_fail (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->func, NotSupported); \
+ if (locked) \
+ g_mutex_lock (backend->priv->sync_mutex); \
+ res = (* E_CAL_BACKEND_SYNC_GET_CLASS (backend)->func) args; \
+ if (locked) \
+ g_mutex_unlock (backend->priv->sync_mutex); \
+ } G_STMT_END
/**
* e_cal_backend_sync_set_lock:
@@ -50,174 +60,230 @@ e_cal_backend_sync_set_lock (ECalBackendSync *backend, gboolean lock)
}
/**
- * e_cal_backend_sync_is_read_only:
+ * e_cal_backend_sync_open:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
- * @read_only: Return value for read-only status.
+ * @cancellable: a #GCancellable for the operation
+ * @only_if_exists: Whether to open the calendar if and only if it already exists
+ * or just create it when it does not exist.
* @error: Out parameter for a #GError.
*
- * Calls the is_read_only method on the given backend.
+ * Calls the open_sync method on the given backend.
*/
void
-e_cal_backend_sync_is_read_only (ECalBackendSync *backend, EDataCal *cal, gboolean *read_only, GError **error)
+e_cal_backend_sync_open (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gboolean only_if_exists, GError **error)
{
e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
- e_return_data_cal_error_if_fail (read_only, InvalidArg);
- LOCK_WRAPPER (is_read_only_sync, (backend, cal, read_only, error));
+ LOCK_WRAPPER (open_sync, (backend, cal, cancellable, only_if_exists, error));
}
/**
- * e_cal_backend_sync_get_cal_address:
+ * e_cal_backend_sync_authenticate_user:
+ * @backend: an #ECalBackendSync
+ * @cancellable: a #GCancellable for the operation
+ * @credentials: an #ECredentials to authenticate with
+ * @error: #GError to set, when something fails
+ *
+ * Authenticates @backend with given @credentials.
+ **/
+void
+e_cal_backend_sync_authenticate_user (ECalBackendSync *backend, GCancellable *cancellable, ECredentials *credentials, GError **error)
+{
+ e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
+ e_return_data_cal_error_if_fail (credentials, InvalidArg);
+
+ LOCK_WRAPPER (authenticate_user_sync, (backend, cancellable, credentials, error));
+}
+
+/**
+ * e_cal_backend_sync_remove:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
- * @address: Return value for the address.
+ * @cancellable: a #GCancellable for the operation
* @error: Out parameter for a #GError.
*
- * Calls the get_cal_address method on the given backend.
+ * Calls the remove_sync method on the given backend.
*/
void
-e_cal_backend_sync_get_cal_address (ECalBackendSync *backend, EDataCal *cal, gchar **address, GError **error)
+e_cal_backend_sync_remove (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **error)
{
e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
- e_return_data_cal_error_if_fail (address, InvalidArg);
- LOCK_WRAPPER (get_cal_address_sync, (backend, cal, address, error));
+ LOCK_WRAPPER (remove_sync, (backend, cal, cancellable, error));
}
/**
- * e_cal_backend_sync_get_alarm_email_address:
+ * e_cal_backend_sync_refresh:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
- * @address: Return value for the address.
+ * @cancellable: a #GCancellable for the operation
* @error: Out parameter for a #GError.
*
- * Calls the get_alarm_email_address method on the given backend.
+ * Calls the refresh_sync method on the given backend.
+ *
+ * Since: 2.30
*/
void
-e_cal_backend_sync_get_alarm_email_address (ECalBackendSync *backend, EDataCal *cal, gchar **address, GError **error)
+e_cal_backend_sync_refresh (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **error)
{
e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
- e_return_data_cal_error_if_fail (address, InvalidArg);
+ e_return_data_cal_error_if_fail (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->refresh_sync != NULL, UnsupportedMethod);
- LOCK_WRAPPER (get_alarm_email_address_sync, (backend, cal, address, error));
+ LOCK_WRAPPER (refresh_sync, (backend, cal, cancellable, error));
}
/**
- * e_cal_backend_sync_get_ldap_attribute:
+ * e_cal_backend_sync_get_backend_property:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
- * @attribute: Return value for LDAP attribute.
+ * @cancellable: a #GCancellable for the operation
+ * @prop_name: Property name whose value to retrieve.
+ * @prop_value: Return value of the @prop_name.
* @error: Out parameter for a #GError.
*
- * Calls the get_ldap_attribute method on the given backend.
- */
-void
-e_cal_backend_sync_get_ldap_attribute (ECalBackendSync *backend, EDataCal *cal, gchar **attribute, GError **error)
+ * Calls the get_backend_property_sync method on the given backend.
+ *
+ * Returns whether processed this property. Returning FALSE means to pass
+ * the call to the ECalBackend parent class, thus neither @error should be
+ * set in this case.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_backend_sync_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error)
{
- e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
- e_return_data_cal_error_if_fail (attribute, InvalidArg);
+ gboolean res = FALSE;
+
+ e_return_data_cal_error_val_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
+ e_return_data_cal_error_val_if_fail (prop_name, InvalidArg);
+ e_return_data_cal_error_val_if_fail (prop_value, InvalidArg);
- LOCK_WRAPPER (get_ldap_attribute_sync, (backend, cal, attribute, error));
+ LOCK_WRAPPER_RET_VAL (get_backend_property_sync, (backend, cal, cancellable, prop_name, prop_value, error));
+
+ return res;
}
/**
- * e_cal_backend_sync_get_static_capabilities:
+ * e_cal_backend_sync_set_backend_property:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
- * @capabilities: Return value for capabilities.
+ * @cancellable: a #GCancellable for the operation
+ * @prop_name: Property name to set.
+ * @prop_value: New value of the @prop_name.
* @error: Out parameter for a #GError.
*
- * Calls the get_capabilities method on the given backend.
- */
-void
-e_cal_backend_sync_get_static_capabilities (ECalBackendSync *backend, EDataCal *cal, gchar **capabilities, GError **error)
+ * Calls the set_backend_property_sync method on the given backend.
+ *
+ * Returns whether processed this property. Returning FALSE means to pass
+ * the call to the ECalBackend parent class, thus neither @error should be
+ * set in this case.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_backend_sync_set_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error)
{
- e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
- e_return_data_cal_error_if_fail (capabilities, InvalidArg);
+ gboolean res = FALSE;
+
+ e_return_data_cal_error_val_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
+ e_return_data_cal_error_val_if_fail (prop_name, InvalidArg);
+ e_return_data_cal_error_val_if_fail (prop_value, InvalidArg);
- LOCK_WRAPPER (get_static_capabilities_sync, (backend, cal, capabilities, error));
+ LOCK_WRAPPER_RET_VAL (set_backend_property_sync, (backend, cal, cancellable, prop_name, prop_value, error));
+
+ return res;
}
/**
- * e_cal_backend_sync_open:
+ * e_cal_backend_sync_get_object:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
- * @only_if_exists: Whether to open the calendar if and only if it already exists
- * or just create it when it does not exist.
- * @username: User name to use for authentication.
- * @password: Password to use for authentication.
+ * @cancellable: a #GCancellable for the operation
+ * @uid: UID of the object to get.
+ * @rid: Recurrence ID of the specific instance to get, or NULL if getting the
+ * master object.
+ * @calobj: Placeholder for returned object.
* @error: Out parameter for a #GError.
*
- * Calls the open method on the given backend.
+ * Calls the get_object_sync method on the given backend.
*/
void
-e_cal_backend_sync_open (ECalBackendSync *backend, EDataCal *cal, gboolean only_if_exists,
- const gchar *username, const gchar *password, GError **error)
+e_cal_backend_sync_get_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **calobj, GError **error)
{
e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
+ e_return_data_cal_error_if_fail (calobj, InvalidArg);
- LOCK_WRAPPER (open_sync, (backend, cal, only_if_exists, username, password, error));
+ LOCK_WRAPPER (get_object_sync, (backend, cal, cancellable, uid, rid, calobj, error));
}
/**
- * e_cal_backend_sync_remove:
+ * e_cal_backend_sync_get_object_list:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
+ * @cancellable: a #GCancellable for the operation
+ * @sexp: Search query.
+ * @calobjs: Placeholder for list of returned objects.
* @error: Out parameter for a #GError.
*
- * Calls the remove method on the given backend.
+ * Calls the get_object_list_sync method on the given backend.
*/
void
-e_cal_backend_sync_remove (ECalBackendSync *backend, EDataCal *cal, GError **error)
+e_cal_backend_sync_get_object_list (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *sexp, GSList **calobjs, GError **error)
{
e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
+ e_return_data_cal_error_if_fail (calobjs, InvalidArg);
- LOCK_WRAPPER (remove_sync, (backend, cal, error));
+ LOCK_WRAPPER (get_object_list_sync, (backend, cal, cancellable, sexp, calobjs, error));
}
/**
- * e_cal_backend_sync_refresh:
+ * e_cal_backend_sync_get_free_busy:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
+ * @cancellable: a #GCancellable for the operation
+ * @users: List of users to get F/B info from.
+ * @start: Time range start.
+ * @end: Time range end.
+ * @freebusyobjects: Placeholder for F/B information.
* @error: Out parameter for a #GError.
*
- * Calls the refresh method on the given backend.
- *
- * Since: 2.30
+ * Calls the get_free_busy_sync method on the given backend.
*/
void
-e_cal_backend_sync_refresh (ECalBackendSync *backend, EDataCal *cal, GError **error)
+e_cal_backend_sync_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const GSList *users, time_t start, time_t end, GSList **freebusyobjects, GError **error)
{
- e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
- e_return_data_cal_error_if_fail (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->refresh_sync != NULL, UnsupportedMethod);
+ e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
- LOCK_WRAPPER (refresh_sync, (backend, cal, error));
+ LOCK_WRAPPER (get_free_busy_sync, (backend, cal, cancellable, users, start, end, freebusyobjects, error));
}
/**
* e_cal_backend_sync_create_object:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
+ * @cancellable: a #GCancellable for the operation
* @calobj: The object to be added.
* @uid: Placeholder for server-generated UID.
+ * @new_object: Placeholder for server-calobj, if it changed. Can be left as is if it's same as @calobj.
* @error: Out parameter for a #GError.
*
- * Calls the create_object method on the given backend.
+ * Calls the create_object_sync method on the given backend.
*/
void
-e_cal_backend_sync_create_object (ECalBackendSync *backend, EDataCal *cal, gchar **calobj, gchar **uid, GError **error)
+e_cal_backend_sync_create_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, gchar **uid, gchar **new_object, GError **error)
{
e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
e_return_data_cal_error_if_fail (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->create_object_sync != NULL, UnsupportedMethod);
- LOCK_WRAPPER (create_object_sync, (backend, cal, calobj, uid, error));
+ LOCK_WRAPPER (create_object_sync, (backend, cal, cancellable, calobj, uid, new_object, error));
}
/**
* e_cal_backend_sync_modify_object:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
+ * @cancellable: a #GCancellable for the operation
* @calobj: Object to be modified.
* @mod: Type of modification to be done.
* @old_object: Placeholder for returning the old object as it was stored on the
@@ -226,187 +292,137 @@ e_cal_backend_sync_create_object (ECalBackendSync *backend, EDataCal *cal, gchar
* on the backend.
* @error: Out parameter for a #GError.
*
- * Calls the modify_object method on the given backend.
+ * Calls the modify_object_sync method on the given backend.
*/
void
-e_cal_backend_sync_modify_object (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj,
+e_cal_backend_sync_modify_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj,
CalObjModType mod, gchar **old_object, gchar **new_object, GError **error)
{
e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
e_return_data_cal_error_if_fail (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->modify_object_sync != NULL, UnsupportedMethod);
- LOCK_WRAPPER (modify_object_sync, (backend, cal, calobj, mod, old_object, new_object, error));
+ LOCK_WRAPPER (modify_object_sync, (backend, cal, cancellable, calobj, mod, old_object, new_object, error));
}
/**
* e_cal_backend_sync_remove_object:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
+ * @cancellable: a #GCancellable for the operation
* @uid: UID of the object to remove.
* @rid: Recurrence ID of the instance to remove, or NULL if removing the
* whole object.
* @mod: Type of removal.
* @old_object: Placeholder for returning the old object as it was stored on the
* backend.
- * @object: Placeholder for returning the object after it has been modified (when
+ * @new_object: Placeholder for returning the object after it has been modified (when
* removing individual instances). If removing the whole object, this will be
* NULL.
* @error: Out parameter for a #GError.
*
- * Calls the remove_object method on the given backend.
+ * Calls the remove_object_sync method on the given backend.
*/
void
-e_cal_backend_sync_remove_object (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *rid,
- CalObjModType mod, gchar **old_object, gchar **object, GError **error)
+e_cal_backend_sync_remove_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid,
+ CalObjModType mod, gchar **old_object, gchar **new_object, GError **error)
{
e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
e_return_data_cal_error_if_fail (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->remove_object_sync != NULL, UnsupportedMethod);
- LOCK_WRAPPER (remove_object_sync, (backend, cal, uid, rid, mod, old_object, object, error));
-}
-
-/**
- * e_cal_backend_sync_discard_alarm:
- * @backend: An ECalBackendSync object.
- * @cal: An EDataCal object.
- * @uid: UID of the object to discard the alarm from.
- * @auid: UID of the alarm to be discarded.
- * @error: Out parameter for a #GError.
- *
- * Calls the discard_alarm method on the given backend.
- */
-void
-e_cal_backend_sync_discard_alarm (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *auid, GError **error)
-{
- e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
- e_return_data_cal_error_if_fail (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->discard_alarm_sync != NULL, UnsupportedMethod);
-
- LOCK_WRAPPER (discard_alarm_sync, (backend, cal, uid, auid, error));
+ LOCK_WRAPPER (remove_object_sync, (backend, cal, cancellable, uid, rid, mod, old_object, new_object, error));
}
/**
* e_cal_backend_sync_receive_objects:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
+ * @cancellable: a #GCancellable for the operation
* @calobj: iCalendar object to receive.
* @error: Out parameter for a #GError.
*
- * Calls the receive_objects method on the given backend.
+ * Calls the receive_objects_sync method on the given backend.
*/
void
-e_cal_backend_sync_receive_objects (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, GError **error)
+e_cal_backend_sync_receive_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GError **error)
{
e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
e_return_data_cal_error_if_fail (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->receive_objects_sync != NULL, UnsupportedMethod);
- LOCK_WRAPPER (receive_objects_sync, (backend, cal, calobj, error));
+ LOCK_WRAPPER (receive_objects_sync, (backend, cal, cancellable, calobj, error));
}
/**
* e_cal_backend_sync_send_objects:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
+ * @cancellable: a #GCancellable for the operation
* @calobj: The iCalendar object to send.
* @users: List of users to send notifications to.
* @modified_calobj: Placeholder for the iCalendar object after being modified.
* @error: Out parameter for a #GError.
*
- * Calls the send_objects method on the given backend.
+ * Calls the send_objects_sync method on the given backend.
*/
void
-e_cal_backend_sync_send_objects (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, GList **users,
+e_cal_backend_sync_send_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GSList **users,
gchar **modified_calobj, GError **error)
{
e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
e_return_data_cal_error_if_fail (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->send_objects_sync != NULL, UnsupportedMethod);
- LOCK_WRAPPER (send_objects_sync, (backend, cal, calobj, users, modified_calobj, error));
+ LOCK_WRAPPER (send_objects_sync, (backend, cal, cancellable, calobj, users, modified_calobj, error));
}
/**
- * e_cal_backend_sync_get_default_object:
+ * e_cal_backend_sync_get_attachment_uris:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
- * @object: Placeholder for returned object.
- * @error: Out parameter for a #GError.
- *
- * Calls the get_default_object method on the given backend.
- */
-void
-e_cal_backend_sync_get_default_object (ECalBackendSync *backend, EDataCal *cal, gchar **object, GError **error)
-{
- e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
- e_return_data_cal_error_if_fail (object, InvalidArg);
-
- LOCK_WRAPPER (get_default_object_sync, (backend, cal, object, error));
-}
-
-/**
- * e_cal_backend_sync_get_object:
- * @backend: An ECalBackendSync object.
- * @cal: An EDataCal object.
- * @uid: UID of the object to get.
- * @rid: Recurrence ID of the specific instance to get, or NULL if getting the
- * master object.
- * @object: Placeholder for returned object.
- * @error: Out parameter for a #GError.
- *
- * Calls the get_object method on the given backend.
- */
-void
-e_cal_backend_sync_get_object (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *rid, gchar **object, GError **error)
-{
- e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
- e_return_data_cal_error_if_fail (object, InvalidArg);
-
- LOCK_WRAPPER (get_object_sync, (backend, cal, uid, rid, object, error));
-}
-
-/**
- * e_cal_backend_sync_get_object_list:
- * @backend: An ECalBackendSync object.
- * @cal: An EDataCal object.
- * @sexp: Search query.
- * @objects: Placeholder for list of returned objects.
+ * @cancellable: a #GCancellable for the operation
+ * @uid: Unique id of the calendar object.
+ * @rid: Recurrence id of the calendar object.
+ * @attachments: Placeholder for list of returned attachment uris.
* @error: Out parameter for a #GError.
*
- * Calls the get_object_list method on the given backend.
+ * Calls the get_attachment_uris_sync method on the given backend.
*/
void
-e_cal_backend_sync_get_object_list (ECalBackendSync *backend, EDataCal *cal, const gchar *sexp, GList **objects, GError **error)
+e_cal_backend_sync_get_attachment_uris (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, GSList **attachments, GError **error)
{
e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
- e_return_data_cal_error_if_fail (objects, InvalidArg);
+ e_return_data_cal_error_if_fail (attachments, InvalidArg);
- LOCK_WRAPPER (get_object_list_sync, (backend, cal, sexp, objects, error));
+ LOCK_WRAPPER (get_attachment_uris_sync, (backend, cal, cancellable, uid, rid, attachments, error));
}
/**
- * e_cal_backend_sync_get_attachment_list:
+ * e_cal_backend_sync_discard_alarm:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
+ * @cancellable: a #GCancellable for the operation
* @uid: Unique id of the calendar object.
* @rid: Recurrence id of the calendar object.
- * @attachments: Placeholder for list of returned attachment uris.
+ * @auid: Alarm ID to remove.
* @error: Out parameter for a #GError.
*
- * Calls the get_attachment_list method on the given backend.
- */
+ * Calls the discard_alarm_sync method on the given backend.
+ **/
void
-e_cal_backend_sync_get_attachment_list (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *rid, GSList **attachments, GError **error)
+e_cal_backend_sync_discard_alarm (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, const gchar *auid, GError **error)
{
e_return_data_cal_error_if_fail (backend && E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
- e_return_data_cal_error_if_fail (attachments, InvalidArg);
+ e_return_data_cal_error_if_fail (uid, InvalidArg);
+ e_return_data_cal_error_if_fail (auid, InvalidArg);
- LOCK_WRAPPER (get_attachment_list_sync, (backend, cal, uid, rid, attachments, error));
+ LOCK_WRAPPER (discard_alarm_sync, (backend, cal, cancellable, uid, rid, auid, error));
}
/**
* e_cal_backend_sync_get_timezone:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
+ * @cancellable: a #GCancellable for the operation
* @tzid: ID of the timezone to retrieve.
- * @object: Placeholder for the returned timezone.
+ * @tzobject: Placeholder for the returned timezone.
* @error: Out parameter for a #GError.
*
* Calls the get_timezone_sync method on the given backend.
@@ -418,15 +434,15 @@ e_cal_backend_sync_get_attachment_list (ECalBackendSync *backend, EDataCal *cal,
* get_timezone_sync completely.
*/
void
-e_cal_backend_sync_get_timezone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzid, gchar **object, GError **error)
+e_cal_backend_sync_get_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzid, gchar **tzobject, GError **error)
{
e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
if (E_CAL_BACKEND_SYNC_GET_CLASS (backend)->get_timezone_sync) {
- LOCK_WRAPPER (get_timezone_sync, (backend, cal, tzid, object, error));
+ LOCK_WRAPPER (get_timezone_sync, (backend, cal, cancellable, tzid, tzobject, error));
}
- if (object && !*object) {
+ if (tzobject && !*tzobject) {
icaltimezone *zone = NULL;
if (backend->priv->mutex_lock)
@@ -445,7 +461,7 @@ e_cal_backend_sync_get_timezone (ECalBackendSync *backend, EDataCal *cal, const
if (!icalcomp) {
g_propagate_error (error, e_data_cal_create_error (InvalidObject, NULL));
} else {
- *object = icalcomponent_as_ical_string_r (icalcomp);
+ *tzobject = icalcomponent_as_ical_string_r (icalcomp);
}
}
}
@@ -455,334 +471,231 @@ e_cal_backend_sync_get_timezone (ECalBackendSync *backend, EDataCal *cal, const
* e_cal_backend_sync_add_timezone:
* @backend: An ECalBackendSync object.
* @cal: An EDataCal object.
- * @tzobj: VTIMEZONE object to be added.
- * @error: Out parameter for a #GError.
- *
- * Calls the add_timezone method on the given backend.
- */
-void
-e_cal_backend_sync_add_timezone (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **error)
-{
- e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
-
- LOCK_WRAPPER (add_timezone_sync, (backend, cal, tzobj, error));
-}
-
-/**
- * e_cal_backend_sync_set_default_zone:
- * @backend: An ECalBackendSync object.
- * @cal: An EDataCal object.
- * @tz: Timezone object as string.
+ * @cancellable: a #GCancellable for the operation
+ * @tzobject: VTIMEZONE object to be added.
* @error: Out parameter for a #GError.
*
- * Calls the set_default_zone method on the given backend.
+ * Calls the add_timezone_sync method on the given backend.
*/
void
-e_cal_backend_sync_set_default_zone (ECalBackendSync *backend, EDataCal *cal, const gchar *tz, GError **error)
+e_cal_backend_sync_add_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobject, GError **error)
{
e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
- LOCK_WRAPPER (set_default_zone_sync, (backend, cal, tz, error));
-}
-
-/**
- * e_cal_backend_sync_get_changes:
- * @backend: An ECalBackendSync object.
- * @cal: An EDataCal object.
- * @change_id: ID of the change to use as base.
- * @adds: Placeholder for list of additions.
- * @modifies: Placeholder for list of modifications.
- * @deletes: Placeholder for list of deletions.
- * @error: Out parameter for a #GError.
- *
- * Calls the get_changes method on the given backend.
- */
-void
-e_cal_backend_sync_get_changes (ECalBackendSync *backend, EDataCal *cal, const gchar *change_id,
- GList **adds, GList **modifies, GList **deletes, GError **error)
-{
- e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
-
- LOCK_WRAPPER (get_changes_sync, (backend, cal, change_id, adds, modifies, deletes, error));
-}
-
-/**
- * e_cal_backend_sync_get_free_busy:
- * @backend: An ECalBackendSync object.
- * @cal: An EDataCal object.
- * @users: List of users to get F/B info from.
- * @start: Time range start.
- * @end: Time range end.
- * @freebusy: Placeholder for F/B information.
- * @error: Out parameter for a #GError.
- *
- * Calls the get_free_busy method on the given backend.
- */
-void
-e_cal_backend_sync_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GList *users,
- time_t start, time_t end, GList **freebusy, GError **error)
-{
- e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_SYNC (backend), InvalidArg);
-
- LOCK_WRAPPER (get_freebusy_sync, (backend, cal, users, start, end, freebusy, error));
+ LOCK_WRAPPER (add_timezone_sync, (backend, cal, cancellable, tzobject, error));
}
static void
-_e_cal_backend_is_read_only (ECalBackend *backend, EDataCal *cal)
+cal_backend_open (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, gboolean only_if_exists)
{
GError *error = NULL;
- gboolean read_only = TRUE;
- e_cal_backend_sync_is_read_only (E_CAL_BACKEND_SYNC (backend), cal, &read_only, &error);
+ e_cal_backend_sync_open (E_CAL_BACKEND_SYNC (backend), cal, cancellable, only_if_exists, &error);
- e_data_cal_notify_read_only (cal, error, read_only);
+ e_data_cal_respond_open (cal, opid, error);
}
static void
-_e_cal_backend_get_cal_address (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+cal_backend_authenticate_user (ECalBackend *backend, GCancellable *cancellable, ECredentials *credentials)
{
GError *error = NULL;
- gchar *address = NULL;
-
- e_cal_backend_sync_get_cal_address (E_CAL_BACKEND_SYNC (backend), cal, &address, &error);
- e_data_cal_notify_cal_address (cal, context, error, address);
+ e_cal_backend_sync_authenticate_user (E_CAL_BACKEND_SYNC (backend), cancellable, credentials, &error);
- g_free (address);
+ e_cal_backend_notify_opened (backend, error);
}
static void
-_e_cal_backend_get_alarm_email_address (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+cal_backend_remove (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable)
{
GError *error = NULL;
- gchar *address = NULL;
- e_cal_backend_sync_get_alarm_email_address (E_CAL_BACKEND_SYNC (backend), cal, &address, &error);
+ e_cal_backend_sync_remove (E_CAL_BACKEND_SYNC (backend), cal, cancellable, &error);
- e_data_cal_notify_alarm_email_address (cal, context, error, address);
-
- g_free (address);
+ e_data_cal_respond_remove (cal, opid, error);
}
static void
-_e_cal_backend_get_ldap_attribute (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+cal_backend_refresh (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable)
{
GError *error = NULL;
- gchar *attribute = NULL;
-
- e_cal_backend_sync_get_ldap_attribute (E_CAL_BACKEND_SYNC (backend), cal, &attribute, &error);
- e_data_cal_notify_ldap_attribute (cal, context, error, attribute);
+ e_cal_backend_sync_refresh (E_CAL_BACKEND_SYNC (backend), cal, cancellable, &error);
- g_free (attribute);
+ e_data_cal_respond_refresh (cal, opid, error);
}
static void
-_e_cal_backend_get_static_capabilities (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+cal_backend_get_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
{
GError *error = NULL;
- gchar *capabilities = NULL;
-
- e_cal_backend_sync_get_static_capabilities (E_CAL_BACKEND_SYNC (backend), cal, &capabilities, &error);
+ gchar *prop_value = NULL;
- e_data_cal_notify_static_capabilities (cal, context, error, capabilities);
+ if (e_cal_backend_sync_get_backend_property (E_CAL_BACKEND_SYNC (backend), cal, cancellable, prop_name, &prop_value, &error))
+ e_data_cal_respond_get_backend_property (cal, opid, error, prop_value);
+ else
+ (* E_CAL_BACKEND_CLASS (e_cal_backend_sync_parent_class)->get_backend_property) (backend, cal, opid, cancellable, prop_name);
- g_free (capabilities);
+ g_free (prop_value);
}
static void
-_e_cal_backend_open (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, gboolean only_if_exists,
- const gchar *username, const gchar *password)
+cal_backend_set_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value)
{
GError *error = NULL;
- e_cal_backend_sync_open (E_CAL_BACKEND_SYNC (backend), cal, only_if_exists, username, password, &error);
-
- e_data_cal_notify_open (cal, context, error);
+ if (e_cal_backend_sync_set_backend_property (E_CAL_BACKEND_SYNC (backend), cal, cancellable, prop_name, prop_value, &error))
+ e_data_cal_respond_set_backend_property (cal, opid, error);
+ else
+ (* E_CAL_BACKEND_CLASS (e_cal_backend_sync_parent_class)->set_backend_property) (backend, cal, opid, cancellable, prop_name, prop_value);
}
static void
-_e_cal_backend_refresh (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+cal_backend_get_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid)
{
GError *error = NULL;
+ gchar *calobj = NULL;
- e_cal_backend_sync_refresh (E_CAL_BACKEND_SYNC (backend), cal, &error);
+ e_cal_backend_sync_get_object (E_CAL_BACKEND_SYNC (backend), cal, cancellable, uid, rid, &calobj, &error);
- e_data_cal_notify_refresh (cal, context, error);
+ e_data_cal_respond_get_object (cal, opid, error, calobj);
+
+ g_free (calobj);
}
static void
-_e_cal_backend_remove (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+cal_backend_get_object_list (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *sexp)
{
GError *error = NULL;
+ GSList *calobjs = NULL;
+
+ e_cal_backend_sync_get_object_list (E_CAL_BACKEND_SYNC (backend), cal, cancellable, sexp, &calobjs, &error);
- e_cal_backend_sync_remove (E_CAL_BACKEND_SYNC (backend), cal, &error);
+ e_data_cal_respond_get_object_list (cal, opid, error, calobjs);
- e_data_cal_notify_remove (cal, context, error);
+ g_slist_foreach (calobjs, (GFunc) g_free, NULL);
+ g_slist_free (calobjs);
}
static void
-_e_cal_backend_create_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
+cal_backend_get_free_busy (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const GSList *users, time_t start, time_t end)
{
GError *error = NULL;
- gchar *uid = NULL, *modified_calobj = (gchar *) calobj;
-
- e_cal_backend_sync_create_object (E_CAL_BACKEND_SYNC (backend), cal, &modified_calobj, &uid, &error);
+ GSList *freebusyobjs = NULL;
- e_data_cal_notify_object_created (cal, context, error, uid, modified_calobj);
+ e_cal_backend_sync_get_free_busy (E_CAL_BACKEND_SYNC (backend), cal, cancellable, users, start, end, &freebusyobjs, &error);
- /* free memory */
- if (uid)
- g_free (uid);
+ if (freebusyobjs)
+ e_data_cal_report_free_busy_data (cal, freebusyobjs);
+ e_data_cal_respond_get_free_busy (cal, opid, error);
- if (modified_calobj != calobj)
- g_free (modified_calobj);
+ g_slist_foreach (freebusyobjs, (GFunc) g_free, NULL);
+ g_slist_free (freebusyobjs);
}
static void
-_e_cal_backend_modify_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj, CalObjModType mod)
+cal_backend_create_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj)
{
GError *error = NULL;
- gchar *old_object = NULL;
- gchar *new_object = NULL;
+ gchar *uid = NULL, *new_object = NULL;
- e_cal_backend_sync_modify_object (E_CAL_BACKEND_SYNC (backend), cal,
- calobj, mod, &old_object, &new_object, &error);
+ e_cal_backend_sync_create_object (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobj, &uid, &new_object, &error);
- if (new_object)
- e_data_cal_notify_object_modified (cal, context, error, old_object, new_object);
- else
- e_data_cal_notify_object_modified (cal, context, error, old_object, calobj);
+ e_data_cal_respond_create_object (cal, opid, error, uid, new_object ? new_object : calobj);
- g_free (old_object);
+ g_free (uid);
g_free (new_object);
}
static void
-_e_cal_backend_remove_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid, CalObjModType mod)
+cal_backend_modify_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj, CalObjModType mod)
{
GError *error = NULL;
- gchar *object = NULL, *old_object = NULL;
-
- e_cal_backend_sync_remove_object (E_CAL_BACKEND_SYNC (backend), cal, uid, rid, mod, &old_object, &object, &error);
-
- if (!error) {
- ECalComponentId *id = g_new0 (ECalComponentId, 1);
- id->uid = g_strdup (uid);
+ gchar *old_object = NULL, *new_object = NULL;
- if (mod == CALOBJ_MOD_THIS)
- id->rid = g_strdup (rid);
+ e_cal_backend_sync_modify_object (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobj, mod, &old_object, &new_object, &error);
- if (!object)
- e_data_cal_notify_object_removed (cal, context, error, id, old_object, object);
- else
- e_data_cal_notify_object_modified (cal, context, error, old_object, object);
-
- e_cal_component_free_id (id);
- } else
- e_data_cal_notify_object_removed (cal, context, error, NULL, old_object, object);
+ e_data_cal_respond_modify_object (cal, opid, error, old_object ? old_object : calobj, new_object);
g_free (old_object);
- g_free (object);
-}
-
-static void
-_e_cal_backend_discard_alarm (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *auid)
-{
- GError *error = NULL;
-
- e_cal_backend_sync_discard_alarm (E_CAL_BACKEND_SYNC (backend), cal, uid, auid, &error);
-
- e_data_cal_notify_alarm_discarded (cal, context, error);
+ g_free (new_object);
}
static void
-_e_cal_backend_receive_objects (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
+cal_backend_remove_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid, CalObjModType mod)
{
GError *error = NULL;
+ gchar *old_object = NULL, *new_object = NULL;
+ ECalComponentId compid;
- e_cal_backend_sync_receive_objects (E_CAL_BACKEND_SYNC (backend), cal, calobj, &error);
-
- e_data_cal_notify_objects_received (cal, context, error);
-}
+ compid.uid = (gchar *) uid;
+ compid.rid = (gchar *) (mod == CALOBJ_MOD_THIS ? rid : NULL);
-static void
-_e_cal_backend_send_objects (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
-{
- GError *error = NULL;
- GList *users = NULL;
- gchar *modified_calobj = NULL;
+ e_cal_backend_sync_remove_object (E_CAL_BACKEND_SYNC (backend), cal, cancellable, uid, rid, mod, &old_object, &new_object, &error);
- e_cal_backend_sync_send_objects (E_CAL_BACKEND_SYNC (backend), cal, calobj, &users, &modified_calobj, &error);
- e_data_cal_notify_objects_sent (cal, context, error, users, modified_calobj);
+ e_data_cal_respond_remove_object (cal, opid, error, &compid, old_object, new_object);
- g_list_foreach (users, (GFunc) g_free, NULL);
- g_list_free (users);
- g_free (modified_calobj);
+ g_free (old_object);
+ g_free (new_object);
}
static void
-_e_cal_backend_get_default_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+cal_backend_receive_objects (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj)
{
GError *error = NULL;
- gchar *object = NULL;
-
- e_cal_backend_sync_get_default_object (E_CAL_BACKEND_SYNC (backend), cal, &object, &error);
- e_data_cal_notify_default_object (cal, context, error, object);
+ e_cal_backend_sync_receive_objects (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobj, &error);
- g_free (object);
+ e_data_cal_respond_receive_objects (cal, opid, error);
}
static void
-_e_cal_backend_get_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid)
+cal_backend_send_objects (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj)
{
GError *error = NULL;
- gchar *object = NULL;
+ GSList *users = NULL;
+ gchar *modified_calobj = NULL;
- e_cal_backend_sync_get_object (E_CAL_BACKEND_SYNC (backend), cal, uid, rid, &object, &error);
+ e_cal_backend_sync_send_objects (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobj, &users, &modified_calobj, &error);
- e_data_cal_notify_object (cal, context, error, object);
+ e_data_cal_respond_send_objects (cal, opid, error, users, modified_calobj ? modified_calobj : calobj);
- g_free (object);
+ g_slist_foreach (users, (GFunc) g_free, NULL);
+ g_slist_free (users);
+ g_free (modified_calobj);
}
static void
-_e_cal_backend_get_attachment_list (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid)
+cal_backend_get_attachment_uris (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid)
{
GError *error = NULL;
- GSList *list = NULL;
+ GSList *attachments = NULL;
- e_cal_backend_sync_get_attachment_list (E_CAL_BACKEND_SYNC (backend), cal, uid, rid, &list, &error);
+ e_cal_backend_sync_get_attachment_uris (E_CAL_BACKEND_SYNC (backend), cal, cancellable, uid, rid, &attachments, &error);
- e_data_cal_notify_attachment_list (cal, context, error, list);
+ e_data_cal_respond_get_attachment_uris (cal, opid, error, attachments);
- g_slist_foreach (list, (GFunc) g_free, NULL);
- g_free (list);
+ g_slist_foreach (attachments, (GFunc) g_free, NULL);
+ g_slist_free (attachments);
}
static void
-_e_cal_backend_get_object_list (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *sexp)
+cal_backend_discard_alarm (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid, const gchar *auid)
{
GError *error = NULL;
- GList *objects = NULL, *l;
- e_cal_backend_sync_get_object_list (E_CAL_BACKEND_SYNC (backend), cal, sexp, &objects, &error);
+ e_cal_backend_sync_discard_alarm (E_CAL_BACKEND_SYNC (backend), cal, cancellable, uid, rid, auid, &error);
- e_data_cal_notify_object_list (cal, context, error, objects);
-
- for (l = objects; l; l = l->next)
- g_free (l->data);
- g_list_free (objects);
+ e_data_cal_respond_discard_alarm (cal, opid, error);
}
static void
-_e_cal_backend_get_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzid)
+cal_backend_get_timezone (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *tzid)
{
GError *error = NULL;
gchar *object = NULL;
- e_cal_backend_sync_get_timezone (E_CAL_BACKEND_SYNC (backend), cal, tzid, &object, &error);
+ e_cal_backend_sync_get_timezone (E_CAL_BACKEND_SYNC (backend), cal, cancellable, tzid, &object, &error);
if (!object && tzid) {
/* fallback if tzid contains only the location of timezone */
@@ -827,22 +740,22 @@ _e_cal_backend_get_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodC
/* also cache this timezone to backend */
if (object)
- e_cal_backend_sync_add_timezone (E_CAL_BACKEND_SYNC (backend), cal, object, NULL);
+ e_cal_backend_sync_add_timezone (E_CAL_BACKEND_SYNC (backend), cal, cancellable, object, NULL);
}
- e_data_cal_notify_timezone_requested (cal, context, error, object);
+ e_data_cal_respond_get_timezone (cal, opid, error, object);
g_free (object);
}
static void
-_e_cal_backend_add_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzobj)
+cal_backend_add_timezone (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *tzobject)
{
GError *error = NULL;
- e_cal_backend_sync_add_timezone (E_CAL_BACKEND_SYNC (backend), cal, tzobj, &error);
+ e_cal_backend_sync_add_timezone (E_CAL_BACKEND_SYNC (backend), cal, cancellable, tzobject, &error);
- e_data_cal_notify_timezone_added (cal, context, error, tzobj);
+ e_data_cal_respond_add_timezone (cal, opid, error);
}
/* The default implementation is looking for timezone in the ical's builtin timezones,
@@ -853,7 +766,7 @@ _e_cal_backend_add_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodC
fails, then call parent's object internal_get_timezone, and that's all.
*/
static icaltimezone *
-_e_cal_backend_internal_get_timezone (ECalBackend *backend, const gchar *tzid)
+cal_backend_internal_get_timezone (ECalBackend *backend, const gchar *tzid)
{
icaltimezone *zone = NULL;
@@ -885,53 +798,18 @@ _e_cal_backend_internal_get_timezone (ECalBackend *backend, const gchar *tzid)
return zone;
}
-static void
-_e_cal_backend_set_default_zone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tz)
+static gboolean
+cal_backend_sync_get_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error)
{
- GError *error = NULL;
-
- e_cal_backend_sync_set_default_zone (E_CAL_BACKEND_SYNC (backend), cal, tz, &error);
-
- e_data_cal_notify_default_timezone_set (cal, context, error);
+ /* to indicate to pass to the ECalBackend parent class */
+ return FALSE;
}
-static void
-_e_cal_backend_get_changes (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *change_id)
+static gboolean
+cal_backend_sync_set_backend_property (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error)
{
- GError *error = NULL;
- GList *adds = NULL, *modifies = NULL, *deletes = NULL, *l;
-
- e_cal_backend_sync_get_changes (E_CAL_BACKEND_SYNC (backend), cal, change_id,
- &adds, &modifies, &deletes, &error);
-
- e_data_cal_notify_changes (cal, context, error, adds, modifies, deletes);
-
- for (l = adds; l; l = l->next)
- g_free (l->data);
- g_list_free (adds);
-
- for (l = modifies; l; l = l->next)
- g_free (l->data);
- g_list_free (modifies);
-
- for (l = deletes; l; l = l->next)
- g_free (l->data);
- g_list_free (deletes);
-}
-
-static void
-_e_cal_backend_get_free_busy (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, GList *users, time_t start, time_t end)
-{
- GError *error = NULL;
- GList *freebusy = NULL, *l;
-
- e_cal_backend_sync_get_free_busy (E_CAL_BACKEND_SYNC (backend), cal, users, start, end, &freebusy, &error);
-
- e_data_cal_notify_free_busy (cal, context, error, freebusy);
-
- for (l = freebusy; l; l = l->next)
- g_free (l->data);
- g_list_free (freebusy);
+ /* to indicate to pass to the ECalBackend parent class */
+ return FALSE;
}
static void
@@ -959,43 +837,39 @@ e_cal_backend_sync_dispose (GObject *object)
backend->priv = NULL;
}
- G_OBJECT_CLASS (parent_class)->dispose (object);
+ G_OBJECT_CLASS (e_cal_backend_sync_parent_class)->dispose (object);
}
static void
e_cal_backend_sync_class_init (ECalBackendSyncClass *klass)
{
GObjectClass *object_class;
- ECalBackendClass *backend_class = E_CAL_BACKEND_CLASS (klass);
-
- parent_class = g_type_class_peek_parent (klass);
-
- object_class = (GObjectClass *) klass;
-
- backend_class->is_read_only = _e_cal_backend_is_read_only;
- backend_class->get_cal_address = _e_cal_backend_get_cal_address;
- backend_class->get_alarm_email_address = _e_cal_backend_get_alarm_email_address;
- backend_class->get_ldap_attribute = _e_cal_backend_get_ldap_attribute;
- backend_class->get_static_capabilities = _e_cal_backend_get_static_capabilities;
- backend_class->open = _e_cal_backend_open;
- backend_class->refresh = _e_cal_backend_refresh;
- backend_class->remove = _e_cal_backend_remove;
- backend_class->create_object = _e_cal_backend_create_object;
- backend_class->modify_object = _e_cal_backend_modify_object;
- backend_class->remove_object = _e_cal_backend_remove_object;
- backend_class->discard_alarm = _e_cal_backend_discard_alarm;
- backend_class->receive_objects = _e_cal_backend_receive_objects;
- backend_class->send_objects = _e_cal_backend_send_objects;
- backend_class->get_default_object = _e_cal_backend_get_default_object;
- backend_class->get_object = _e_cal_backend_get_object;
- backend_class->get_object_list = _e_cal_backend_get_object_list;
- backend_class->get_attachment_list = _e_cal_backend_get_attachment_list;
- backend_class->get_timezone = _e_cal_backend_get_timezone;
- backend_class->add_timezone = _e_cal_backend_add_timezone;
- backend_class->set_default_zone = _e_cal_backend_set_default_zone;
- backend_class->get_changes = _e_cal_backend_get_changes;
- backend_class->get_free_busy = _e_cal_backend_get_free_busy;
- backend_class->internal_get_timezone = _e_cal_backend_internal_get_timezone;
+ ECalBackendClass *backend_class;
+ object_class = G_OBJECT_CLASS (klass);
object_class->dispose = e_cal_backend_sync_dispose;
+
+ backend_class = E_CAL_BACKEND_CLASS (klass);
+ backend_class->open = cal_backend_open;
+ backend_class->authenticate_user = cal_backend_authenticate_user;
+ backend_class->remove = cal_backend_remove;
+ backend_class->refresh = cal_backend_refresh;
+ backend_class->get_backend_property = cal_backend_get_backend_property;
+ backend_class->set_backend_property = cal_backend_set_backend_property;
+ backend_class->get_object = cal_backend_get_object;
+ backend_class->get_object_list = cal_backend_get_object_list;
+ backend_class->get_free_busy = cal_backend_get_free_busy;
+ backend_class->create_object = cal_backend_create_object;
+ backend_class->modify_object = cal_backend_modify_object;
+ backend_class->remove_object = cal_backend_remove_object;
+ backend_class->receive_objects = cal_backend_receive_objects;
+ backend_class->send_objects = cal_backend_send_objects;
+ backend_class->get_attachment_uris = cal_backend_get_attachment_uris;
+ backend_class->discard_alarm = cal_backend_discard_alarm;
+ backend_class->get_timezone = cal_backend_get_timezone;
+ backend_class->add_timezone = cal_backend_add_timezone;
+ backend_class->internal_get_timezone = cal_backend_internal_get_timezone;
+
+ klass->get_backend_property_sync = cal_backend_sync_get_backend_property;
+ klass->set_backend_property_sync = cal_backend_sync_set_backend_property;
}
diff --git a/calendar/libedata-cal/e-cal-backend-sync.h b/calendar/libedata-cal/e-cal-backend-sync.h
index 5080582..a77dc87 100644
--- a/calendar/libedata-cal/e-cal-backend-sync.h
+++ b/calendar/libedata-cal/e-cal-backend-sync.h
@@ -16,6 +16,7 @@ G_BEGIN_DECLS
#define E_IS_CAL_BACKEND_SYNC(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_CAL_BACKEND_SYNC))
#define E_IS_CAL_BACKEND_SYNC_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_CAL_BACKEND_SYNC))
#define E_CAL_BACKEND_SYNC_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((k), E_TYPE_CAL_BACKEND_SYNC, ECalBackendSyncClass))
+
typedef struct _ECalBackendSync ECalBackendSync;
typedef struct _ECalBackendSyncClass ECalBackendSyncClass;
typedef struct _ECalBackendSyncPrivate ECalBackendSyncPrivate;
@@ -30,177 +31,51 @@ struct _ECalBackendSyncClass {
ECalBackendClass parent_class;
/* Virtual methods */
- void (*is_read_only_sync) (ECalBackendSync *backend, EDataCal *cal, gboolean *read_only, GError **perror);
- void (*get_cal_address_sync) (ECalBackendSync *backend, EDataCal *cal, gchar **address, GError **perror);
- void (*get_alarm_email_address_sync) (ECalBackendSync *backend, EDataCal *cal, gchar **address, GError **perror);
- void (*get_ldap_attribute_sync) (ECalBackendSync *backend, EDataCal *cal, gchar **attribute, GError **perror);
- void (*get_static_capabilities_sync) (ECalBackendSync *backend, EDataCal *cal, gchar **capabilities, GError **perror);
-
- void (*open_sync) (ECalBackendSync *backend, EDataCal *cal, gboolean only_if_exists, const gchar *username, const gchar *password, GError **perror);
- void (*refresh_sync) (ECalBackendSync *backend, EDataCal *cal, GError **perror);
- void (*remove_sync) (ECalBackendSync *backend, EDataCal *cal, GError **perror);
-
- void (*create_object_sync) (ECalBackendSync *backend, EDataCal *cal, gchar **calobj, gchar **uid, GError **perror);
- void (*modify_object_sync) (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, CalObjModType mod, gchar **old_object, gchar **new_object, GError **perror);
- void (*remove_object_sync) (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *rid, CalObjModType mod, gchar **old_object, gchar **object, GError **perror);
-
- void (*discard_alarm_sync) (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *auid, GError **perror);
-
- void (*receive_objects_sync) (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, GError **perror);
- void (*send_objects_sync) (ECalBackendSync *backend, EDataCal *cal, const gchar *calobj, GList **users,
- gchar **modified_calobj, GError **perror);
-
- void (*get_default_object_sync) (ECalBackendSync *backend, EDataCal *cal, gchar **object, GError **perror);
- void (*get_object_sync) (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *rid, gchar **object, GError **perror);
- void (*get_object_list_sync) (ECalBackendSync *backend, EDataCal *cal, const gchar *sexp, GList **objects, GError **perror);
-
- void (*get_attachment_list_sync) (ECalBackendSync *backend, EDataCal *cal, const gchar *uid, const gchar *rid, GSList **attachments, GError **perror);
-
- void (*get_timezone_sync) (ECalBackendSync *backend, EDataCal *cal, const gchar *tzid, gchar **object, GError **perror);
- void (*add_timezone_sync) (ECalBackendSync *backend, EDataCal *cal, const gchar *tzobj, GError **perror);
- void (*set_default_zone_sync) (ECalBackendSync *backend, EDataCal *cal, const gchar *tz, GError **perror);
-
- void (*get_changes_sync) (ECalBackendSync *backend, EDataCal *cal, const gchar *change_id, GList **adds, GList **modifies, GList **deletes, GError **perror);
- void (*get_freebusy_sync) (ECalBackendSync *backend, EDataCal *cal, GList *users, time_t start, time_t end, GList **freebusy, GError **perror);
-
- /* Padding for future expansion */
- void (*_cal_reserved0) (void);
- void (*_cal_reserved1) (void);
- void (*_cal_reserved2) (void);
- void (*_cal_reserved3) (void);
- void (*_cal_reserved4) (void);
-
+ void (* open_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gboolean only_if_exists, GError **error);
+ void (* remove_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **error);
+
+ void (* refresh_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **error);
+ gboolean (* get_backend_property_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error);
+ gboolean (* set_backend_property_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error);
+ void (* get_object_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **calobj, GError **error);
+ void (* get_object_list_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *sexp, GSList **calobjs, GError **error);
+ void (* get_free_busy_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const GSList *users, time_t start, time_t end, GSList **freebusyobjs, GError **error);
+ void (* create_object_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, gchar **uid, gchar **new_object, GError **error);
+ void (* modify_object_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, CalObjModType mod, gchar **old_object, gchar **new_object, GError **error);
+ void (* remove_object_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, CalObjModType mod, gchar **old_object, gchar **new_object, GError **error);
+ void (* receive_objects_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GError **error);
+ void (* send_objects_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GSList **users, gchar **modified_calobj, GError **error);
+ void (* get_attachment_uris_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, GSList **attachments, GError **error);
+ void (* discard_alarm_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, const gchar *auid, GError **error);
+ void (* get_timezone_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzid, gchar **tzobject, GError **error);
+ void (* add_timezone_sync) (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobject, GError **error);
+
+ void (* authenticate_user_sync) (ECalBackendSync *backend, GCancellable *cancellable, ECredentials *credentials, GError **error);
};
-typedef ECalBackendSync * (*ECalBackendSyncFactoryFn) (void);
-GType e_cal_backend_sync_get_type (void);
-
-void e_cal_backend_sync_set_lock (ECalBackendSync *backend,
- gboolean lock);
-
-void e_cal_backend_sync_is_read_only (ECalBackendSync *backend,
- EDataCal *cal,
- gboolean *read_only,
- GError **error);
-void e_cal_backend_sync_get_cal_address (ECalBackendSync *backend,
- EDataCal *cal,
- gchar **address,
- GError **error);
-void e_cal_backend_sync_get_alarm_email_address
- (ECalBackendSync *backend,
- EDataCal *cal,
- gchar **address,
- GError **error);
-void e_cal_backend_sync_get_ldap_attribute (ECalBackendSync *backend,
- EDataCal *cal,
- gchar **attribute,
- GError **error);
-void e_cal_backend_sync_get_static_capabilities
- (ECalBackendSync *backend,
- EDataCal *cal,
- gchar **capabiliites,
- GError **error);
-void e_cal_backend_sync_open (ECalBackendSync *backend,
- EDataCal *cal,
- gboolean only_if_exists,
- const gchar *username,
- const gchar *password,
- GError **error);
-void e_cal_backend_sync_refresh (ECalBackendSync *backend,
- EDataCal *cal,
- GError **error);
-void e_cal_backend_sync_remove (ECalBackendSync *backend,
- EDataCal *cal,
- GError **error);
-void e_cal_backend_sync_create_object (ECalBackendSync *backend,
- EDataCal *cal,
- gchar **calobj,
- gchar **uid,
- GError **error);
-void e_cal_backend_sync_modify_object (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *calobj,
- CalObjModType mod,
- gchar **old_object,
- gchar **new_object,
- GError **error);
-void e_cal_backend_sync_remove_object (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *uid,
- const gchar *rid,
- CalObjModType mod,
- gchar **old_object,
- gchar **object,
- GError **error);
-void e_cal_backend_sync_get_attachment_list (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *uid,
- const gchar *rid,
- GSList **attachments,
- GError **error);
-
-void e_cal_backend_sync_discard_alarm (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *uid,
- const gchar *auid,
- GError **error);
-
-void e_cal_backend_sync_receive_objects (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *calobj,
- GError **error);
-void e_cal_backend_sync_send_objects (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *calobj,
- GList **users,
- gchar **modified_calobj,
- GError **error);
-void e_cal_backend_sync_get_default_object (ECalBackendSync *backend,
- EDataCal *cal,
- gchar **object,
- GError **error);
-
-void e_cal_backend_sync_get_object (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *uid,
- const gchar *rid,
- gchar **object,
- GError **error);
-
-void e_cal_backend_sync_get_object_list (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *sexp,
- GList **objects,
- GError **error);
-
-void e_cal_backend_sync_get_timezone (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *tzid,
- gchar **object,
- GError **error);
-void e_cal_backend_sync_add_timezone (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *tzobj,
- GError **error);
-void e_cal_backend_sync_set_default_zone (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *tzobj,
- GError **error);
-
-void e_cal_backend_sync_get_changes (ECalBackendSync *backend,
- EDataCal *cal,
- const gchar *change_id,
- GList **adds,
- GList **modifies,
- GList **deletes,
- GError **error);
-void e_cal_backend_sync_get_free_busy (ECalBackendSync *backend,
- EDataCal *cal,
- GList *users,
- time_t start,
- time_t end,
- GList **freebusy,
- GError **error);
+GType e_cal_backend_sync_get_type (void);
+
+void e_cal_backend_sync_set_lock (ECalBackendSync *backend, gboolean lock);
+
+void e_cal_backend_sync_open (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, gboolean only_if_exists, GError **error);
+void e_cal_backend_sync_remove (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **error);
+void e_cal_backend_sync_refresh (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **error);
+gboolean e_cal_backend_sync_get_backend_property(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, gchar **prop_value, GError **error);
+gboolean e_cal_backend_sync_set_backend_property(ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value, GError **error);
+void e_cal_backend_sync_get_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, gchar **calobj, GError **error);
+void e_cal_backend_sync_get_object_list (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *sexp, GSList **calobjs, GError **error);
+void e_cal_backend_sync_get_free_busy (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const GSList *users, time_t start, time_t end, GSList **freebusyobjs, GError **error);
+void e_cal_backend_sync_create_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, gchar **uid, gchar **new_object, GError **error);
+void e_cal_backend_sync_modify_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, CalObjModType mod, gchar **old_object, gchar **new_object, GError **error);
+void e_cal_backend_sync_remove_object (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, CalObjModType mod, gchar **old_object, gchar **new_object, GError **error);
+void e_cal_backend_sync_receive_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GError **error);
+void e_cal_backend_sync_send_objects (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GSList **users, gchar **modified_calobj, GError **error);
+void e_cal_backend_sync_get_attachment_uris (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, GSList **attachments, GError **error);
+void e_cal_backend_sync_discard_alarm (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const gchar *rid, const gchar *auid, GError **error);
+void e_cal_backend_sync_get_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzid, gchar **tzobject, GError **error);
+void e_cal_backend_sync_add_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobject, GError **error);
+
+void e_cal_backend_sync_authenticate_user (ECalBackendSync *backend, GCancellable *cancellable, ECredentials *credentials, GError **error);
G_END_DECLS
diff --git a/calendar/libedata-cal/e-cal-backend.c b/calendar/libedata-cal/e-cal-backend.c
index 5082ab3..a65051f 100644
--- a/calendar/libedata-cal/e-cal-backend.c
+++ b/calendar/libedata-cal/e-cal-backend.c
@@ -22,47 +22,41 @@
*/
#include <config.h>
-#include <libxml/parser.h>
-#include <libxml/parserInternals.h>
-#include <libxml/xmlmemory.h>
+
+#include <glib/gi18n-lib.h>
#include <libedataserver/e-data-server-util.h>
#include "e-cal-backend.h"
#include "e-cal-backend-cache.h"
-/* For convenience */
-#define CLASS(backend) (E_CAL_BACKEND_GET_CLASS(backend))
-
#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
+#define EDC_OPENING_ERROR e_data_cal_create_error (Busy, _("Cannot process, calendar backend is opening"))
/* Private part of the CalBackend structure */
struct _ECalBackendPrivate {
/* The source for this backend */
ESource *source;
+ /* The kind of components for this backend */
+ icalcomponent_kind kind;
+
+ gboolean opening, opened, readonly, removed, online;
/* URI, from source. This is cached, since we return const. */
gchar *uri;
gchar *cache_dir;
- /* The kind of components for this backend */
- icalcomponent_kind kind;
-
/* List of Cal objects */
GMutex *clients_mutex;
- GList *clients;
+ GSList *clients;
- GMutex *queries_mutex;
- EList *queries;
+ GMutex *views_mutex;
+ GSList *views;
/* ECalBackend to pass notifications on to */
ECalBackend *notification_proxy;
- /* used when notifying clients about progress of some operation,
- * we do not send multiple notifications with the same percent
- * value */
- gint last_percent_notified;
};
/* Property IDs */
@@ -192,6 +186,40 @@ cal_backend_set_kind (ECalBackend *backend,
}
static void
+cal_backend_get_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (prop_name != NULL);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_OPENED)) {
+ e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_is_opened (backend) ? "TRUE" : "FALSE");
+ } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_OPENING)) {
+ e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_is_opening (backend) ? "TRUE" : "FALSE");
+ } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_ONLINE)) {
+ e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_is_online (backend) ? "TRUE" : "FALSE");
+ } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_READONLY)) {
+ e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_is_readonly (backend) ? "TRUE" : "FALSE");
+ } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CACHE_DIR)) {
+ e_data_cal_respond_get_backend_property (cal, opid, NULL, e_cal_backend_get_cache_dir (backend));
+ } else {
+ e_data_cal_respond_get_backend_property (cal, opid, e_data_cal_create_error_fmt (NotSupported, _("Unknown calendar property '%s'"), prop_name), NULL);
+ }
+}
+
+static void
+cal_backend_set_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (prop_name != NULL);
+
+ e_data_cal_respond_set_backend_property (cal, opid, e_data_cal_create_error_fmt (NotSupported, _("Cannot change value of calendar property '%s'"), prop_name));
+}
+
+static void
cal_backend_set_property (GObject *object,
guint property_id,
const GValue *value,
@@ -264,10 +292,12 @@ cal_backend_finalize (GObject *object)
g_assert (priv->clients == NULL);
- g_object_unref (priv->queries);
+ g_slist_free (priv->views);
+ /* should be NULL, anyway */
+ g_slist_free (priv->clients);
g_mutex_free (priv->clients_mutex);
- g_mutex_free (priv->queries_mutex);
+ g_mutex_free (priv->views_mutex);
g_free (priv->uri);
g_free (priv->cache_dir);
@@ -285,21 +315,26 @@ static void
cal_backend_constructed (GObject *object)
{
cal_backend_set_default_cache_dir (E_CAL_BACKEND (object));
+
+ G_OBJECT_CLASS (e_cal_backend_parent_class)->constructed (object);
}
static void
-e_cal_backend_class_init (ECalBackendClass *class)
+e_cal_backend_class_init (ECalBackendClass *klass)
{
GObjectClass *object_class;
- g_type_class_add_private (class, sizeof (ECalBackendPrivate));
+ g_type_class_add_private (klass, sizeof (ECalBackendPrivate));
- object_class = G_OBJECT_CLASS (class);
+ object_class = G_OBJECT_CLASS (klass);
object_class->set_property = cal_backend_set_property;
object_class->get_property = cal_backend_get_property;
object_class->finalize = cal_backend_finalize;
object_class->constructed = cal_backend_constructed;
+ klass->get_backend_property = cal_backend_get_backend_property;
+ klass->set_backend_property = cal_backend_set_backend_property;
+
g_object_class_install_property (
object_class,
PROP_CACHE_DIR,
@@ -347,7 +382,7 @@ e_cal_backend_class_init (ECalBackendClass *class)
signals[LAST_CLIENT_GONE] = g_signal_new (
"last_client_gone",
- G_TYPE_FROM_CLASS (class),
+ G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ECalBackendClass, last_client_gone),
NULL, NULL,
@@ -364,10 +399,161 @@ e_cal_backend_init (ECalBackend *backend)
backend->priv->clients = NULL;
backend->priv->clients_mutex = g_mutex_new ();
- backend->priv->queries = e_list_new (
- (EListCopyFunc) NULL,
- (EListFreeFunc) NULL, NULL);
- backend->priv->queries_mutex = g_mutex_new ();
+ backend->priv->views = NULL;
+ backend->priv->views_mutex = g_mutex_new ();
+
+ backend->priv->readonly = TRUE;
+ backend->priv->online = FALSE;
+}
+
+/**
+ * e_cal_backend_get_source:
+ * @backend: an #ECalBackend
+ *
+ * Gets the #ESource associated with the given backend.
+ *
+ * Returns: The #ESource for the backend.
+ */
+ESource *
+e_cal_backend_get_source (ECalBackend *backend)
+{
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+
+ return backend->priv->source;
+}
+
+/**
+ * e_cal_backend_get_uri:
+ * @backend: an #ECalBackend
+ *
+ * Queries the URI of a calendar backend, which must already have an open
+ * calendar.
+ *
+ * Returns: The URI where the calendar is stored.
+ **/
+const gchar *
+e_cal_backend_get_uri (ECalBackend *backend)
+{
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+
+ return backend->priv->uri;
+}
+
+/**
+ * e_cal_backend_get_kind:
+ * @backend: an #ECalBackend
+ *
+ * Gets the kind of components the given backend stores.
+ *
+ * Returns: The kind of components for this backend.
+ */
+icalcomponent_kind
+e_cal_backend_get_kind (ECalBackend *backend)
+{
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), ICAL_NO_COMPONENT);
+
+ return backend->priv->kind;
+}
+
+/**
+ * e_cal_backend_is_online:
+ * @backend: an #ECalBackend
+ *
+ * Returns: Whether is backend online.
+ **/
+gboolean
+e_cal_backend_is_online (ECalBackend *backend)
+{
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+
+ return backend->priv->online;
+}
+
+/**
+ * e_cal_backend_is_opened:
+ * @backend: an #ECalBackend
+ *
+ * Checks if @backend's storage has been opened (and
+ * authenticated, if necessary) and the backend itself
+ * is ready for accessing. This property is changed automatically
+ * within call of e_cal_backend_notify_opened().
+ *
+ * Returns: %TRUE if fully opened, %FALSE otherwise.
+ **/
+gboolean
+e_cal_backend_is_opened (ECalBackend *backend)
+{
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+
+ return backend->priv->opened;
+}
+
+/**
+ * e_cal_backend_is_opening::
+ * @backend: an #ECalBackend
+ *
+ * Checks if @backend is processing its opening phase, which
+ * includes everything since the e_cal_backend_open() call,
+ * through authentication, up to e_cal_backend_notify_opened().
+ * This property is managed automatically and the backend deny
+ * every operation except of cancel and authenticate_user while
+ * it is being opening.
+ *
+ * Returns: %TRUE if opening phase is in the effect, %FALSE otherwise.
+ **/
+gboolean
+e_cal_backend_is_opening (ECalBackend *backend)
+{
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+
+ return backend->priv->opening;
+}
+
+/**
+ * e_cal_backend_is_readonly:
+ * @backend: an #ECalBackend
+ *
+ * Returns: Whether is backend read-only. This value is the last used
+ * in a call of e_cal_backend_notify_readonly().
+ **/
+gboolean
+e_cal_backend_is_readonly (ECalBackend *backend)
+{
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+
+ return backend->priv->readonly;
+}
+
+/**
+ * e_cal_backend_is_removed:
+ * @backend: an #ECalBackend
+ *
+ * Checks if @backend has been removed from its physical storage.
+ *
+ * Returns: %TRUE if @backend has been removed, %FALSE otherwise.
+ **/
+gboolean
+e_cal_backend_is_removed (ECalBackend *backend)
+{
+ g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
+
+ return backend->priv->removed;
+}
+
+/**
+ * e_cal_backend_set_is_removed:
+ * @backend: an #ECalBackend
+ * @is_removed: A flag indicating whether the backend's storage was removed
+ *
+ * Sets the flag indicating whether @backend was removed to @is_removed.
+ * Meant to be used by backend implementations.
+ **/
+void
+e_cal_backend_set_is_removed (ECalBackend *backend, gboolean is_removed)
+{
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+
+ backend->priv->removed = is_removed;
}
/**
@@ -415,52 +601,60 @@ e_cal_backend_set_cache_dir (ECalBackend *backend,
}
/**
- * e_cal_backend_get_kind:
- * @backend: an #ECalBackend
- *
- * Gets the kind of components the given backend stores.
- *
- * Returns: The kind of components for this backend.
- */
-icalcomponent_kind
-e_cal_backend_get_kind (ECalBackend *backend)
-{
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), ICAL_NO_COMPONENT);
-
- return backend->priv->kind;
-}
-
-/**
- * e_cal_backend_get_source:
+ * e_cal_backend_get_backend_property:
* @backend: an #ECalBackend
- *
- * Gets the #ESource associated with the given backend.
- *
- * Returns: The #ESource for the backend.
- */
-ESource *
-e_cal_backend_get_source (ECalBackend *backend)
+ * @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @prop_name: property name to get value of; cannot be NULL
+ *
+ * Calls the get_backend_property method on the given backend.
+ * This might be finished with e_data_cal_respond_get_backend_property().
+ * Default implementation takes care of common properties and returns
+ * an 'unsupported' error for any unknown properties. The subclass may
+ * always call this default implementation for properties which fetching
+ * it doesn't overwrite.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_backend_get_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name)
{
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (prop_name != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_backend_property != NULL);
- return backend->priv->source;
+ (* E_CAL_BACKEND_GET_CLASS (backend)->get_backend_property) (backend, cal, opid, cancellable, prop_name);
}
/**
- * e_cal_backend_get_uri:
+ * e_cal_backend_set_backend_property:
* @backend: an #ECalBackend
- *
- * Queries the URI of a calendar backend, which must already have an open
- * calendar.
- *
- * Returns: The URI where the calendar is stored.
+ * @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @prop_name: property name to change; cannot be NULL
+ * @prop_value: value to set to @prop_name; cannot be NULL
+ *
+ * Calls the set_backend_property method on the given backend.
+ * This might be finished with e_data_cal_respond_set_backend_property().
+ * Default implementation simply returns an 'unsupported' error.
+ * The subclass may always call this default implementation for properties
+ * which fetching it doesn't overwrite.
+ *
+ * Since: 3.2
**/
-const gchar *
-e_cal_backend_get_uri (ECalBackend *backend)
+void
+e_cal_backend_set_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value)
{
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (prop_name != NULL);
+ g_return_if_fail (prop_value != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->set_backend_property != NULL);
- return backend->priv->uri;
+ (* E_CAL_BACKEND_GET_CLASS (backend)->set_backend_property) (backend, cal, opid, cancellable, prop_name, prop_value);
}
static void
@@ -493,7 +687,7 @@ e_cal_backend_add_client (ECalBackend *backend, EDataCal *cal)
g_object_weak_ref (G_OBJECT (cal), cal_destroy_cb, backend);
g_mutex_lock (priv->clients_mutex);
- priv->clients = g_list_append (priv->clients, cal);
+ priv->clients = g_slist_append (priv->clients, cal);
g_mutex_unlock (priv->clients_mutex);
}
@@ -517,7 +711,7 @@ e_cal_backend_remove_client_private (ECalBackend *backend, EDataCal *cal, gboole
/* Disconnect */
g_mutex_lock (priv->clients_mutex);
- priv->clients = g_list_remove (priv->clients, cal);
+ priv->clients = g_slist_remove (priv->clients, cal);
g_mutex_unlock (priv->clients_mutex);
/* When all clients go away, notify the parent factory about it so that
@@ -541,773 +735,598 @@ e_cal_backend_remove_client (ECalBackend *backend, EDataCal *cal)
}
/**
- * e_cal_backend_add_query:
+ * e_cal_backend_add_view:
* @backend: an #ECalBackend
- * @query: An #EDataCalView object.
+ * @view: An #EDataCalView object.
*
- * Adds a query to the list of live queries being run by the given backend.
- * Doing so means that any listener on the query will get notified of any
- * change that affect the live query.
+ * Adds a view to the list of live views being run by the given backend.
+ * Doing so means that any listener on the view will get notified of any
+ * change that affect the live view.
*/
void
-e_cal_backend_add_query (ECalBackend *backend, EDataCalView *query)
+e_cal_backend_add_view (ECalBackend *backend, EDataCalView *view)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_mutex_lock (backend->priv->queries_mutex);
-
- e_list_append (backend->priv->queries, query);
-
- g_mutex_unlock (backend->priv->queries_mutex);
-}
+ g_mutex_lock (backend->priv->views_mutex);
-/**
- * e_cal_backend_get_queries:
- * @backend: an #ECalBackend
- *
- * Gets the list of live queries being run on the given backend.
- *
- * Returns: The list of live queries.
- */
-EList *
-e_cal_backend_get_queries (ECalBackend *backend)
-{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
+ backend->priv->views = g_slist_append (backend->priv->views, view);
- return backend->priv->queries;
+ g_mutex_unlock (backend->priv->views_mutex);
}
/**
- * e_cal_backend_remove_query
+ * e_cal_backend_remove_view
* @backend: an #ECalBackend
- * @query: An #EDataCalView object, previously added with @ref e_cal_backend_add_query.
+ * @view: An #EDataCalView object, previously added with @ref e_cal_backend_add_view.
*
- * Removes query from the list of live queries for the backend.
+ * Removes view from the list of live views for the backend.
*
* Since: 2.24
**/
void
-e_cal_backend_remove_query (ECalBackend *backend, EDataCalView *query)
+e_cal_backend_remove_view (ECalBackend *backend, EDataCalView *view)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_mutex_lock (backend->priv->queries_mutex);
+ g_mutex_lock (backend->priv->views_mutex);
- e_list_remove (backend->priv->queries, query);
+ backend->priv->views = g_slist_remove (backend->priv->views, view);
- g_mutex_unlock (backend->priv->queries_mutex);
+ g_mutex_unlock (backend->priv->views_mutex);
}
/**
- * e_cal_backend_get_cal_address:
+ * e_cal_backend_foreach_view:
* @backend: an #ECalBackend
+ * @callback: callback to call
+ * @user_data: user_data passed into the @callback
*
- * Queries the cal address associated with a calendar backend, which
- * must already have an open calendar.
+ * Calls @callback for each known calendar view of this @backend.
+ * @callback returns %FALSE to stop further processing.
**/
void
-e_cal_backend_get_cal_address (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+e_cal_backend_foreach_view (ECalBackend *backend, gboolean (* callback) (EDataCalView *view, gpointer user_data), gpointer user_data)
{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
-
- g_assert (CLASS (backend)->get_cal_address != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->get_cal_address) (backend, cal, context);
+ const GSList *views;
+ EDataCalView *view;
+ gboolean stop = FALSE;
- g_object_unref (backend);
-}
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (callback != NULL);
-void
-e_cal_backend_notify_readonly (ECalBackend *backend, gboolean read_only)
-{
- ECalBackendPrivate *priv;
- GList *l;
+ g_mutex_lock (backend->priv->views_mutex);
- priv = backend->priv;
+ for (views = backend->priv->views; views && !stop; views = views->next) {
+ view = E_DATA_CAL_VIEW (views->data);
- if (priv->notification_proxy) {
- e_cal_backend_notify_readonly (priv->notification_proxy, read_only);
- return;
+ g_object_ref (view);
+ stop = !callback (view, user_data);
+ g_object_unref (view);
}
- for (l = priv->clients; l; l = l->next)
- e_data_cal_notify_read_only (l->data, NULL /* Success */, read_only);
-}
-
-void
-e_cal_backend_notify_cal_address (ECalBackend *backend, EServerMethodContext context, gchar *address)
-{
- ECalBackendPrivate *priv;
- GList *l;
-
- priv = backend->priv;
- for (l = priv->clients; l; l = l->next)
- e_data_cal_notify_cal_address (l->data, context, NULL /* Success */, address);
+ g_mutex_unlock (backend->priv->views_mutex);
}
/**
- * e_cal_backend_get_alarm_email_address:
+ * e_cal_backend_set_notification_proxy:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
+ * @proxy: The calendar backend to act as notification proxy.
*
- * Calls the get_alarm_email_address method on the given backend.
+ * Sets the backend that will act as notification proxy for the given backend.
*/
void
-e_cal_backend_get_alarm_email_address (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+e_cal_backend_set_notification_proxy (ECalBackend *backend, ECalBackend *proxy)
{
- g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_assert (CLASS (backend)->get_alarm_email_address != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->get_alarm_email_address) (backend, cal, context);
-
- g_object_unref (backend);
+ backend->priv->notification_proxy = proxy;
}
/**
- *e_cal_backend_get_alarm_email_address:
- * @backend: an #ECalBackend
- * @cal: an #EDataCal
+ * e_cal_backend_set_online:
+ * @backend: A calendar backend
+ * @is_online: Whether is online
*
- * Calls the get_ldap_attribute method of the given backend.
+ * Sets the online mode of the calendar
*/
void
-e_cal_backend_get_ldap_attribute (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+e_cal_backend_set_online (ECalBackend *backend, gboolean is_online)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->set_online != NULL);
- g_assert (CLASS (backend)->get_ldap_attribute != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->get_ldap_attribute) (backend, cal, context);
-
- g_object_unref (backend);
+ (* E_CAL_BACKEND_GET_CLASS (backend)->set_online) (backend, is_online);
}
/**
- * e_cal_backend_get_alarm_email_address:
+ * e_cal_backend_open:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @only_if_exists: Whether the calendar should be opened only if it already
+ * exists. If FALSE, a new calendar will be created when the specified @uri
+ * does not exist.
*
- * Calls the get_static_capabilities method on the given backend.
- */
+ * Opens a calendar backend with data from a calendar stored at the specified URI.
+ * This might be finished with e_data_cal_respond_open() or e_cal_backend_respond_opened(),
+ * though the overall opening phase finishes only after call
+ * of e_cal_backend_notify_opened() after which call the backend
+ * is either fully opened (including authentication against (remote)
+ * server/storage) or an error was encountered during this opening phase.
+ * 'opened' and 'opening' properties are updated automatically.
+ * The backend refuses all other operations until the opening phase is finished.
+ *
+ * The e_cal_backend_notify_opened() is called either from this function
+ * or from e_cal_backend_authenticate_user(), or after necessary steps
+ * initiated by these two functions.
+ *
+ * The opening phase usually works like this:
+ * 1) client requests open for the backend
+ * 2) server receives this request and calls e_cal_backend_open() - the opening phase begun
+ * 3) either the backend is opened during this call, and notifies client
+ * with e_cal_backend_notify_opened() about that. This is usually
+ * for local backends; their opening phase is finished
+ * 4) or the backend requires authentication, thus it notifies client
+ * about that with e_cal_backend_notify_auth_required() and is
+ * waiting for credentials, which will be received from client
+ * by e_cal_backend_authenticate_user() call. Backend's opening
+ * phase is still running in this case, thus it doesn't call
+ * e_cal_backend_notify_opened() within e_cal_backend_open() call.
+ * 5) when backend receives credentials in e_cal_backend_authenticate_user()
+ * then it tries to authenticate against a server/storage with them
+ * and only after it knows result of the authentication, whether user
+ * was or wasn't authenticated, it notifies client with the result
+ * by e_cal_backend_notify_opened() and it's opening phase is
+ * finished now. If there was no error returned then the backend is
+ * considered opened, otherwise it's considered closed. Use AuthenticationFailed
+ * error when the given credentials were rejected by the server/store, which
+ * will result in a re-prompt on the client side, otherwise use AuthenticationRequired
+ * if there was anything wrong with the given credentials. Set error's
+ * message to a reason for a re-prompt, it'll be shown to a user.
+ * 6) client checks error returned from e_cal_backend_notify_opened() and
+ * reprompts for a password if it was AuthenticationFailed. Otherwise
+ * considers backend opened based on the error presence (no error means success).
+ *
+ * In any case, the call of e_cal_backend_open() should be always finished
+ * with e_data_cal_respond_open(), which has no influence on the opening phase,
+ * or alternatively with e_cal_backend_respond_opened(). Never use authentication
+ * errors in e_data_cal_respond_open() to notify the client the authentication is
+ * required, there is e_cal_backend_notify_auth_required() for this.
+ **/
void
-e_cal_backend_get_static_capabilities (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+e_cal_backend_open (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, gboolean only_if_exists)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->open != NULL);
+
+ g_mutex_lock (backend->priv->clients_mutex);
+
+ if (e_cal_backend_is_opened (backend)) {
+ g_mutex_unlock (backend->priv->clients_mutex);
- g_assert (CLASS (backend)->get_static_capabilities != NULL);
+ e_data_cal_report_readonly (cal, backend->priv->readonly);
+ e_data_cal_report_online (cal, backend->priv->online);
- g_object_ref (backend);
+ e_cal_backend_respond_opened (backend, cal, opid, NULL);
+ } else if (e_cal_backend_is_opening (backend)) {
+ g_mutex_unlock (backend->priv->clients_mutex);
- (* CLASS (backend)->get_static_capabilities) (backend, cal, context);
+ e_data_cal_respond_open (cal, opid, EDC_OPENING_ERROR);
+ } else {
+ backend->priv->opening = TRUE;
+ g_mutex_unlock (backend->priv->clients_mutex);
- g_object_unref (backend);
+ (* E_CAL_BACKEND_GET_CLASS (backend)->open) (backend, cal, opid, cancellable, only_if_exists);
+ }
}
/**
- * e_cal_backend_open:
+ * e_cal_backend_authenticate_user:
* @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @only_if_exists: Whether the calendar should be opened only if it already
- * exists. If FALSE, a new calendar will be created when the specified @uri
- * does not exist.
- * @username: User name to use for authentication (if needed).
- * @password: Password for @username.
- *
- * Opens a calendar backend with data from a calendar stored at the specified
- * URI.
- */
+ * @cancellable: a #GCancellable for the operation
+ * @credentials: #ECredentials to use for authentication
+ *
+ * Notifies @backend about @credentials provided by user to use
+ * for authentication. This notification is usually called during
+ * opening phase as a response to e_cal_backend_notify_auth_required()
+ * on the client side and it results in setting property 'opening' to %TRUE
+ * unless the backend is already opened. This function finishes opening
+ * phase, thus it should be finished with e_cal_backend_notify_opened().
+ *
+ * See information at e_cal_backend_open() for more details
+ * how the opening phase works.
+ **/
void
-e_cal_backend_open (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, gboolean only_if_exists,
- const gchar *username, const gchar *password)
+e_cal_backend_authenticate_user (ECalBackend *backend,
+ GCancellable *cancellable,
+ ECredentials *credentials)
{
- g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (credentials != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->authenticate_user);
- g_assert (CLASS (backend)->open != NULL);
-
- g_object_ref (backend);
+ if (!e_cal_backend_is_opened (backend))
+ backend->priv->opening = TRUE;
- (* CLASS (backend)->open) (backend, cal, context, only_if_exists, username, password);
-
- g_object_unref (backend);
+ (* E_CAL_BACKEND_GET_CLASS (backend)->authenticate_user) (backend, cancellable, credentials);
}
/**
- * e_cal_backend_refresh:
- * @backend: an #ECalBackend
- * @cal: an #EDataCal
- *
- * Refreshes the calendar being accessed by the given backend.
- *
- * Since: 2.30
- */
-void
-e_cal_backend_refresh (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
-{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
-
- g_assert (CLASS (backend)->refresh != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->refresh) (backend, cal, context);
-
- g_object_unref (backend);
-}
-
-/**
- * e_cal_backend_remove:
+ * e_cal_backend_remove:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
*
* Removes the calendar being accessed by the given backend.
- */
+ * This might be finished with e_data_cal_respond_remove().
+ **/
void
-e_cal_backend_remove (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+e_cal_backend_remove (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->remove != NULL);
- g_assert (CLASS (backend)->remove != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->remove) (backend, cal, context);
-
- g_object_unref (backend);
-}
-
-/**
- * e_cal_backend_is_loaded:
- * @backend: an #ECalBackend
- *
- * Queries whether a calendar backend has been loaded yet.
- *
- * Returns: TRUE if the backend has been loaded with data, FALSE
- * otherwise.
- */
-gboolean
-e_cal_backend_is_loaded (ECalBackend *backend)
-{
- gboolean result;
-
- g_return_val_if_fail (backend != NULL, FALSE);
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
-
- g_assert (CLASS (backend)->is_loaded != NULL);
-
- g_object_ref (backend);
-
- result = (* CLASS (backend)->is_loaded) (backend);
-
- g_object_unref (backend);
-
- return result;
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_remove (cal, opid, EDC_OPENING_ERROR);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->remove) (backend, cal, opid, cancellable);
}
/**
- * e_cal_backend_is_read_only
+ * e_cal_backend_refresh:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
*
- * Queries whether a calendar backend is read only or not.
- *
- */
-void
-e_cal_backend_is_read_only (ECalBackend *backend, EDataCal *cal)
-{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
-
- g_assert (CLASS (backend)->is_read_only != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->is_read_only) (backend, cal);
-
- g_object_unref (backend);
-}
-
-/**
- * e_cal_backend_start_query:
- * @backend: an #ECalBackend
- * @query: The query to be started.
- *
- * Starts a new live query on the given backend.
- */
-void
-e_cal_backend_start_query (ECalBackend *backend, EDataCalView *query)
-{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
-
- g_assert (CLASS (backend)->start_query != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->start_query) (backend, query);
-
- g_object_unref (backend);
-}
-
-/**
- * e_cal_backend_get_mode:
- * @backend: an #ECalBackend
- *
- * Queries whether a calendar backend is connected remotely.
+ * Refreshes the calendar being accessed by the given backend.
+ * This might be finished with e_data_cal_respond_refresh(),
+ * and it might be called as soon as possible; it doesn't mean
+ * that the refreshing is done after calling that, the backend
+ * is only notifying client whether it started the refresh process
+ * or not.
*
- * Returns: The current mode the calendar is in
+ * Since: 2.30
**/
-CalMode
-e_cal_backend_get_mode (ECalBackend *backend)
-{
- CalMode result;
-
- g_return_val_if_fail (backend != NULL, FALSE);
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), FALSE);
-
- g_assert (CLASS (backend)->get_mode != NULL);
-
- g_object_ref (backend);
-
- result = (* CLASS (backend)->get_mode) (backend);
-
- g_object_unref (backend);
-
- return result;
-}
-
-/**
- * e_cal_backend_set_mode:
- * @backend: A calendar backend
- * @mode: Mode to change to
- *
- * Sets the mode of the calendar
- */
-void
-e_cal_backend_set_mode (ECalBackend *backend, CalMode mode)
-{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
-
- g_assert (CLASS (backend)->set_mode != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->set_mode) (backend, mode);
-
- g_object_unref (backend);
-}
-
-/**
- * e_cal_backend_get_default_object:
- * @backend: an #ECalBackend
- * @cal: an #EDataCal
- *
- * Calls the get_default_object method on the given backend.
- */
void
-e_cal_backend_get_default_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context)
+e_cal_backend_refresh (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_assert (CLASS (backend)->get_default_object != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->get_default_object) (backend, cal, context);
-
- g_object_unref (backend);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_refresh (cal, opid, EDC_OPENING_ERROR);
+ else if (!E_CAL_BACKEND_GET_CLASS (backend)->refresh)
+ e_data_cal_respond_refresh (cal, opid, EDC_ERROR (UnsupportedMethod));
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->refresh) (backend, cal, opid, cancellable);
}
/**
* e_cal_backend_get_object:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @uid: Unique identifier for a calendar object.
* @rid: ID for the object's recurrence to get.
*
* Queries a calendar backend for a calendar object based on its unique
* identifier and its recurrence ID (if a recurrent appointment).
- */
+ * This might be finished with e_data_cal_respond_get_object().
+ **/
void
-e_cal_backend_get_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid)
+e_cal_backend_get_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (uid != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_object != NULL);
- g_assert (CLASS (backend)->get_object != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->get_object) (backend, cal, context, uid, rid);
-
- g_object_unref (backend);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_get_object (cal, opid, EDC_OPENING_ERROR, NULL);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->get_object) (backend, cal, opid, cancellable, uid, rid);
}
/**
* e_cal_backend_get_object_list:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @sexp: Expression to search for.
*
* Calls the get_object_list method on the given backend.
- */
-void
-e_cal_backend_get_object_list (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *sexp)
-{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
-
- g_assert (CLASS (backend)->get_object_list != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->get_object_list) (backend, cal, context, sexp);
-
- g_object_unref (backend);
-}
-
-/**
- * e_cal_backend_get_attachment_list:
- * @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @uid: Unique identifier for a calendar object.
- * @rid: ID for the object's recurrence to get.
- *
- * Queries a calendar backend for attachments present in a calendar object based
- * on its unique identifier and its recurrence ID (if a recurrent appointment).
- */
+ * This might be finished with e_data_cal_respond_get_object_list().
+ **/
void
-e_cal_backend_get_attachment_list (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid)
+e_cal_backend_get_object_list (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *sexp)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (uid != NULL);
-
- g_assert (CLASS (backend)->get_object != NULL);
-
- g_object_ref (backend);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_object_list != NULL);
- (* CLASS (backend)->get_attachment_list) (backend, cal, context, uid, rid);
-
- g_object_unref (backend);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_get_object_list (cal, opid, EDC_OPENING_ERROR, NULL);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->get_object_list) (backend, cal, opid, cancellable, sexp);
}
/**
* e_cal_backend_get_free_busy:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @users: List of users to get free/busy information for.
* @start: Start time for query.
* @end: End time for query.
*
- * Gets a free/busy object for the given time interval
- */
+ * Gets a free/busy object for the given time interval. Client side is
+ * notified about free/busy objects throug e_data_cal_report_free_busy_data().
+ * This might be finished with e_data_cal_respond_get_free_busy().
+ **/
void
-e_cal_backend_get_free_busy (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, GList *users, time_t start, time_t end)
+e_cal_backend_get_free_busy (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const GSList *users, time_t start, time_t end)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (start != -1 && end != -1);
g_return_if_fail (start <= end);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_free_busy != NULL);
- g_assert (CLASS (backend)->get_free_busy != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->get_free_busy) (backend, cal, context, users, start, end);
-
- g_object_unref (backend);
-}
-
-/**
- * e_cal_backend_get_changes:
- * @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @change_id: A unique uid for the callers change list
- *
- * Builds a sequence of objects and the type of change that occurred on them since
- * the last time the give change_id was seen
- */
-void
-e_cal_backend_get_changes (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *change_id)
-{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (change_id != NULL);
-
- g_assert (CLASS (backend)->get_changes != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->get_changes) (backend, cal, context, change_id);
-
- g_object_unref (backend);
-}
-
-/**
- * e_cal_backend_discard_alarm
- * @backend: an #ECalBackend
- * @cal: an #EDataCal
- * @uid: UID of the component to discard the alarm from.
- * @auid: Alarm ID.
- *
- * Discards an alarm from the given component. This allows the specific backend
- * to do whatever is needed to really discard the alarm.
- */
-void
-e_cal_backend_discard_alarm (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *auid)
-{
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (uid != NULL);
- g_return_if_fail (auid != NULL);
-
- g_assert (CLASS (backend)->discard_alarm != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->discard_alarm) (backend, cal, context, uid, auid);
-
- g_object_unref (backend);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_get_free_busy (cal, opid, EDC_OPENING_ERROR);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->get_free_busy) (backend, cal, opid, cancellable, users, start, end);
}
/**
* e_cal_backend_create_object:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @calobj: The object to create.
*
* Calls the create_object method on the given backend.
- */
+ * This might be finished with e_data_cal_respond_create_object().
+ **/
void
-e_cal_backend_create_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
+e_cal_backend_create_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (calobj != NULL);
- g_object_ref (backend);
-
- if (CLASS (backend)->create_object)
- (* CLASS (backend)->create_object) (backend, cal, context, calobj);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_create_object (cal, opid, EDC_OPENING_ERROR, NULL, NULL);
+ else if (E_CAL_BACKEND_GET_CLASS (backend)->create_object)
+ (* E_CAL_BACKEND_GET_CLASS (backend)->create_object) (backend, cal, opid, cancellable, calobj);
else
- e_data_cal_notify_object_created (cal, context, EDC_ERROR (UnsupportedMethod), NULL, NULL);
-
- g_object_unref (backend);
+ e_data_cal_respond_create_object (cal, opid, EDC_ERROR (UnsupportedMethod), NULL, NULL);
}
/**
* e_cal_backend_modify_object:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @calobj: Object to be modified.
* @mod: Type of modification.
*
* Calls the modify_object method on the given backend.
- */
+ * This might be finished with e_data_cal_respond_modify_object().
+ **/
void
-e_cal_backend_modify_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj, CalObjModType mod)
+e_cal_backend_modify_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj, CalObjModType mod)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (calobj != NULL);
- g_object_ref (backend);
-
- if (CLASS (backend)->modify_object)
- (* CLASS (backend)->modify_object) (backend, cal, context, calobj, mod);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_modify_object (cal, opid, EDC_OPENING_ERROR, NULL, NULL);
+ else if (E_CAL_BACKEND_GET_CLASS (backend)->modify_object)
+ (* E_CAL_BACKEND_GET_CLASS (backend)->modify_object) (backend, cal, opid, cancellable, calobj, mod);
else
- e_data_cal_notify_object_removed (cal, context, EDC_ERROR (UnsupportedMethod), NULL, NULL, NULL);
-
- g_object_unref (backend);
+ e_data_cal_respond_modify_object (cal, opid, EDC_ERROR (UnsupportedMethod), NULL, NULL);
}
/**
* e_cal_backend_remove_object:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @uid: Unique identifier of the object to remove.
* @rid: A recurrence ID.
* @mod: Type of removal.
*
* Removes an object in a calendar backend. The backend will notify all of its
* clients about the change.
- */
+ * This might be finished with e_data_cal_respond_remove_object().
+ **/
void
-e_cal_backend_remove_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid, CalObjModType mod)
+e_cal_backend_remove_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid, CalObjModType mod)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (uid != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->remove_object != NULL);
- g_assert (CLASS (backend)->remove_object != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->remove_object) (backend, cal, context, uid, rid, mod);
-
- g_object_unref (backend);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_remove_object (cal, opid, EDC_OPENING_ERROR, NULL, NULL, NULL);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->remove_object) (backend, cal, opid, cancellable, uid, rid, mod);
}
/**
* e_cal_backend_receive_objects:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @calobj: iCalendar object.
*
* Calls the receive_objects method on the given backend.
- */
+ * This might be finished with e_data_cal_respond_receive_objects().
+ **/
void
-e_cal_backend_receive_objects (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
+e_cal_backend_receive_objects (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (calobj != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->receive_objects != NULL);
- g_assert (CLASS (backend)->receive_objects != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->receive_objects) (backend, cal, context, calobj);
-
- g_object_unref (backend);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_receive_objects (cal, opid, EDC_OPENING_ERROR);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->receive_objects) (backend, cal, opid, cancellable, calobj);
}
/**
* e_cal_backend_send_objects:
* @backend: an #ECalBackend
* @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
* @calobj: iCalendar object to be sent.
*
* Calls the send_objects method on the given backend.
- */
+ * This might be finished with e_data_cal_respond_send_objects().
+ **/
void
-e_cal_backend_send_objects (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj)
+e_cal_backend_send_objects (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
g_return_if_fail (calobj != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->send_objects != NULL);
- g_assert (CLASS (backend)->send_objects != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->send_objects) (backend, cal, context, calobj);
-
- g_object_unref (backend);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_send_objects (cal, opid, EDC_OPENING_ERROR, NULL, NULL);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->send_objects) (backend, cal, opid, cancellable, calobj);
}
/**
- * e_cal_backend_get_timezone:
+ * e_cal_backend_get_attachment_uris:
* @backend: an #ECalBackend
* @cal: an #EDataCal
- * @tzid: Unique identifier of a VTIMEZONE object. Note that this must not be
- * NULL.
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @uid: Unique identifier for a calendar object.
+ * @rid: ID for the object's recurrence to get.
*
- * Returns the icaltimezone* corresponding to the TZID, or NULL if the TZID
- * can't be found.
- */
+ * Queries a calendar backend for attachments present in a calendar object based
+ * on its unique identifier and its recurrence ID (if a recurrent appointment).
+ * This might be finished with e_data_cal_respond_get_attachment_uris().
+ **/
void
-e_cal_backend_get_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzid)
+e_cal_backend_get_attachment_uris (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (tzid != NULL);
-
- g_assert (CLASS (backend)->get_timezone != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->get_timezone) (backend, cal, context, tzid);
+ g_return_if_fail (uid != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_attachment_uris != NULL);
- g_object_unref (backend);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_get_attachment_uris (cal, opid, EDC_OPENING_ERROR, NULL);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->get_attachment_uris) (backend, cal, opid, cancellable, uid, rid);
}
/**
- * e_cal_backend_set_default_zone:
+ * e_cal_backend_discard_alarm:
* @backend: an #ECalBackend
* @cal: an #EDataCal
- * @tzobj: The timezone object, in a string.
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @uid: Unique identifier for a calendar object.
+ * @rid: ID for the object's recurrence to discard alarm in.
+ * @auid: Unique identifier of the alarm itself.
*
- * Sets the default timezone for the calendar, which is used to resolve
- * DATE and floating DATE-TIME values.
- */
+ * Discards alarm @auid from the object identified by @uid and @rid.
+ * This might be finished with e_data_cal_respond_discard_alarm().
+ * Default implementation of this method returns Not Supported error.
+ **/
void
-e_cal_backend_set_default_zone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzobj)
+e_cal_backend_discard_alarm (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid, const gchar *auid)
{
g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (tzobj != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->set_default_zone) (backend, cal, context, tzobj);
+ g_return_if_fail (uid != NULL);
+ g_return_if_fail (auid != NULL);
- g_object_unref (backend);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_discard_alarm (cal, opid, EDC_OPENING_ERROR);
+ else if (E_CAL_BACKEND_GET_CLASS (backend)->discard_alarm)
+ (* E_CAL_BACKEND_GET_CLASS (backend)->discard_alarm) (backend, cal, opid, cancellable, uid, rid, auid);
+ else
+ e_data_cal_respond_discard_alarm (cal, opid, e_data_cal_create_error (NotSupported, NULL));
}
/**
- * e_cal_backend_add_timezone
+ * e_cal_backend_get_timezone:
* @backend: an #ECalBackend
* @cal: an #EDataCal
- * @tzobj: The timezone object, in a string.
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @tzid: Unique identifier of a VTIMEZONE object. Note that this must not be
+ * NULL.
*
- * Add a timezone object to the given backend.
- */
+ * Returns the icaltimezone* corresponding to the TZID, or NULL if the TZID
+ * can't be found.
+ * This might be finished with e_data_cal_respond_get_timezone().
+ **/
void
-e_cal_backend_add_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzobj)
+e_cal_backend_get_timezone (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *tzid)
{
+ g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (tzobj != NULL);
- g_return_if_fail (CLASS (backend)->add_timezone != NULL);
-
- g_object_ref (backend);
-
- (* CLASS (backend)->add_timezone) (backend, cal, context, tzobj);
+ g_return_if_fail (tzid != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->get_timezone != NULL);
- g_object_unref (backend);
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_get_timezone (cal, opid, EDC_OPENING_ERROR, NULL);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->get_timezone) (backend, cal, opid, cancellable, tzid);
}
/**
- * e_cal_backend_internal_get_default_timezone:
+ * e_cal_backend_add_timezone
* @backend: an #ECalBackend
+ * @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ * @cancellable: a #GCancellable for the operation
+ * @tzobj: The timezone object, in a string.
*
- * Calls the internal_get_default_timezone method on the given backend.
- */
-icaltimezone *
-e_cal_backend_internal_get_default_timezone (ECalBackend *backend)
+ * Add a timezone object to the given backend.
+ * This might be finished with e_data_cal_respond_add_timezone().
+ **/
+void
+e_cal_backend_add_timezone (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *tzobject)
{
- icaltimezone *timezone;
-
- g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
- g_return_val_if_fail (CLASS (backend)->internal_get_default_timezone != NULL, NULL);
-
- g_object_ref (backend);
-
- timezone = (* CLASS (backend)->internal_get_default_timezone) (backend);
-
- g_object_unref (backend);
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (tzobject != NULL);
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->add_timezone != NULL);
- return timezone;
+ if (e_cal_backend_is_opening (backend))
+ e_data_cal_respond_add_timezone (cal, opid, EDC_OPENING_ERROR);
+ else
+ (* E_CAL_BACKEND_GET_CLASS (backend)->add_timezone) (backend, cal, opid, cancellable, tzobject);
}
/**
@@ -1320,38 +1339,59 @@ e_cal_backend_internal_get_default_timezone (ECalBackend *backend)
icaltimezone *
e_cal_backend_internal_get_timezone (ECalBackend *backend, const gchar *tzid)
{
- icaltimezone *timezone;
-
g_return_val_if_fail (E_IS_CAL_BACKEND (backend), NULL);
g_return_val_if_fail (tzid != NULL, NULL);
- g_return_val_if_fail (CLASS (backend)->internal_get_timezone != NULL, NULL);
+ g_return_val_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->internal_get_timezone != NULL, NULL);
- g_object_ref (backend);
-
- timezone = (* CLASS (backend)->internal_get_timezone) (backend, tzid);
+ return (* E_CAL_BACKEND_GET_CLASS (backend)->internal_get_timezone) (backend, tzid);
+}
- g_object_unref (backend);
+/**
+ * e_cal_backend_start_view:
+ * @backend: an #ECalBackend
+ * @view: The view to be started.
+ *
+ * Starts a new live view on the given backend.
+ */
+void
+e_cal_backend_start_view (ECalBackend *backend, EDataCalView *view)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (E_CAL_BACKEND_GET_CLASS (backend)->start_view != NULL);
- return timezone;
+ (* E_CAL_BACKEND_GET_CLASS (backend)->start_view) (backend, view);
}
/**
- * e_cal_backend_set_notification_proxy:
+ * e_cal_backend_stop_view:
* @backend: an #ECalBackend
- * @proxy: The calendar backend to act as notification proxy.
+ * @view: The view to be stopped.
*
- * Sets the backend that will act as notification proxy for the given backend.
+ * Stops a previously started live view on the given backend.
+ *
+ * Since: 3.2
*/
void
-e_cal_backend_set_notification_proxy (ECalBackend *backend, ECalBackend *proxy)
+e_cal_backend_stop_view (ECalBackend *backend, EDataCalView *view)
{
- ECalBackendPrivate *priv;
-
+ g_return_if_fail (backend != NULL);
g_return_if_fail (E_IS_CAL_BACKEND (backend));
- priv = backend->priv;
+ /* backward compatibility, do not force each backend define this function */
+ if (!E_CAL_BACKEND_GET_CLASS (backend)->stop_view)
+ return;
- priv->notification_proxy = proxy;
+ (* E_CAL_BACKEND_GET_CLASS (backend)->stop_view) (backend, view);
+}
+
+static gboolean
+object_created_cb (EDataCalView *view, gpointer calobj)
+{
+ if (e_data_cal_view_object_matches (view, calobj))
+ e_data_cal_view_notify_objects_added_1 (view, calobj);
+
+ return TRUE;
}
/**
@@ -1369,9 +1409,6 @@ void
e_cal_backend_notify_object_created (ECalBackend *backend, const gchar *calobj)
{
ECalBackendPrivate *priv;
- EList *queries;
- EIterator *iter;
- EDataCalView *query;
priv = backend->priv;
@@ -1380,35 +1417,33 @@ e_cal_backend_notify_object_created (ECalBackend *backend, const gchar *calobj)
return;
}
- queries = e_cal_backend_get_queries (backend);
- iter = e_list_get_iterator (queries);
-
- while (e_iterator_is_valid (iter)) {
- query = QUERY (e_iterator_get (iter));
-
- g_object_ref (query);
- if (e_data_cal_view_object_matches (query, calobj))
- e_data_cal_view_notify_objects_added_1 (query, calobj);
- g_object_unref (query);
+ e_cal_backend_foreach_view (backend, object_created_cb, (gpointer) calobj);
+}
- e_iterator_next (iter);
- }
- g_object_unref (iter);
+/**
+ * e_cal_backend_notify_objects_added:
+ *
+ * Since: 2.24
+ **/
+void
+e_cal_backend_notify_objects_added (ECalBackend *backend, EDataCalView *view, const GSList *objects)
+{
+ e_data_cal_view_notify_objects_added (view, objects);
}
static void
-match_query_and_notify (EDataCalView *query, const gchar *old_object, const gchar *object)
+match_view_and_notify (EDataCalView *view, const gchar *old_object, const gchar *object)
{
gboolean old_match = FALSE, new_match = FALSE;
if (old_object)
- old_match = e_data_cal_view_object_matches (query, old_object);
+ old_match = e_data_cal_view_object_matches (view, old_object);
- new_match = e_data_cal_view_object_matches (query, object);
+ new_match = e_data_cal_view_object_matches (view, object);
if (old_match && new_match)
- e_data_cal_view_notify_objects_modified_1 (query, object);
+ e_data_cal_view_notify_objects_modified_1 (view, object);
else if (new_match)
- e_data_cal_view_notify_objects_added_1 (query, object);
+ e_data_cal_view_notify_objects_added_1 (view, object);
else if (old_match) {
ECalComponent *comp = NULL;
@@ -1416,7 +1451,7 @@ match_query_and_notify (EDataCalView *query, const gchar *old_object, const gcha
if (comp) {
ECalComponentId *id = e_cal_component_get_id (comp);
- e_data_cal_view_notify_objects_removed_1 (query, id);
+ e_data_cal_view_notify_objects_removed_1 (view, id);
e_cal_component_free_id (id);
g_object_unref (comp);
@@ -1424,107 +1459,22 @@ match_query_and_notify (EDataCalView *query, const gchar *old_object, const gcha
}
}
-/**
- * e_cal_backend_notify_view_progress_start
- * @backend: an #ECalBackend
- *
- * This methods has to be used before e_cal_backend_notify_view_progress.
- * Sets last notified percent value to 0.
- *
- * Since: 2.24
- **/
-void
-e_cal_backend_notify_view_progress_start (ECalBackend *backend)
-{
- ECalBackendPrivate *priv;
-
- priv = backend->priv;
-
- priv->last_percent_notified = 0;
-}
-
-/**
- * e_cal_backend_notify_view_progress:
- * @backend: an #ECalBackend
- * @message: the UID of the removed object
- * @percent: percentage of the objects loaded in the view
- *
- * Notifies each of the backend's listeners about the view_progress in downloading the items.
- **/
-void
-e_cal_backend_notify_view_progress (ECalBackend *backend, const gchar *message, gint percent)
-{
- ECalBackendPrivate *priv;
- EList *queries;
- EIterator *iter;
- EDataCalView *query;
-
- priv = backend->priv;
-
- if (percent <= priv->last_percent_notified)
- return;
-
- priv->last_percent_notified = percent;
-
- if (priv->notification_proxy) {
- e_cal_backend_notify_view_progress (priv->notification_proxy, message, percent);
- return;
- }
-
- queries = e_cal_backend_get_queries (backend);
- iter = e_list_get_iterator (queries);
-
- while (e_iterator_is_valid (iter)) {
- query = QUERY (e_iterator_get (iter));
-
- g_object_ref (query);
-
- e_data_cal_view_notify_progress (query, message, percent);
-
- g_object_unref (query);
-
- e_iterator_next (iter);
- }
- g_object_unref (iter);
-}
+struct call_data {
+ const gchar *old_object;
+ const gchar *object;
+ const ECalComponentId *id;
+};
-/**
- * e_cal_backend_notify_view_done:
- * @backend: an #ECalBackend
- * @error: returns the error, if any, once the view is fully populated.
- *
- * Notifies each of the backend's listeners about the view_done in downloading the items.
- **/
-void
-e_cal_backend_notify_view_done (ECalBackend *backend, const GError *error)
+static gboolean
+call_match_and_notify (EDataCalView *view, gpointer user_data)
{
- ECalBackendPrivate *priv;
- EList *queries;
- EIterator *iter;
- EDataCalView *query;
-
- priv = backend->priv;
-
- if (priv->notification_proxy) {
- e_cal_backend_notify_view_done (priv->notification_proxy, error);
- return;
- }
-
- queries = e_cal_backend_get_queries (backend);
- iter = e_list_get_iterator (queries);
+ struct call_data *cd = user_data;
- while (e_iterator_is_valid (iter)) {
- query = QUERY (e_iterator_get (iter));
+ g_return_val_if_fail (user_data != NULL, FALSE);
- g_object_ref (query);
+ match_view_and_notify (view, cd->old_object, cd->object);
- e_data_cal_view_notify_done (query, error);
-
- g_object_unref (query);
-
- e_iterator_next (iter);
- }
- g_object_unref (iter);
+ return TRUE;
}
/**
@@ -1540,13 +1490,10 @@ e_cal_backend_notify_view_done (ECalBackend *backend, const GError *error)
* modified by non-EDS clients.
**/
void
-e_cal_backend_notify_object_modified (ECalBackend *backend,
- const gchar *old_object, const gchar *object)
+e_cal_backend_notify_object_modified (ECalBackend *backend, const gchar *old_object, const gchar *object)
{
ECalBackendPrivate *priv;
- EList *queries;
- EIterator *iter;
- EDataCalView *query;
+ struct call_data cd;
priv = backend->priv;
@@ -1555,19 +1502,40 @@ e_cal_backend_notify_object_modified (ECalBackend *backend,
return;
}
- queries = e_cal_backend_get_queries (backend);
- iter = e_list_get_iterator (queries);
+ cd.old_object = old_object;
+ cd.object = object;
+ cd.id = NULL;
- while (e_iterator_is_valid (iter)) {
- query = QUERY (e_iterator_get (iter));
+ e_cal_backend_foreach_view (backend, call_match_and_notify, &cd);
+}
- g_object_ref (query);
- match_query_and_notify (query, old_object, object);
- g_object_unref (query);
+/**
+ * e_cal_backend_notify_objects_modified:
+ *
+ * Since: 2.24
+ **/
+void
+e_cal_backend_notify_objects_modified (ECalBackend *backend, EDataCalView *view, const GSList *objects)
+{
+ e_data_cal_view_notify_objects_modified (view, objects);
+}
- e_iterator_next (iter);
- }
- g_object_unref (iter);
+static gboolean
+object_removed_cb (EDataCalView *view, gpointer user_data)
+{
+ struct call_data *cd = user_data;
+
+ g_return_val_if_fail (user_data != NULL, FALSE);
+
+ if (cd->object == NULL) {
+ /* if object == NULL, it means the object has been completely
+ removed from the backend */
+ if (!cd->old_object || e_data_cal_view_object_matches (view, cd->old_object))
+ e_data_cal_view_notify_objects_removed_1 (view, cd->id);
+ } else
+ match_view_and_notify (view, cd->old_object, cd->object);
+
+ return TRUE;
}
/**
@@ -1590,9 +1558,7 @@ e_cal_backend_notify_object_removed (ECalBackend *backend, const ECalComponentId
const gchar *old_object, const gchar *object)
{
ECalBackendPrivate *priv;
- EList *queries;
- EIterator *iter;
- EDataCalView *query;
+ struct call_data cd;
priv = backend->priv;
@@ -1601,125 +1567,225 @@ e_cal_backend_notify_object_removed (ECalBackend *backend, const ECalComponentId
return;
}
- queries = e_cal_backend_get_queries (backend);
- iter = e_list_get_iterator (queries);
-
- while (e_iterator_is_valid (iter)) {
- query = QUERY (e_iterator_get (iter));
+ cd.old_object = old_object;
+ cd.object = object;
+ cd.id = id;
- g_object_ref (query);
-
- if (object == NULL) {
- /* if object == NULL, it means the object has been completely
- removed from the backend */
- if (!old_object || e_data_cal_view_object_matches (query, old_object))
- e_data_cal_view_notify_objects_removed_1 (query, id);
- } else
- match_query_and_notify (query, old_object, object);
-
- g_object_unref (query);
-
- e_iterator_next (iter);
- }
- g_object_unref (iter);
+ e_cal_backend_foreach_view (backend, object_removed_cb, &cd);
}
/**
- * e_cal_backend_notify_objects_added:
+ * e_cal_backend_notify_objects_removed:
*
* Since: 2.24
**/
void
-e_cal_backend_notify_objects_added (ECalBackend *backend, EDataCalView *query, const GList *objects)
+e_cal_backend_notify_objects_removed (ECalBackend *backend, EDataCalView *view, const GSList *ids)
{
- e_data_cal_view_notify_objects_added (query, objects);
+ e_data_cal_view_notify_objects_removed (view, ids);
}
/**
- * e_cal_backend_notify_objects_removed:
+ * e_cal_backend_notify_error:
+ * @backend: an #ECalBackend
+ * @message: Error message
*
- * Since: 2.24
+ * Notifies each of the backend's listeners about an error
**/
void
-e_cal_backend_notify_objects_removed (ECalBackend *backend, EDataCalView *query, const GList *ids)
+e_cal_backend_notify_error (ECalBackend *backend, const gchar *message)
{
- e_data_cal_view_notify_objects_removed (query, ids);
+ ECalBackendPrivate *priv = backend->priv;
+ GSList *l;
+
+ if (priv->notification_proxy) {
+ e_cal_backend_notify_error (priv->notification_proxy, message);
+ return;
+ }
+
+ g_mutex_lock (priv->clients_mutex);
+
+ for (l = priv->clients; l; l = l->next)
+ e_data_cal_report_error (l->data, message);
+
+ g_mutex_unlock (priv->clients_mutex);
}
/**
- * e_cal_backend_notify_objects_modified:
+ * e_cal_backend_notify_readonly:
+ * @backend: an #ECalBackend
+ * @is_readonly: flag indicating readonly status
*
- * Since: 2.24
+ * Notifies all backend's clients about the current readonly state.
+ * Meant to be used by backend implementations.
**/
void
-e_cal_backend_notify_objects_modified (ECalBackend *backend, EDataCalView *query, const GList *objects)
+e_cal_backend_notify_readonly (ECalBackend *backend, gboolean is_readonly)
{
- e_data_cal_view_notify_objects_modified (query, objects);
+ ECalBackendPrivate *priv;
+ GSList *l;
+
+ priv = backend->priv;
+ priv->readonly = is_readonly;
+
+ if (priv->notification_proxy) {
+ e_cal_backend_notify_readonly (priv->notification_proxy, is_readonly);
+ return;
+ }
+
+ g_mutex_lock (priv->clients_mutex);
+
+ for (l = priv->clients; l; l = l->next)
+ e_data_cal_report_readonly (l->data, is_readonly);
+
+ g_mutex_unlock (priv->clients_mutex);
}
/**
- * e_cal_backend_notify_mode:
+ * e_cal_backend_notify_online:
* @backend: an #ECalBackend
- * @status: Status of the mode set
- * @mode: the current mode
+ * @is_online: flag indicating whether @backend is connected and online
*
- * Notifies each of the backend's listeners about the results of a
- * setMode call.
+ * Notifies clients of @backend's connection status indicated by @is_online.
+ * Meant to be used by backend implementations.
**/
void
-e_cal_backend_notify_mode (ECalBackend *backend,
- EDataCalViewListenerSetModeStatus status,
- EDataCalMode mode)
+e_cal_backend_notify_online (ECalBackend *backend, gboolean is_online)
{
- ECalBackendPrivate *priv = backend->priv;
- GList *l;
+ ECalBackendPrivate *priv;
+ GSList *clients;
+
+ priv = backend->priv;
+ priv->online = is_online;
if (priv->notification_proxy) {
- e_cal_backend_notify_mode (priv->notification_proxy, status, mode);
+ e_cal_backend_notify_online (priv->notification_proxy, is_online);
return;
}
- for (l = priv->clients; l; l = l->next)
- e_data_cal_notify_mode (l->data, status, mode);
+ g_mutex_lock (priv->clients_mutex);
+
+ for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
+ e_data_cal_report_online (E_DATA_CAL (clients->data), is_online);
+
+ g_mutex_unlock (priv->clients_mutex);
}
/**
* e_cal_backend_notify_auth_required:
* @backend: an #ECalBackend
+ * @is_self: Use %TRUE to indicate the authentication is required
+ * for the @backend, otheriwse the authentication is for any
+ * other source. Having @credentials %NULL means @is_self
+ * automatically.
+ * @credentials: an #ECredentials that contains extra information for
+ * a source for which authentication is requested.
+ * This parameter can be NULL to indicate "for this calendar".
+ *
+ * Notifies clients that @backend requires authentication in order to
+ * connect. This function call does not influence 'opening', but
+ * influences 'opened' property, which is set to %FALSE when @is_self
+ * is %TRUE or @credentials is %NULL. Opening phase is finished
+ * by e_cal_backend_notify_opened() if this is requested for @backend.
+ *
+ * See e_cal_backend_open() for a description how the whole opening
+ * phase works.
+ *
+ * Meant to be used by backend implementations.
+ **/
+void
+e_cal_backend_notify_auth_required (ECalBackend *backend, gboolean is_self, const ECredentials *credentials)
+{
+ ECalBackendPrivate *priv;
+ GSList *clients;
+
+ priv = backend->priv;
+
+ if (priv->notification_proxy) {
+ e_cal_backend_notify_auth_required (priv->notification_proxy, is_self, credentials);
+ return;
+ }
+
+ g_mutex_lock (priv->clients_mutex);
+
+ if (is_self || !credentials)
+ priv->opened = FALSE;
+
+ for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
+ e_data_cal_report_auth_required (E_DATA_CAL (clients->data), credentials);
+
+ g_mutex_unlock (priv->clients_mutex);
+}
+
+/**
+ * e_cal_backend_notify_opened:
+ * @backend: an #ECalBackend
+ * @error: a #GError corresponding to the error encountered during
+ * the opening phase. Use %NULL for success. The @error is freed
+ * automatically if not %NULL.
*
- * Notifies each of the backend's listeners that authentication is required to
- * open the calendar.
- */
+ * Notifies clients that @backend finished its opening phase.
+ * See e_cal_backend_open() for more information how the opening
+ * phase works. Calling this function changes 'opening' property,
+ * same as 'opened'. 'opening' is set to %FALSE and the backend
+ * is considered 'opened' only if the @error is %NULL.
+ *
+ * See also: e_cal_backend_respond_opened()
+ *
+ * Note: The @error is freed automatically if not %NULL.
+ *
+ * Meant to be used by backend implementations.
+ **/
void
-e_cal_backend_notify_auth_required (ECalBackend *backend)
+e_cal_backend_notify_opened (ECalBackend *backend, GError *error)
{
- ECalBackendPrivate *priv = backend->priv;
- GList *l;
+ ECalBackendPrivate *priv;
+ GSList *clients;
- for (l = priv->clients; l; l = l->next)
- e_data_cal_notify_auth_required (l->data);
+ priv = backend->priv;
+ g_mutex_lock (priv->clients_mutex);
+
+ priv->opening = FALSE;
+ priv->opened = error == NULL;
+
+ for (clients = priv->clients; clients != NULL; clients = g_slist_next (clients))
+ e_data_cal_report_opened (E_DATA_CAL (clients->data), error);
+
+ g_mutex_unlock (priv->clients_mutex);
+
+ if (error)
+ g_error_free (error);
}
/**
- * e_cal_backend_notify_error:
+ * e_cal_backend_respond_opened:
* @backend: an #ECalBackend
- * @message: Error message
+ * @cal: an #EDataCal
+ * @opid: an operation ID
+ * @error: result error; can be %NULL, if it isn't then it's automatically freed
*
- * Notifies each of the backend's listeners about an error
+ * This is a replacement for e_data_cal_respond_open() for cases where
+ * the finish of 'open' method call also finishes backend opening phase.
+ * This function covers calling of both e_data_cal_respond_open() and
+ * e_cal_backend_notify_opened() with the same @error.
+ *
+ * See e_cal_backend_open() for more details how the opening phase works.
**/
void
-e_cal_backend_notify_error (ECalBackend *backend, const gchar *message)
+e_cal_backend_respond_opened (ECalBackend *backend, EDataCal *cal, guint32 opid, GError *error)
{
- ECalBackendPrivate *priv = backend->priv;
- GList *l;
+ GError *copy = NULL;
- if (priv->notification_proxy) {
- e_cal_backend_notify_error (priv->notification_proxy, message);
- return;
- }
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (E_IS_CAL_BACKEND (backend));
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (opid != 0);
- for (l = priv->clients; l; l = l->next)
- e_data_cal_notify_error (l->data, message);
+ if (error)
+ copy = g_error_copy (error);
+
+ e_data_cal_respond_open (cal, opid, error);
+ e_cal_backend_notify_opened (backend, copy);
}
/**
diff --git a/calendar/libedata-cal/e-cal-backend.h b/calendar/libedata-cal/e-cal-backend.h
index d9fccf8..360c4e4 100644
--- a/calendar/libedata-cal/e-cal-backend.h
+++ b/calendar/libedata-cal/e-cal-backend.h
@@ -23,8 +23,8 @@
#ifndef E_CAL_BACKEND_H
#define E_CAL_BACKEND_H
-#include "libedataserver/e-list.h"
-#include "libedataserver/e-source.h"
+#include <libedataserver/e-credentials.h>
+#include <libedataserver/e-source.h>
#include <libecal/e-cal-util.h>
#include <libecal/e-cal-component.h>
#include "e-data-cal-common.h"
@@ -38,11 +38,20 @@ G_BEGIN_DECLS
#define E_TYPE_CAL_BACKEND (e_cal_backend_get_type ())
#define E_CAL_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CAL_BACKEND, ECalBackend))
-#define E_CAL_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CAL_BACKEND, \
- ECalBackendClass))
+#define E_CAL_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CAL_BACKEND, ECalBackendClass))
#define E_IS_CAL_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CAL_BACKEND))
#define E_IS_CAL_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CAL_BACKEND))
-#define E_CAL_BACKEND_GET_CLASS(obj) (E_CAL_BACKEND_CLASS (G_OBJECT_GET_CLASS (obj)))
+#define E_CAL_BACKEND_GET_CLASS(obj) (E_CAL_BACKEND_CLASS (G_OBJECT_GET_CLASS (obj)))
+
+#define CLIENT_BACKEND_PROPERTY_OPENED "opened"
+#define CLIENT_BACKEND_PROPERTY_OPENING "opening"
+#define CLIENT_BACKEND_PROPERTY_ONLINE "online"
+#define CLIENT_BACKEND_PROPERTY_READONLY "readonly"
+#define CLIENT_BACKEND_PROPERTY_CACHE_DIR "cache-dir"
+#define CLIENT_BACKEND_PROPERTY_CAPABILITIES "capabilities"
+#define CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS "cal-email-address"
+#define CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS "alarm-email-address"
+#define CAL_BACKEND_PROPERTY_DEFAULT_OBJECT "default-object"
struct _ECalBackendCache;
@@ -57,136 +66,106 @@ struct _ECalBackend {
struct _ECalBackendClass {
GObjectClass parent_class;
- /* Notification signals */
- void (* last_client_gone) (ECalBackend *backend);
- void (* cal_added) (ECalBackend *backend, EDataCal *cal);
-
/* Virtual methods */
- gboolean (* is_loaded) (ECalBackend *backend);
- void (* is_read_only) (ECalBackend *backend, EDataCal *cal);
- void (* get_cal_address) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
- void (* get_alarm_email_address) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
- void (* get_ldap_attribute) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
- void (* get_static_capabilities) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
-
- void (* open) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, gboolean only_if_exists, const gchar *username, const gchar *password);
- void (* refresh) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
- void (* remove) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
-
- /* Object related virtual methods */
- void (* create_object) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj);
- void (* modify_object) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj, CalObjModType mod);
- void (* remove_object) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid, CalObjModType mod);
-
- void (* discard_alarm) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *auid);
-
- void (* receive_objects) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj);
- void (* send_objects) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj);
-
- void (* get_default_object) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
- void (* get_object) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid);
- void (* get_object_list) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *sexp);
-
- void (* get_attachment_list) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid);
-
- /* Timezone related virtual methods */
- void (* get_timezone) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzid);
- void (* add_timezone) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *object);
- void (* set_default_zone) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzobj);
+ void (* get_backend_property) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name);
+ void (* set_backend_property) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value);
+
+ void (* open) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, gboolean only_if_exists);
+ void (* remove) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
+ void (* set_online) (ECalBackend *backend, gboolean is_online);
+ void (* authenticate_user) (ECalBackend *backend, GCancellable *cancellable, ECredentials *credentials);
+
+ void (* refresh) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
+ void (* get_object) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid);
+ void (* get_object_list) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *sexp);
+ void (* get_free_busy) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const GSList *users, time_t start, time_t end);
+ void (* create_object) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj);
+ void (* modify_object) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj, CalObjModType mod);
+ void (* remove_object) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid, CalObjModType mod);
+ void (* receive_objects) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj);
+ void (* send_objects) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj);
+ void (* get_attachment_uris) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid);
+ void (* discard_alarm) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid, const gchar *auid);
+ void (* get_timezone) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *tzid);
+ void (* add_timezone) (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *tzobject);
+
+ void (* start_view) (ECalBackend *backend, EDataCalView *view);
+ void (* stop_view) (ECalBackend *backend, EDataCalView *view);
- void (* start_query) (ECalBackend *backend, EDataCalView *query);
-
- /* Mode relate virtual methods */
- CalMode (* get_mode) (ECalBackend *backend);
- void (* set_mode) (ECalBackend *backend, CalMode mode);
-
- void (* get_free_busy) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, GList *users, time_t start, time_t end);
- void (* get_changes) (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *change_id);
+ /* Notification signals */
+ void (* last_client_gone) (ECalBackend *backend);
/* Internal methods for use only in the pcs */
- icaltimezone *(* internal_get_default_timezone) (ECalBackend *backend);
icaltimezone *(* internal_get_timezone) (ECalBackend *backend, const gchar *tzid);
};
-GType e_cal_backend_get_type (void);
-
-ESource *e_cal_backend_get_source (ECalBackend *backend);
-const gchar *e_cal_backend_get_uri (ECalBackend *backend);
-icalcomponent_kind e_cal_backend_get_kind (ECalBackend *backend);
-
-const gchar *e_cal_backend_get_cache_dir (ECalBackend *backend);
-void e_cal_backend_set_cache_dir (ECalBackend *backend, const gchar *cache_dir);
-
-void e_cal_backend_add_client (ECalBackend *backend, EDataCal *cal);
-void e_cal_backend_remove_client (ECalBackend *backend, EDataCal *cal);
-
-void e_cal_backend_add_query (ECalBackend *backend, EDataCalView *query);
-EList *e_cal_backend_get_queries (ECalBackend *backend);
-void e_cal_backend_remove_query (ECalBackend *backend, EDataCalView *query);
-
-void e_cal_backend_is_read_only (ECalBackend *backend, EDataCal *cal);
-void e_cal_backend_get_cal_address (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
-void e_cal_backend_get_alarm_email_address (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
-void e_cal_backend_get_ldap_attribute (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
-void e_cal_backend_get_static_capabilities (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
-
-void e_cal_backend_open (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, gboolean only_if_exists, const gchar *username, const gchar *password);
-void e_cal_backend_refresh (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
-void e_cal_backend_remove (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
-
-void e_cal_backend_create_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj);
-void e_cal_backend_modify_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj, CalObjModType mod);
-void e_cal_backend_remove_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid, CalObjModType mod);
-
-void e_cal_backend_discard_alarm (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *auid);
-
-void e_cal_backend_receive_objects (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj);
-void e_cal_backend_send_objects (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *calobj);
-
-void e_cal_backend_get_default_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context);
-void e_cal_backend_get_object (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid);
-void e_cal_backend_get_object_list (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *sexp);
-void e_cal_backend_get_attachment_list (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *uid, const gchar *rid);
-
-gboolean e_cal_backend_is_loaded (ECalBackend *backend);
-
-void e_cal_backend_start_query (ECalBackend *backend, EDataCalView *query);
-
-CalMode e_cal_backend_get_mode (ECalBackend *backend);
-void e_cal_backend_set_mode (ECalBackend *backend, CalMode mode);
-
-void e_cal_backend_get_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzid);
-void e_cal_backend_add_timezone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *object);
-void e_cal_backend_set_default_zone (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *tzobj);
-
-void e_cal_backend_get_changes (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, const gchar *change_id);
-void e_cal_backend_get_free_busy (ECalBackend *backend, EDataCal *cal, EServerMethodContext context, GList *users, time_t start, time_t end);
-
-icaltimezone* e_cal_backend_internal_get_default_timezone (ECalBackend *backend);
-icaltimezone* e_cal_backend_internal_get_timezone (ECalBackend *backend, const gchar *tzid);
-
-void e_cal_backend_set_notification_proxy (ECalBackend *backend, ECalBackend *proxy);
-void e_cal_backend_notify_object_created (ECalBackend *backend, const gchar *calobj);
-void e_cal_backend_notify_object_modified (ECalBackend *backend, const gchar *old_object, const gchar *object);
-void e_cal_backend_notify_object_removed (ECalBackend *backend, const ECalComponentId *id, const gchar *old_object, const gchar *object);
-
-void e_cal_backend_notify_mode (ECalBackend *backend,
- EDataCalViewListenerSetModeStatus status,
- EDataCalMode mode);
-void e_cal_backend_notify_auth_required (ECalBackend *backend);
-void e_cal_backend_notify_error (ECalBackend *backend, const gchar *message);
-
-void e_cal_backend_notify_view_done (ECalBackend *backend, const GError *error);
-void e_cal_backend_notify_view_progress_start (ECalBackend *backend);
-void e_cal_backend_notify_view_progress (ECalBackend *backend, const gchar *message, gint percent);
-void e_cal_backend_notify_readonly (ECalBackend *backend, gboolean read_only);
-void e_cal_backend_notify_cal_address (ECalBackend *backend, EServerMethodContext context, gchar *address);
-
-void e_cal_backend_notify_objects_added (ECalBackend *backend, EDataCalView *query, const GList *objects);
-void e_cal_backend_notify_objects_removed (ECalBackend *backend, EDataCalView *query, const GList *ids);
-void e_cal_backend_notify_objects_modified (ECalBackend *backend, EDataCalView *query, const GList *objects);
-
-void e_cal_backend_empty_cache (ECalBackend *backend, struct _ECalBackendCache *cache);
+GType e_cal_backend_get_type (void);
+
+ESource * e_cal_backend_get_source (ECalBackend *backend);
+const gchar * e_cal_backend_get_uri (ECalBackend *backend);
+icalcomponent_kind e_cal_backend_get_kind (ECalBackend *backend);
+gboolean e_cal_backend_is_online (ECalBackend *backend);
+gboolean e_cal_backend_is_opened (ECalBackend *backend);
+gboolean e_cal_backend_is_opening (ECalBackend *backend);
+gboolean e_cal_backend_is_readonly (ECalBackend *backend);
+gboolean e_cal_backend_is_removed (ECalBackend *backend);
+
+const gchar * e_cal_backend_get_cache_dir (ECalBackend *backend);
+void e_cal_backend_set_cache_dir (ECalBackend *backend, const gchar *cache_dir);
+
+void e_cal_backend_add_client (ECalBackend *backend, EDataCal *cal);
+void e_cal_backend_remove_client (ECalBackend *backend, EDataCal *cal);
+
+void e_cal_backend_add_view (ECalBackend *backend, EDataCalView *view);
+void e_cal_backend_remove_view (ECalBackend *backend, EDataCalView *view);
+void e_cal_backend_foreach_view (ECalBackend *backend, gboolean (* callback) (EDataCalView *view, gpointer user_data), gpointer user_data);
+
+void e_cal_backend_set_notification_proxy (ECalBackend *backend, ECalBackend *proxy);
+
+void e_cal_backend_get_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name);
+void e_cal_backend_set_backend_property (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *prop_name, const gchar *prop_value);
+
+void e_cal_backend_set_online (ECalBackend *backend, gboolean is_online);
+void e_cal_backend_authenticate_user (ECalBackend *backend, GCancellable *cancellable, ECredentials *credentials);
+
+void e_cal_backend_open (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, gboolean only_if_exists);
+void e_cal_backend_remove (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
+void e_cal_backend_refresh (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
+void e_cal_backend_get_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid);
+void e_cal_backend_get_object_list (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *sexp);
+void e_cal_backend_get_free_busy (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const GSList *users, time_t start, time_t end);
+void e_cal_backend_create_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj);
+void e_cal_backend_modify_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj, CalObjModType mod);
+void e_cal_backend_remove_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid, CalObjModType mod);
+void e_cal_backend_receive_objects (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj);
+void e_cal_backend_send_objects (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj);
+void e_cal_backend_get_attachment_uris (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid);
+void e_cal_backend_discard_alarm (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid, const gchar *auid);
+void e_cal_backend_get_timezone (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *tzid);
+void e_cal_backend_add_timezone (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *tzobject);
+icaltimezone * e_cal_backend_internal_get_timezone (ECalBackend *backend, const gchar *tzid);
+void e_cal_backend_start_view (ECalBackend *backend, EDataCalView *view);
+void e_cal_backend_stop_view (ECalBackend *backend, EDataCalView *view);
+
+void e_cal_backend_notify_object_created (ECalBackend *backend, const gchar *calobj);
+void e_cal_backend_notify_objects_added (ECalBackend *backend, EDataCalView *view, const GSList *objects);
+void e_cal_backend_notify_object_modified (ECalBackend *backend, const gchar *old_object, const gchar *object);
+void e_cal_backend_notify_objects_modified (ECalBackend *backend, EDataCalView *view, const GSList *objects);
+void e_cal_backend_notify_object_removed (ECalBackend *backend, const ECalComponentId *id, const gchar *old_object, const gchar *object);
+void e_cal_backend_notify_objects_removed (ECalBackend *backend, EDataCalView *view, const GSList *ids);
+
+void e_cal_backend_notify_error (ECalBackend *backend, const gchar *message);
+void e_cal_backend_notify_readonly (ECalBackend *backend, gboolean is_readonly);
+void e_cal_backend_notify_online (ECalBackend *backend, gboolean is_online);
+void e_cal_backend_notify_auth_required (ECalBackend *backend, gboolean is_self, const ECredentials *credentials);
+void e_cal_backend_notify_opened (ECalBackend *backend, GError *error);
+
+void e_cal_backend_empty_cache (ECalBackend *backend, struct _ECalBackendCache *cache);
+
+/* protected functions for subclasses */
+void e_cal_backend_set_is_removed (ECalBackend *backend, gboolean is_removed);
+
+void e_cal_backend_respond_opened (ECalBackend *backend, EDataCal *cal, guint32 opid, GError *error);
G_END_DECLS
diff --git a/calendar/libedata-cal/e-data-cal-common.h b/calendar/libedata-cal/e-data-cal-common.h
index e81fb34..e03fc15 100644
--- a/calendar/libedata-cal/e-data-cal-common.h
+++ b/calendar/libedata-cal/e-data-cal-common.h
@@ -39,9 +39,6 @@ typedef struct _EDataCalViewClass EDataCalViewClass;
typedef struct _ECalBackendSExp ECalBackendSExp;
typedef struct _ECalBackendSExpClass ECalBackendSExpClass;
-/* Opaque type for backend method context */
-typedef gpointer EServerMethodContext;
-
G_END_DECLS
diff --git a/calendar/libedata-cal/e-data-cal-factory.c b/calendar/libedata-cal/e-data-cal-factory.c
index 38e1e68..8e64ffb 100644
--- a/calendar/libedata-cal/e-data-cal-factory.c
+++ b/calendar/libedata-cal/e-data-cal-factory.c
@@ -48,7 +48,7 @@
#include "e-data-cal-factory.h"
#include "e-cal-backend-loader-factory.h"
-#include "e-gdbus-egdbuscalfactory.h"
+#include "e-gdbus-cal-factory.h"
#ifdef HAVE_ICAL_UNKNOWN_TOKEN_HANDLING
#include <libical/ical.h>
@@ -97,7 +97,7 @@ struct _EDataCalFactoryPrivate {
GHashTable *connections;
- gint mode;
+ gboolean is_online;
/* this is for notifications of source changes */
ESourceList *lists[E_CAL_SOURCE_TYPE_LAST];
@@ -297,6 +297,18 @@ calendar_freed_cb (EDataCalFactory *factory, GObject *dead)
10, (GSourceFunc) g_main_loop_quit, loop);
}
+static void
+last_client_gone_cb (ECalBackend *backend, EDataCalFactory *factory)
+{
+ EDataCalFactoryPrivate *priv = factory->priv;
+
+ if (e_cal_backend_is_removed (backend)) {
+ g_mutex_lock (priv->backends_mutex);
+ g_hash_table_foreach_remove (priv->backends, remove_dead_calendar_cb, backend);
+ g_mutex_unlock (priv->backends_mutex);
+ }
+}
+
struct find_backend_data {
const gchar *str_uri;
ECalBackend *backend;
@@ -329,7 +341,7 @@ find_backend_cb (gpointer key, gpointer value, gpointer data)
}
static gboolean
-impl_CalFactory_getCal (EGdbusCalFactory *object, GDBusMethodInvocation *invocation, const gchar *source_xml, guint type, EDataCalFactory *factory)
+impl_CalFactory_getCal (EGdbusCalFactory *object, GDBusMethodInvocation *invocation, const gchar * const *in_source_type, EDataCalFactory *factory)
{
EDataCal *calendar;
EDataCalFactoryPrivate *priv = factory->priv;
@@ -343,15 +355,21 @@ impl_CalFactory_getCal (EGdbusCalFactory *object, GDBusMethodInvocation *invocat
const gchar *sender;
GList *list;
GError *error = NULL;
+ gchar *source_xml = NULL;
+ guint type = 0;
- /* Remove a pending exit */
- if (priv->exit_timeout) {
- g_source_remove (priv->exit_timeout);
- priv->exit_timeout = 0;
+ if (!e_gdbus_cal_factory_decode_get_cal (in_source_type, &source_xml, &type)) {
+ error = g_error_new (E_DATA_CAL_ERROR, NoSuchCal, _("Invalid call"));
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ g_error_free (error);
+
+ return TRUE;
}
source = e_source_new_from_standalone_xml (source_xml);
if (!source) {
+ g_free (source_xml);
+
error = g_error_new (E_DATA_CAL_ERROR, NoSuchCal, _("Invalid source"));
g_dbus_method_invocation_return_gerror (invocation, error);
g_error_free (error);
@@ -359,6 +377,8 @@ impl_CalFactory_getCal (EGdbusCalFactory *object, GDBusMethodInvocation *invocat
return TRUE;
}
+ g_free (source_xml);
+
/* Get the URI so we can extract the protocol */
str_uri = e_source_get_uri (source);
if (!str_uri) {
@@ -469,12 +489,19 @@ impl_CalFactory_getCal (EGdbusCalFactory *object, GDBusMethodInvocation *invocat
g_hash_table_insert (
priv->backends, g_strdup (uid_type_string), backend);
- e_cal_backend_set_mode (backend, priv->mode);
+ g_signal_connect (backend, "last-client-gone", G_CALLBACK (last_client_gone_cb), factory);
+ e_cal_backend_set_online (backend, priv->is_online);
} else if (!e_source_equal (source, e_cal_backend_get_source (backend))) {
/* source changed, update it in a backend */
update_source_in_backend (backend, source);
}
+ /* Remove a pending exit */
+ if (priv->exit_timeout) {
+ g_source_remove (priv->exit_timeout);
+ priv->exit_timeout = 0;
+ }
+
calendar = e_data_cal_new (backend, source);
e_cal_backend_add_client (backend, calendar);
@@ -503,11 +530,10 @@ cleanup2:
g_free (uid_type_string);
g_object_unref (source);
- if (error) {
- g_dbus_method_invocation_return_gerror (invocation, error);
+ e_gdbus_cal_factory_complete_get_cal (object, invocation, path, error);
+
+ if (error)
g_error_free (error);
- } else
- e_gdbus_cal_factory_complete_get_cal (object, invocation, path);
g_free (path);
@@ -640,27 +666,27 @@ set_backend_online_status (gpointer key, gpointer value, gpointer data)
{
ECalBackend *backend = E_CAL_BACKEND (value);
- e_cal_backend_set_mode (backend, GPOINTER_TO_INT (data));
+ e_cal_backend_set_online (backend, GPOINTER_TO_INT (data) != 0);
}
/**
- * e_data_cal_factory_set_backend_mode:
+ * e_data_cal_factory_set_backend_online:
* @factory: A calendar factory.
- * @mode: Online mode to set.
+ * @is_online: Online mode to set.
*
* Sets the online mode for all backends created by the given factory.
*/
void
-e_data_cal_factory_set_backend_mode (EDataCalFactory *factory, gint mode)
+e_data_cal_factory_set_backend_online (EDataCalFactory *factory, gboolean is_online)
{
g_return_if_fail (E_IS_DATA_CAL_FACTORY (factory));
- factory->priv->mode = mode;
+ factory->priv->is_online = is_online;
g_mutex_lock (factory->priv->backends_mutex);
g_hash_table_foreach (
factory->priv->backends,
set_backend_online_status,
- GINT_TO_POINTER (factory->priv->mode));
+ GINT_TO_POINTER (factory->priv->is_online ? 1 : 0));
g_mutex_unlock (factory->priv->backends_mutex);
}
@@ -842,8 +868,7 @@ offline_state_changed_cb (EOfflineListener *eol,
g_return_if_fail (state == EOL_STATE_ONLINE || state == EOL_STATE_OFFLINE);
- e_data_cal_factory_set_backend_mode (
- factory, state == EOL_STATE_ONLINE ? Remote : Local);
+ e_data_cal_factory_set_backend_online (factory, state == EOL_STATE_ONLINE);
}
static void
diff --git a/calendar/libedata-cal/e-data-cal-factory.h b/calendar/libedata-cal/e-data-cal-factory.h
index cd5afe6..3bf4779 100644
--- a/calendar/libedata-cal/e-data-cal-factory.h
+++ b/calendar/libedata-cal/e-data-cal-factory.h
@@ -55,16 +55,13 @@ typedef enum {
GQuark e_data_cal_factory_error_quark (void);
#define E_DATA_CAL_FACTORY_ERROR e_data_cal_factory_error_quark ()
-GType e_data_cal_factory_get_type (void);
+GType e_data_cal_factory_get_type (void);
-void e_data_cal_factory_register_backend (EDataCalFactory *factory,
- ECalBackendFactory *backend_factory);
-
-void e_data_cal_factory_register_backends (EDataCalFactory *factory);
-
-gint e_data_cal_factory_get_n_backends (EDataCalFactory *factory);
-void e_data_cal_factory_dump_active_backends (EDataCalFactory *factory);
-void e_data_cal_factory_set_backend_mode (EDataCalFactory *factory, gint mode);
+void e_data_cal_factory_register_backend (EDataCalFactory *factory, ECalBackendFactory *backend_factory);
+void e_data_cal_factory_register_backends (EDataCalFactory *factory);
+gint e_data_cal_factory_get_n_backends (EDataCalFactory *factory);
+void e_data_cal_factory_dump_active_backends (EDataCalFactory *factory);
+void e_data_cal_factory_set_backend_online (EDataCalFactory *factory, gboolean is_online);
G_END_DECLS
diff --git a/calendar/libedata-cal/e-data-cal-types.h b/calendar/libedata-cal/e-data-cal-types.h
index fce65cc..d4f75f4 100644
--- a/calendar/libedata-cal/e-data-cal-types.h
+++ b/calendar/libedata-cal/e-data-cal-types.h
@@ -6,6 +6,7 @@ G_BEGIN_DECLS
typedef enum {
Success,
+ Busy,
RepositoryOffline,
PermissionDenied,
InvalidRange,
@@ -39,12 +40,6 @@ typedef enum {
} EDataCalCallStatus;
typedef enum {
- ModeSet, /* All OK */
- ModeNotSet, /* Generic error */
- ModeNotSupported /* Mode not supported */
-} EDataCalViewListenerSetModeStatus;
-
-typedef enum {
Event = 1 << 0,
Todo = 1 << 1,
Journal = 1 << 2,
@@ -58,12 +53,6 @@ typedef enum {
All = 0x07
} EDataCalObjModType;
-typedef enum {
- Local = 1 << 0,
- Remote = 1 << 1,
- AnyMode = 0x07
-} EDataCalMode;
-
G_END_DECLS
#endif /* __E_DATA_CAL_TYPES_H__ */
diff --git a/calendar/libedata-cal/e-data-cal-view.c b/calendar/libedata-cal/e-data-cal-view.c
index 78407aa..c0eea92 100644
--- a/calendar/libedata-cal/e-data-cal-view.c
+++ b/calendar/libedata-cal/e-data-cal-view.c
@@ -1,5 +1,5 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* Evolution calendar - Live search query implementation
+/* Evolution calendar - Live search view implementation
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
* Copyright (C) 2009 Intel Corporation
@@ -33,7 +33,7 @@
#include "libedataserver/e-data-server-util.h"
#include "e-cal-backend-sexp.h"
#include "e-data-cal-view.h"
-#include "e-gdbus-egdbuscalview.h"
+#include "e-gdbus-cal-view.h"
static void ensure_pending_flush_timeout (EDataCalView *view);
@@ -48,9 +48,9 @@ struct _EDataCalViewPrivate {
gboolean started;
gboolean stopped;
- gboolean done;
+ gboolean complete;
- /* Sexp that defines the query */
+ /* Sexp that defines the view */
ECalBackendSExp *sexp;
GArray *adds;
@@ -61,6 +61,9 @@ struct _EDataCalViewPrivate {
GMutex *pending_mutex;
guint flush_id;
+
+ /* which fields is listener interested in */
+ GHashTable *fields_of_interest;
};
G_DEFINE_TYPE (EDataCalView, e_data_cal_view, G_TYPE_OBJECT);
@@ -102,6 +105,43 @@ e_data_cal_view_class_init (EDataCalViewClass *klass)
}
static guint
+str_ic_hash (gconstpointer key)
+{
+ guint32 hash = 5381;
+ const gchar *str = key;
+ gint ii;
+
+ if (!str)
+ return hash;
+
+ for (ii = 0; str[ii]; ii++) {
+ hash = hash * 33 + g_ascii_tolower (str[ii]);
+ }
+
+ return hash;
+}
+
+static gboolean
+str_ic_equal (gconstpointer a, gconstpointer b)
+{
+ const gchar *stra = a, *strb = b;
+ gint ii;
+
+ if (!stra && !strb)
+ return TRUE;
+
+ if (!stra || !strb)
+ return FALSE;
+
+ for (ii = 0; stra[ii] && strb[ii]; ii++) {
+ if (g_ascii_tolower (stra[ii]) != g_ascii_tolower (strb[ii]))
+ return FALSE;
+ }
+
+ return stra[ii] == strb[ii];
+}
+
+static guint
id_hash (gconstpointer key)
{
const ECalComponentId *id = key;
@@ -118,11 +158,11 @@ id_equal (gconstpointer a, gconstpointer b)
EDataCalView *
e_data_cal_view_new (ECalBackend *backend, ECalBackendSExp *sexp)
{
- EDataCalView *query;
+ EDataCalView *view;
- query = g_object_new (E_DATA_CAL_VIEW_TYPE, "backend", backend, "sexp", sexp, NULL);
+ view = g_object_new (E_DATA_CAL_VIEW_TYPE, "backend", backend, "sexp", sexp, NULL);
- return query;
+ return view;
}
/**
@@ -131,14 +171,14 @@ e_data_cal_view_new (ECalBackend *backend, ECalBackendSExp *sexp)
* Since: 2.32
**/
guint
-e_data_cal_view_register_gdbus_object (EDataCalView *query, GDBusConnection *connection, const gchar *object_path, GError **error)
+e_data_cal_view_register_gdbus_object (EDataCalView *view, GDBusConnection *connection, const gchar *object_path, GError **error)
{
- g_return_val_if_fail (query != NULL, 0);
- g_return_val_if_fail (E_IS_DATA_CAL_VIEW (query), 0);
+ g_return_val_if_fail (view != NULL, 0);
+ g_return_val_if_fail (E_IS_DATA_CAL_VIEW (view), 0);
g_return_val_if_fail (connection != NULL, 0);
g_return_val_if_fail (object_path != NULL, 0);
- return e_gdbus_cal_view_register_object (query->priv->gdbus_object, connection, object_path, error);
+ return e_gdbus_cal_view_register_object (view->priv->gdbus_object, connection, object_path, error);
}
static void
@@ -221,7 +261,7 @@ ensure_pending_flush_timeout (EDataCalView *view)
if (priv->flush_id)
return;
- priv->flush_id = g_timeout_add (e_data_cal_view_is_done (view) ? 10 : (THRESHOLD_SECONDS * 1000), pending_flush_timeout_cb, view);
+ priv->flush_id = g_timeout_add (e_data_cal_view_is_completed (view) ? 10 : (THRESHOLD_SECONDS * 1000), pending_flush_timeout_cb, view);
}
static void
@@ -287,57 +327,94 @@ notify_remove (EDataCalView *view, ECalComponentId *id)
}
static void
-notify_done (EDataCalView *view, const GError *error)
+notify_complete (EDataCalView *view, const GError *error)
{
- gchar *gdbus_error_msg = NULL;
+ gchar **error_strv;
send_pending_adds (view);
send_pending_changes (view);
send_pending_removes (view);
- e_gdbus_cal_view_emit_done (view->priv->gdbus_object, error ? error->code : 0, e_util_ensure_gdbus_string (error ? error->message : "", &gdbus_error_msg));
+ error_strv = e_gdbus_templates_encode_error (error);
+
+ e_gdbus_cal_view_emit_complete (view->priv->gdbus_object, (const gchar * const *) error_strv);
- g_free (gdbus_error_msg);
+ g_strfreev (error_strv);
}
static gboolean
-impl_DataCalView_start (EGdbusCalView *object, GDBusMethodInvocation *invocation, EDataCalView *query)
+impl_DataCalView_start (EGdbusCalView *object, GDBusMethodInvocation *invocation, EDataCalView *view)
{
EDataCalViewPrivate *priv;
- priv = query->priv;
+ priv = view->priv;
if (!priv->started) {
priv->started = TRUE;
- e_debug_log(FALSE, E_DEBUG_LOG_DOMAIN_CAL_QUERIES, "---;%p;QUERY-START;%s;%s", query, e_data_cal_view_get_text (query), G_OBJECT_TYPE_NAME(priv->backend));
- e_cal_backend_start_query (priv->backend, query);
+ e_debug_log(FALSE, E_DEBUG_LOG_DOMAIN_CAL_QUERIES, "---;%p;VIEW-START;%s;%s", view, e_data_cal_view_get_text (view), G_OBJECT_TYPE_NAME(priv->backend));
+ e_cal_backend_start_view (priv->backend, view);
}
- e_gdbus_cal_view_complete_start (object, invocation);
+ e_gdbus_cal_view_complete_start (object, invocation, NULL);
return TRUE;
}
static gboolean
-impl_DataCalView_stop (EGdbusCalView *object, GDBusMethodInvocation *invocation, EDataCalView *query)
+impl_DataCalView_stop (EGdbusCalView *object, GDBusMethodInvocation *invocation, EDataCalView *view)
{
EDataCalViewPrivate *priv;
- priv = query->priv;
+ priv = view->priv;
priv->stopped = TRUE;
- e_gdbus_cal_view_complete_stop (object, invocation);
+ e_gdbus_cal_view_complete_stop (object, invocation, NULL);
+ e_cal_backend_stop_view (priv->backend, view);
return TRUE;
}
static gboolean
-impl_DataCalView_dispose (EGdbusCalView *object, GDBusMethodInvocation *invocation, EDataCalView *query)
+impl_DataCalView_dispose (EGdbusCalView *object, GDBusMethodInvocation *invocation, EDataCalView *view)
{
- e_gdbus_cal_view_complete_dispose (object, invocation);
+ e_gdbus_cal_view_complete_dispose (object, invocation, NULL);
+
+ view->priv->stopped = TRUE;
+ e_cal_backend_stop_view (view->priv->backend, view);
+
+ g_object_unref (view);
+
+ return TRUE;
+}
+
+static gboolean
+impl_DataCalView_setFieldsOfInterest (EGdbusCalView *object, GDBusMethodInvocation *invocation, const gchar * const *in_fields_of_interest, EDataCalView *view)
+{
+ EDataCalViewPrivate *priv;
+ gint ii;
+
+ g_return_val_if_fail (in_fields_of_interest != NULL, TRUE);
+
+ priv = view->priv;
+
+ if (priv->fields_of_interest)
+ g_hash_table_destroy (priv->fields_of_interest);
+ priv->fields_of_interest = NULL;
- g_object_unref (query);
+ for (ii = 0; in_fields_of_interest[ii]; ii++) {
+ const gchar *field = in_fields_of_interest[ii];
+
+ if (!*field)
+ continue;
+
+ if (!priv->fields_of_interest)
+ priv->fields_of_interest = g_hash_table_new_full (str_ic_hash, str_ic_equal, g_free, NULL);
+
+ g_hash_table_insert (priv->fields_of_interest, g_strdup (field), GINT_TO_POINTER (1));
+ }
+
+ e_gdbus_cal_view_complete_set_fields_of_interest (object, invocation, NULL);
return TRUE;
}
@@ -345,11 +422,11 @@ impl_DataCalView_dispose (EGdbusCalView *object, GDBusMethodInvocation *invocati
static void
e_data_cal_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
- EDataCalView *query;
+ EDataCalView *view;
EDataCalViewPrivate *priv;
- query = QUERY (object);
- priv = query->priv;
+ view = E_DATA_CAL_VIEW (object);
+ priv = view->priv;
switch (property_id) {
case PROP_BACKEND:
@@ -367,11 +444,11 @@ e_data_cal_view_set_property (GObject *object, guint property_id, const GValue *
static void
e_data_cal_view_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
- EDataCalView *query;
+ EDataCalView *view;
EDataCalViewPrivate *priv;
- query = QUERY (object);
- priv = query->priv;
+ view = E_DATA_CAL_VIEW (object);
+ priv = view->priv;
switch (property_id) {
case PROP_BACKEND:
@@ -388,23 +465,25 @@ e_data_cal_view_get_property (GObject *object, guint property_id, GValue *value,
/* Instance init */
static void
-e_data_cal_view_init (EDataCalView *query)
+e_data_cal_view_init (EDataCalView *view)
{
EDataCalViewPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (
- query, E_DATA_CAL_VIEW_TYPE, EDataCalViewPrivate);
+ view, E_DATA_CAL_VIEW_TYPE, EDataCalViewPrivate);
- query->priv = priv;
+ view->priv = priv;
priv->gdbus_object = e_gdbus_cal_view_stub_new ();
- g_signal_connect (priv->gdbus_object, "handle-start", G_CALLBACK (impl_DataCalView_start), query);
- g_signal_connect (priv->gdbus_object, "handle-stop", G_CALLBACK (impl_DataCalView_stop), query);
- g_signal_connect (priv->gdbus_object, "handle-dispose", G_CALLBACK (impl_DataCalView_dispose), query);
+ g_signal_connect (priv->gdbus_object, "handle-start", G_CALLBACK (impl_DataCalView_start), view);
+ g_signal_connect (priv->gdbus_object, "handle-stop", G_CALLBACK (impl_DataCalView_stop), view);
+ g_signal_connect (priv->gdbus_object, "handle-dispose", G_CALLBACK (impl_DataCalView_dispose), view);
+ g_signal_connect (priv->gdbus_object, "handle-set-fields-of-interest", G_CALLBACK (impl_DataCalView_setFieldsOfInterest), view);
priv->backend = NULL;
priv->started = FALSE;
priv->stopped = FALSE;
- priv->done = FALSE;
+ priv->complete = FALSE;
priv->sexp = NULL;
+ priv->fields_of_interest = NULL;
priv->adds = g_array_sized_new (TRUE, TRUE, sizeof (gchar *), THRESHOLD_ITEMS);
priv->changes = g_array_sized_new (TRUE, TRUE, sizeof (gchar *), THRESHOLD_ITEMS);
@@ -419,17 +498,17 @@ e_data_cal_view_init (EDataCalView *query)
static void
e_data_cal_view_dispose (GObject *object)
{
- EDataCalView *query;
+ EDataCalView *view;
EDataCalViewPrivate *priv;
g_return_if_fail (object != NULL);
- g_return_if_fail (IS_QUERY (object));
+ g_return_if_fail (E_IS_DATA_CAL_VIEW (object));
- query = QUERY (object);
- priv = query->priv;
+ view = E_DATA_CAL_VIEW (object);
+ priv = view->priv;
if (priv->backend) {
- e_cal_backend_remove_query (priv->backend, query);
+ e_cal_backend_remove_view (priv->backend, view);
g_object_unref (priv->backend);
priv->backend = NULL;
}
@@ -454,17 +533,28 @@ e_data_cal_view_dispose (GObject *object)
static void
e_data_cal_view_finalize (GObject *object)
{
- EDataCalView *query;
+ EDataCalView *view;
EDataCalViewPrivate *priv;
g_return_if_fail (object != NULL);
- g_return_if_fail (IS_QUERY (object));
+ g_return_if_fail (E_IS_DATA_CAL_VIEW (object));
- query = QUERY (object);
- priv = query->priv;
+ view = E_DATA_CAL_VIEW (object);
+ priv = view->priv;
+
+ reset_array (priv->adds);
+ reset_array (priv->changes);
+ reset_array (priv->removes);
+
+ g_array_free (priv->adds, TRUE);
+ g_array_free (priv->changes, TRUE);
+ g_array_free (priv->removes, TRUE);
g_hash_table_destroy (priv->ids);
+ if (priv->fields_of_interest)
+ g_hash_table_destroy (priv->fields_of_interest);
+
g_mutex_free (priv->pending_mutex);
(* G_OBJECT_CLASS (e_data_cal_view_parent_class)->finalize) (object);
@@ -472,83 +562,67 @@ e_data_cal_view_finalize (GObject *object)
/**
* e_data_cal_view_get_text:
- * @query: A #EDataCalView object.
+ * @view: A #EDataCalView object.
*
- * Get the expression used for the given query.
+ * Get the expression used for the given view.
*
- * Returns: the query expression used to search.
+ * Returns: the view expression used to search.
*/
const gchar *
-e_data_cal_view_get_text (EDataCalView *query)
+e_data_cal_view_get_text (EDataCalView *view)
{
- g_return_val_if_fail (IS_QUERY (query), NULL);
+ g_return_val_if_fail (E_IS_DATA_CAL_VIEW (view), NULL);
- return e_cal_backend_sexp_text (query->priv->sexp);
+ return e_cal_backend_sexp_text (view->priv->sexp);
}
/**
* e_data_cal_view_get_object_sexp:
- * @query: A query object.
+ * @view: A view object.
*
- * Get the #ECalBackendSExp object used for the given query.
+ * Get the #ECalBackendSExp object used for the given view.
*
* Returns: The expression object used to search.
*/
ECalBackendSExp *
-e_data_cal_view_get_object_sexp (EDataCalView *query)
+e_data_cal_view_get_object_sexp (EDataCalView *view)
{
- g_return_val_if_fail (IS_QUERY (query), NULL);
+ g_return_val_if_fail (E_IS_DATA_CAL_VIEW (view), NULL);
- return query->priv->sexp;
+ return view->priv->sexp;
}
/**
* e_data_cal_view_object_matches:
- * @query: A query object.
+ * @view: A view object.
* @object: Object to match.
*
* Compares the given @object to the regular expression used for the
- * given query.
+ * given view.
*
* Returns: TRUE if the object matches the expression, FALSE if not.
*/
gboolean
-e_data_cal_view_object_matches (EDataCalView *query, const gchar *object)
+e_data_cal_view_object_matches (EDataCalView *view, const gchar *object)
{
EDataCalViewPrivate *priv;
- g_return_val_if_fail (query != NULL, FALSE);
- g_return_val_if_fail (IS_QUERY (query), FALSE);
+ g_return_val_if_fail (view != NULL, FALSE);
+ g_return_val_if_fail (E_IS_DATA_CAL_VIEW (view), FALSE);
g_return_val_if_fail (object != NULL, FALSE);
- priv = query->priv;
+ priv = view->priv;
return e_cal_backend_sexp_match_object (priv->sexp, object, priv->backend);
}
/**
- * e_data_cal_view_get_matched_objects:
- * @query: A query object.
- *
- * Gets the list of objects already matched for the given query.
- *
- * Returns: A list of matched objects.
- */
-GList *
-e_data_cal_view_get_matched_objects (EDataCalView *query)
-{
- g_return_val_if_fail (IS_QUERY (query), NULL);
- /* TODO e_data_cal_view_get_matched_objects */
- return NULL;
-}
-
-/**
* e_data_cal_view_is_started:
- * @query: A query object.
+ * @view: A view object.
*
- * Checks whether the given query has already been started.
+ * Checks whether the given view has already been started.
*
- * Returns: TRUE if the query has already been started, FALSE otherwise.
+ * Returns: TRUE if the view has already been started, FALSE otherwise.
*/
gboolean
e_data_cal_view_is_started (EDataCalView *view)
@@ -560,11 +634,11 @@ e_data_cal_view_is_started (EDataCalView *view)
/**
* e_data_cal_view_is_stopped:
- * @query: A query object.
+ * @view: A view object.
*
- * Checks whether the given query has been stopped.
+ * Checks whether the given view has been stopped.
*
- * Returns: TRUE if the query has been stopped, FALSE otherwise.
+ * Returns: TRUE if the view has been stopped, FALSE otherwise.
*
* Since: 2.32
*/
@@ -577,40 +651,56 @@ e_data_cal_view_is_stopped (EDataCalView *view)
}
/**
- * e_data_cal_view_is_done:
- * @query: A query object.
+ * e_data_cal_view_is_completed:
+ * @view: A view object.
*
- * Checks whether the given query is already done. Being done means the initial
+ * Checks whether the given view is already completed. Being completed means the initial
* matching of objects have been finished, not that no more notifications about
- * changes will be sent. In fact, even after done, notifications will still be sent
- * if there are changes in the objects matching the query search expression.
+ * changes will be sent. In fact, even after completed, notifications will still be sent
+ * if there are changes in the objects matching the view search expression.
*
- * Returns: TRUE if the query is done, FALSE if still in progress.
+ * Returns: TRUE if the view is completed, FALSE if still in progress.
*/
gboolean
-e_data_cal_view_is_done (EDataCalView *query)
+e_data_cal_view_is_completed (EDataCalView *view)
{
- EDataCalViewPrivate *priv;
+ g_return_val_if_fail (E_IS_DATA_CAL_VIEW (view), FALSE);
- g_return_val_if_fail (IS_QUERY (query), FALSE);
+ return view->priv->complete;
+}
- priv = query->priv;
+/**
+ * e_data_cal_view_get_fields_of_interest:
+ * @view: A view object.
+ *
+ * Returns: Hash table of field names which the listener is interested in.
+ * Backends can return fully populated objects, but the listener advertised
+ * that it will use only these. Returns %NULL for all available fields.
+ *
+ * Note: The data pointer in the hash table has no special meaning, it's
+ * only GINT_TO_POINTER(1) for easier checking. Also, field names are
+ * compared case insensitively.
+ **/
+/* const */ GHashTable *
+e_data_cal_view_get_fields_of_interest (EDataCalView *view)
+{
+ g_return_val_if_fail (E_IS_DATA_CAL_VIEW (view), NULL);
- return priv->done;
+ return view->priv->fields_of_interest;
}
/**
* e_data_cal_view_notify_objects_added:
- * @query: A query object.
+ * @view: A view object.
* @objects: List of objects that have been added.
*
- * Notifies all query listeners of the addition of a list of objects.
+ * Notifies all view listeners of the addition of a list of objects.
*/
void
-e_data_cal_view_notify_objects_added (EDataCalView *view, const GList *objects)
+e_data_cal_view_notify_objects_added (EDataCalView *view, const GSList *objects)
{
EDataCalViewPrivate *priv;
- const GList *l;
+ const GSList *l;
g_return_if_fail (view && E_IS_DATA_CAL_VIEW (view));
priv = view->priv;
@@ -629,15 +719,15 @@ e_data_cal_view_notify_objects_added (EDataCalView *view, const GList *objects)
/**
* e_data_cal_view_notify_objects_added_1:
- * @query: A query object.
+ * @view: A view object.
* @object: The object that has been added.
*
- * Notifies all the query listeners of the addition of a single object.
+ * Notifies all the view listeners of the addition of a single object.
*/
void
e_data_cal_view_notify_objects_added_1 (EDataCalView *view, const gchar *object)
{
- GList l = {NULL,};
+ GSList l = {NULL,};
g_return_if_fail (view && E_IS_DATA_CAL_VIEW (view));
g_return_if_fail (object);
@@ -648,16 +738,16 @@ e_data_cal_view_notify_objects_added_1 (EDataCalView *view, const gchar *object)
/**
* e_data_cal_view_notify_objects_modified:
- * @query: A query object.
+ * @view: A view object.
* @objects: List of modified objects.
*
- * Notifies all query listeners of the modification of a list of objects.
+ * Notifies all view listeners of the modification of a list of objects.
*/
void
-e_data_cal_view_notify_objects_modified (EDataCalView *view, const GList *objects)
+e_data_cal_view_notify_objects_modified (EDataCalView *view, const GSList *objects)
{
EDataCalViewPrivate *priv;
- const GList *l;
+ const GSList *l;
g_return_if_fail (view && E_IS_DATA_CAL_VIEW (view));
priv = view->priv;
@@ -677,15 +767,15 @@ e_data_cal_view_notify_objects_modified (EDataCalView *view, const GList *object
/**
* e_data_cal_view_notify_objects_modified_1:
- * @query: A query object.
+ * @view: A view object.
* @object: The modified object.
*
- * Notifies all query listeners of the modification of a single object.
+ * Notifies all view listeners of the modification of a single object.
*/
void
e_data_cal_view_notify_objects_modified_1 (EDataCalView *view, const gchar *object)
{
- GList l = {NULL,};
+ GSList l = {NULL,};
g_return_if_fail (view && E_IS_DATA_CAL_VIEW (view));
g_return_if_fail (object);
@@ -696,16 +786,16 @@ e_data_cal_view_notify_objects_modified_1 (EDataCalView *view, const gchar *obje
/**
* e_data_cal_view_notify_objects_removed:
- * @query: A query object.
+ * @view: A view object.
* @ids: List of IDs for the objects that have been removed.
*
- * Notifies all query listener of the removal of a list of objects.
+ * Notifies all view listener of the removal of a list of objects.
*/
void
-e_data_cal_view_notify_objects_removed (EDataCalView *view, const GList *ids)
+e_data_cal_view_notify_objects_removed (EDataCalView *view, const GSList *ids)
{
EDataCalViewPrivate *priv;
- const GList *l;
+ const GSList *l;
g_return_if_fail (view && E_IS_DATA_CAL_VIEW (view));
priv = view->priv;
@@ -726,15 +816,15 @@ e_data_cal_view_notify_objects_removed (EDataCalView *view, const GList *ids)
/**
* e_data_cal_view_notify_objects_removed_1:
- * @query: A query object.
+ * @view: A view object.
* @id: ID of the removed object.
*
- * Notifies all query listener of the removal of a single object.
+ * Notifies all view listener of the removal of a single object.
*/
void
e_data_cal_view_notify_objects_removed_1 (EDataCalView *view, const ECalComponentId *id)
{
- GList l = {NULL,};
+ GSList l = {NULL,};
g_return_if_fail (view && E_IS_DATA_CAL_VIEW (view));
g_return_if_fail (id);
@@ -745,14 +835,14 @@ e_data_cal_view_notify_objects_removed_1 (EDataCalView *view, const ECalComponen
/**
* e_data_cal_view_notify_progress:
- * @query: A query object.
- * @message: Progress message to send to listeners.
+ * @view: A view object.
* @percent: Percentage completed.
+ * @message: Progress message to send to listeners.
*
- * Notifies all query listeners of progress messages.
+ * Notifies all view listeners of progress messages.
*/
void
-e_data_cal_view_notify_progress (EDataCalView *view, const gchar *message, gint percent)
+e_data_cal_view_notify_progress (EDataCalView *view, gint percent, const gchar *message)
{
EDataCalViewPrivate *priv;
gchar *gdbus_message = NULL;
@@ -763,21 +853,21 @@ e_data_cal_view_notify_progress (EDataCalView *view, const gchar *message, gint
if (!priv->started || priv->stopped)
return;
- e_gdbus_cal_view_emit_progress (view->priv->gdbus_object, e_util_ensure_gdbus_string (message, &gdbus_message), percent);
+ e_gdbus_cal_view_emit_progress (view->priv->gdbus_object, percent, e_util_ensure_gdbus_string (message, &gdbus_message));
g_free (gdbus_message);
}
/**
- * e_data_cal_view_notify_done:
- * @query: A query object.
- * @error: Query completion error, if any.
+ * e_data_cal_view_notify_complete:
+ * @view: A view object.
+ * @error: View completion error, if any.
*
- * Notifies all query listeners of the completion of the query, including a
+ * Notifies all view listeners of the completion of the view, including a
* status code.
*/
void
-e_data_cal_view_notify_done (EDataCalView *view, const GError *error)
+e_data_cal_view_notify_complete (EDataCalView *view, const GError *error)
{
EDataCalViewPrivate *priv;
@@ -789,9 +879,9 @@ e_data_cal_view_notify_done (EDataCalView *view, const GError *error)
g_mutex_lock (priv->pending_mutex);
- priv->done = TRUE;
+ priv->complete = TRUE;
- notify_done (view, error);
+ notify_complete (view, error);
g_mutex_unlock (priv->pending_mutex);
}
diff --git a/calendar/libedata-cal/e-data-cal-view.h b/calendar/libedata-cal/e-data-cal-view.h
index 2ec3f48..0be824b 100644
--- a/calendar/libedata-cal/e-data-cal-view.h
+++ b/calendar/libedata-cal/e-data-cal-view.h
@@ -1,4 +1,4 @@
-/* Evolution calendar - Live search query implementation
+/* Evolution calendar - Live search view implementation
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
@@ -36,9 +36,6 @@ G_BEGIN_DECLS
#define E_DATA_CAL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_DATA_CAL_VIEW_TYPE, EDataCalView))
#define E_DATA_CAL_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_DATA_CAL_VIEW_TYPE, EDataCalViewClass))
#define E_IS_DATA_CAL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_DATA_CAL_VIEW_TYPE))
-/* Deprecated macros */
-#define QUERY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_DATA_CAL_VIEW_TYPE, EDataCalView))
-#define IS_QUERY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_DATA_CAL_VIEW_TYPE))
typedef struct _EDataCalViewPrivate EDataCalViewPrivate;
@@ -51,37 +48,25 @@ struct _EDataCalViewClass {
GObjectClass parent_class;
};
-GType e_data_cal_view_get_type (void);
-EDataCalView *e_data_cal_view_new (ECalBackend *backend, ECalBackendSExp *sexp);
+GType e_data_cal_view_get_type (void);
+EDataCalView * e_data_cal_view_new (ECalBackend *backend, ECalBackendSExp *sexp);
+guint e_data_cal_view_register_gdbus_object (EDataCalView *view, GDBusConnection *connection, const gchar *object_path, GError **error);
+const gchar * e_data_cal_view_get_text (EDataCalView *view);
+ECalBackendSExp * e_data_cal_view_get_object_sexp (EDataCalView *view);
+gboolean e_data_cal_view_object_matches (EDataCalView *view, const gchar *object);
+gboolean e_data_cal_view_is_started (EDataCalView *view);
+gboolean e_data_cal_view_is_completed (EDataCalView *view);
+gboolean e_data_cal_view_is_stopped (EDataCalView *view);
+/* const */ GHashTable *e_data_cal_view_get_fields_of_interest (EDataCalView *view);
-guint e_data_cal_view_register_gdbus_object (EDataCalView *query, GDBusConnection *connection, const gchar *object_path, GError **error);
-
-const gchar *e_data_cal_view_get_text (EDataCalView *query);
-ECalBackendSExp *e_data_cal_view_get_object_sexp (EDataCalView *query);
-gboolean e_data_cal_view_object_matches (EDataCalView *query, const gchar *object);
-
-GList *e_data_cal_view_get_matched_objects (EDataCalView *query);
-gboolean e_data_cal_view_is_started (EDataCalView *query);
-gboolean e_data_cal_view_is_done (EDataCalView *query);
-gboolean e_data_cal_view_is_stopped (EDataCalView *query);
-
-void e_data_cal_view_notify_objects_added (EDataCalView *query,
- const GList *objects);
-void e_data_cal_view_notify_objects_added_1 (EDataCalView *query,
- const gchar *object);
-void e_data_cal_view_notify_objects_modified (EDataCalView *query,
- const GList *objects);
-void e_data_cal_view_notify_objects_modified_1 (EDataCalView *query,
- const gchar *object);
-void e_data_cal_view_notify_objects_removed (EDataCalView *query,
- const GList *ids);
-void e_data_cal_view_notify_objects_removed_1 (EDataCalView *query,
- const ECalComponentId *id);
-void e_data_cal_view_notify_progress (EDataCalView *query,
- const gchar *message,
- gint percent);
-void e_data_cal_view_notify_done (EDataCalView *query,
- const GError *error);
+void e_data_cal_view_notify_objects_added (EDataCalView *view, const GSList *objects);
+void e_data_cal_view_notify_objects_added_1 (EDataCalView *view, const gchar *object);
+void e_data_cal_view_notify_objects_modified (EDataCalView *view, const GSList *objects);
+void e_data_cal_view_notify_objects_modified_1 (EDataCalView *view, const gchar *object);
+void e_data_cal_view_notify_objects_removed (EDataCalView *view, const GSList *ids);
+void e_data_cal_view_notify_objects_removed_1 (EDataCalView *view, const ECalComponentId *id);
+void e_data_cal_view_notify_progress (EDataCalView *view, gint percent, const gchar *message);
+void e_data_cal_view_notify_complete (EDataCalView *view, const GError *error);
G_END_DECLS
diff --git a/calendar/libedata-cal/e-data-cal.c b/calendar/libedata-cal/e-data-cal.c
index 2e7d580..f7e00da 100644
--- a/calendar/libedata-cal/e-data-cal.c
+++ b/calendar/libedata-cal/e-data-cal.c
@@ -31,11 +31,13 @@
#include <unistd.h>
#include <glib-object.h>
-#include <libedataserver/e-debug-log.h>
+#include <libedataserver/e-credentials.h>
#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-operation-pool.h>
+
#include "e-data-cal.h"
#include "e-data-cal-enumtypes.h"
-#include "e-gdbus-egdbuscal.h"
+#include "e-gdbus-cal.h"
G_DEFINE_TYPE (EDataCal, e_data_cal, G_TYPE_OBJECT);
@@ -44,11 +46,314 @@ G_DEFINE_TYPE (EDataCal, e_data_cal, G_TYPE_OBJECT);
struct _EDataCalPrivate {
EGdbusCal *gdbus_object;
+
ECalBackend *backend;
ESource *source;
- GHashTable *live_queries;
+
+ GStaticRecMutex pending_ops_lock;
+ GHashTable *pending_ops; /* opid to GCancellable for still running operations */
};
+static EOperationPool *ops_pool = NULL;
+
+typedef enum {
+ OP_OPEN,
+ OP_AUTHENTICATE,
+ OP_REMOVE,
+ OP_REFRESH,
+ OP_GET_BACKEND_PROPERTY,
+ OP_SET_BACKEND_PROPERTY,
+ OP_GET_OBJECT,
+ OP_GET_OBJECT_LIST,
+ OP_GET_FREE_BUSY,
+ OP_CREATE_OBJECT,
+ OP_MODIFY_OBJECT,
+ OP_REMOVE_OBJECT,
+ OP_RECEIVE_OBJECTS,
+ OP_SEND_OBJECTS,
+ OP_GET_ATTACHMENT_URIS,
+ OP_DISCARD_ALARM,
+ OP_GET_VIEW,
+ OP_GET_TIMEZONE,
+ OP_ADD_TIMEZONE,
+ OP_CANCEL_OPERATION,
+ OP_CANCEL_ALL,
+ OP_CLOSE
+} OperationID;
+
+typedef struct {
+ OperationID op;
+ guint32 id; /* operation id */
+ EDataCal *cal; /* calendar */
+ GCancellable *cancellable;
+
+ union {
+ /* OP_OPEN */
+ gboolean only_if_exists;
+ /* OP_AUTHENTICATE */
+ ECredentials *credentials;
+ /* OP_GET_OBJECT */
+ /* OP_GET_ATTACHMENT_URIS */
+ struct _ur {
+ gchar *uid;
+ gchar *rid;
+ } ur;
+ /* OP_DISCARD_ALARM */
+ struct _ura {
+ gchar *uid;
+ gchar *rid;
+ gchar *auid;
+ } ura;
+ /* OP_GET_OBJECT_LIST */
+ /* OP_GET_VIEW */
+ gchar *sexp;
+ /* OP_GET_FREE_BUSY */
+ struct _free_busy {
+ time_t start, end;
+ GSList *users;
+ } fb;
+ /* OP_CREATE_OBJECT */
+ /* OP_RECEIVE_OBJECTS */
+ /* OP_SEND_OBJECTS */
+ struct _co {
+ gchar *calobj;
+ } co;
+ /* OP_MODIFY_OBJECT */
+ struct _mo {
+ gchar *calobj;
+ EDataCalObjModType mod;
+ } mo;
+ /* OP_REMOVE_OBJECT */
+ struct _ro {
+ gchar *uid;
+ gchar *rid;
+ EDataCalObjModType mod;
+ } ro;
+ /* OP_GET_TIMEZONE */
+ gchar *tzid;
+ /* OP_ADD_TIMEZONE */
+ gchar *tzobject;
+ /* OP_CANCEL_OPERATION */
+ guint opid;
+ /* OP_GET_BACKEND_PROPERTY */
+ gchar *prop_name;
+ /* OP_SET_BACKEND_PROPERTY */
+ struct _sbp {
+ gchar *prop_name;
+ gchar *prop_value;
+ } sbp;
+
+ /* OP_REMOVE */
+ /* OP_REFRESH */
+ /* OP_CANCEL_ALL */
+ /* OP_CLOSE */
+ } d;
+} OperationData;
+
+/* Function to get a new EDataCalView path, used by getView below */
+static gchar *
+construct_calview_path (void)
+{
+ static guint counter = 1;
+ return g_strdup_printf ("/org/gnome/evolution/dataserver/CalendarView/%d/%d", getpid(), counter++);
+}
+
+static void
+cancel_ops_cb (gpointer opid, gpointer cancellable, gpointer user_data)
+{
+ g_return_if_fail (cancellable != NULL);
+
+ g_cancellable_cancel (cancellable);
+}
+
+static void
+operation_thread (gpointer data, gpointer user_data)
+{
+ OperationData *op = data;
+ ECalBackend *backend;
+
+ backend = e_data_cal_get_backend (op->cal);
+
+ switch (op->op) {
+ case OP_OPEN:
+ e_cal_backend_open (backend, op->cal, op->id, op->cancellable, op->d.only_if_exists);
+ break;
+ case OP_REMOVE:
+ e_cal_backend_remove (backend, op->cal, op->id, op->cancellable);
+ break;
+ case OP_REFRESH:
+ e_cal_backend_refresh (backend, op->cal, op->id, op->cancellable);
+ break;
+ case OP_GET_BACKEND_PROPERTY:
+ e_cal_backend_get_backend_property (backend, op->cal, op->id, op->cancellable, op->d.prop_name);
+ g_free (op->d.prop_name);
+ break;
+ case OP_SET_BACKEND_PROPERTY:
+ e_cal_backend_set_backend_property (backend, op->cal, op->id, op->cancellable, op->d.sbp.prop_name, op->d.sbp.prop_value);
+ g_free (op->d.sbp.prop_name);
+ g_free (op->d.sbp.prop_value);
+ break;
+ case OP_GET_OBJECT:
+ e_cal_backend_get_object (backend, op->cal, op->id, op->cancellable, op->d.ur.uid, op->d.ur.rid && *op->d.ur.rid ? op->d.ur.rid : NULL);
+ g_free (op->d.ur.uid);
+ g_free (op->d.ur.rid);
+ break;
+ case OP_GET_OBJECT_LIST:
+ e_cal_backend_get_object_list (backend, op->cal, op->id, op->cancellable, op->d.sexp);
+ g_free (op->d.sexp);
+ break;
+ case OP_GET_FREE_BUSY:
+ e_cal_backend_get_free_busy (backend, op->cal, op->id, op->cancellable, op->d.fb.users, op->d.fb.start, op->d.fb.end);
+ g_slist_foreach (op->d.fb.users, (GFunc) g_free, NULL);
+ g_slist_free (op->d.fb.users);
+ break;
+ case OP_CREATE_OBJECT:
+ e_cal_backend_create_object (backend, op->cal, op->id, op->cancellable, op->d.co.calobj);
+ g_free (op->d.co.calobj);
+ break;
+ case OP_MODIFY_OBJECT:
+ e_cal_backend_modify_object (backend, op->cal, op->id, op->cancellable, op->d.mo.calobj, op->d.mo.mod);
+ g_free (op->d.mo.calobj);
+ break;
+ case OP_REMOVE_OBJECT:
+ e_cal_backend_remove_object (backend, op->cal, op->id, op->cancellable, op->d.ro.uid, op->d.ro.rid && *op->d.ro.rid ? op->d.ro.rid : NULL, op->d.ro.mod);
+ g_free (op->d.ro.uid);
+ g_free (op->d.ro.rid);
+ break;
+ case OP_RECEIVE_OBJECTS:
+ e_cal_backend_receive_objects (backend, op->cal, op->id, op->cancellable, op->d.co.calobj);
+ g_free (op->d.co.calobj);
+ break;
+ case OP_SEND_OBJECTS:
+ e_cal_backend_send_objects (backend, op->cal, op->id, op->cancellable, op->d.co.calobj);
+ g_free (op->d.co.calobj);
+ break;
+ case OP_GET_ATTACHMENT_URIS:
+ e_cal_backend_get_attachment_uris (backend, op->cal, op->id, op->cancellable, op->d.ur.uid, op->d.ur.rid && *op->d.ur.rid ? op->d.ur.rid : NULL);
+ g_free (op->d.ur.uid);
+ g_free (op->d.ur.rid);
+ break;
+ case OP_DISCARD_ALARM:
+ e_cal_backend_discard_alarm (backend, op->cal, op->id, op->cancellable, op->d.ura.uid, op->d.ura.rid && *op->d.ura.rid ? op->d.ura.rid : NULL, op->d.ura.auid);
+ g_free (op->d.ura.uid);
+ g_free (op->d.ura.rid);
+ g_free (op->d.ura.auid);
+ break;
+ case OP_GET_VIEW:
+ if (op->d.sexp) {
+ EDataCalView *view;
+ ECalBackendSExp *obj_sexp;
+ gchar *path;
+ GError *error = NULL;
+
+ /* we handle this entirely here, since it doesn't require any
+ backend involvement now that we have e_cal_view_start to
+ actually kick off the search. */
+
+ obj_sexp = e_cal_backend_sexp_new (op->d.sexp);
+ if (!obj_sexp) {
+ g_free (op->d.sexp);
+ e_data_cal_respond_get_view (op->cal, op->id, EDC_ERROR (InvalidQuery), NULL);
+ break;
+ }
+
+ view = e_data_cal_view_new (backend, obj_sexp);
+ if (!view) {
+ g_object_unref (obj_sexp);
+ g_free (op->d.sexp);
+ e_data_cal_respond_get_view (op->cal, op->id, EDC_ERROR (OtherError), NULL);
+ break;
+ }
+
+ path = construct_calview_path ();
+ e_data_cal_view_register_gdbus_object (view, e_gdbus_cal_stub_get_connection (op->cal->priv->gdbus_object), path, &error);
+
+ if (error) {
+ g_object_unref (view);
+ g_free (op->d.sexp);
+ e_data_cal_respond_get_view (op->cal, op->id, EDC_ERROR_EX (OtherError, error->message), NULL);
+ g_error_free (error);
+ g_free (path);
+
+ break;
+ }
+
+ e_cal_backend_add_view (backend, view);
+
+ e_data_cal_respond_get_view (op->cal, op->id, EDC_ERROR (Success), path);
+
+ g_free (path);
+ }
+ g_free (op->d.sexp);
+ break;
+ case OP_GET_TIMEZONE:
+ e_cal_backend_get_timezone (backend, op->cal, op->id, op->cancellable, op->d.tzid);
+ g_free (op->d.tzid);
+ break;
+ case OP_ADD_TIMEZONE:
+ e_cal_backend_add_timezone (backend, op->cal, op->id, op->cancellable, op->d.tzobject);
+ g_free (op->d.tzobject);
+ break;
+ case OP_AUTHENTICATE:
+ e_cal_backend_authenticate_user (backend, op->cancellable, op->d.credentials);
+ e_credentials_free (op->d.credentials);
+ break;
+ case OP_CANCEL_OPERATION:
+ g_static_rec_mutex_lock (&op->cal->priv->pending_ops_lock);
+
+ if (g_hash_table_lookup (op->cal->priv->pending_ops, GUINT_TO_POINTER (op->d.opid))) {
+ GCancellable *cancellable = g_hash_table_lookup (op->cal->priv->pending_ops, GUINT_TO_POINTER (op->d.opid));
+
+ g_cancellable_cancel (cancellable);
+ }
+
+ g_static_rec_mutex_unlock (&op->cal->priv->pending_ops_lock);
+ break;
+ case OP_CLOSE:
+ /* close just cancels all pending ops and frees data cal */
+ e_cal_backend_remove_client (backend, op->cal);
+ case OP_CANCEL_ALL:
+ g_static_rec_mutex_lock (&op->cal->priv->pending_ops_lock);
+ g_hash_table_foreach (op->cal->priv->pending_ops, cancel_ops_cb, NULL);
+ g_static_rec_mutex_unlock (&op->cal->priv->pending_ops_lock);
+ break;
+ }
+
+ g_object_unref (op->cal);
+ g_object_unref (op->cancellable);
+ g_slice_free (OperationData, op);
+}
+
+static OperationData *
+op_new (OperationID op, EDataCal *cal)
+{
+ OperationData *data;
+
+ data = g_slice_new0 (OperationData);
+ data->op = op;
+ data->cal = g_object_ref (cal);
+ data->id = e_operation_pool_reserve_opid (ops_pool);
+ data->cancellable = g_cancellable_new ();
+
+ g_static_rec_mutex_lock (&cal->priv->pending_ops_lock);
+ g_hash_table_insert (cal->priv->pending_ops, GUINT_TO_POINTER (data->id), g_object_ref (data->cancellable));
+ g_static_rec_mutex_unlock (&cal->priv->pending_ops_lock);
+
+ return data;
+}
+
+static void
+op_complete (EDataCal *cal, guint32 opid)
+{
+ g_return_if_fail (cal != NULL);
+
+ e_operation_pool_release_opid (ops_pool, opid);
+
+ g_static_rec_mutex_lock (&cal->priv->pending_ops_lock);
+ g_hash_table_remove (cal->priv->pending_ops, GUINT_TO_POINTER (opid));
+ g_static_rec_mutex_unlock (&cal->priv->pending_ops_lock);
+}
+
/* Create the EDataCal error quark */
GQuark
e_data_cal_error_quark (void)
@@ -57,6 +362,7 @@ e_data_cal_error_quark (void)
static const GDBusErrorEntry entries[] = {
{ Success, ERR_PREFIX "Success" },
+ { Busy, ERR_PREFIX "Busy" },
{ RepositoryOffline, ERR_PREFIX "RepositoryOffline" },
{ PermissionDenied, ERR_PREFIX "PermissionDenied" },
{ InvalidRange, ERR_PREFIX "InvalidRange" },
@@ -106,6 +412,7 @@ e_data_cal_status_to_string (EDataCalCallStatus status)
const gchar *msg;
} statuses[] = {
{ Success, N_("Success") },
+ { Busy, N_("Backend is busy") },
{ RepositoryOffline, N_("Repository offline") },
{ PermissionDenied, N_("Permission denied") },
{ InvalidRange, N_("Invalid range") },
@@ -195,6 +502,19 @@ data_cal_return_error (GDBusMethodInvocation *invocation, const GError *perror,
g_error_free (error);
}
+
+EDataCal *
+e_data_cal_new (ECalBackend *backend, ESource *source)
+{
+ EDataCal *cal;
+
+ cal = g_object_new (E_TYPE_DATA_CAL, NULL);
+ cal->priv->backend = g_object_ref (backend);
+ cal->priv->source = g_object_ref (source);
+
+ return cal;
+}
+
/**
* e_data_cal_get_source:
* @cal: an #EDataCal
@@ -208,360 +528,364 @@ data_cal_return_error (GDBusMethodInvocation *invocation, const GError *perror,
ESource*
e_data_cal_get_source (EDataCal *cal)
{
- return cal->priv->source;
+ return cal->priv->source;
}
ECalBackend*
e_data_cal_get_backend (EDataCal *cal)
{
- return cal->priv->backend;
+ return cal->priv->backend;
}
-/* EDataCal::getUri method */
-static gboolean
-impl_Cal_getUri (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
+/**
+ * e_data_cal_register_gdbus_object:
+ *
+ * Registers GDBus object of this EDataCal.
+ *
+ * Since: 2.32
+ **/
+guint
+e_data_cal_register_gdbus_object (EDataCal *cal, GDBusConnection *connection, const gchar *object_path, GError **error)
{
- e_gdbus_cal_complete_get_uri (object, invocation, e_cal_backend_get_uri (cal->priv->backend));
+ g_return_val_if_fail (cal != NULL, 0);
+ g_return_val_if_fail (E_IS_DATA_CAL (cal), 0);
+ g_return_val_if_fail (connection != NULL, 0);
+ g_return_val_if_fail (object_path != NULL, 0);
- return TRUE;
+ return e_gdbus_cal_register_object (cal->priv->gdbus_object, connection, object_path, error);
}
-/* EDataCal::getCacheDir method */
static gboolean
-impl_Cal_getCacheDir (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
+impl_Cal_open (EGdbusCal *object, GDBusMethodInvocation *invocation, gboolean in_only_if_exists, EDataCal *cal)
{
- e_gdbus_cal_complete_get_cache_dir (object, invocation, e_cal_backend_get_cache_dir (cal->priv->backend));
+ OperationData *op;
+
+ op = op_new (OP_OPEN, cal);
+ op->d.only_if_exists = in_only_if_exists;
+
+ e_gdbus_cal_complete_open (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::open method */
static gboolean
-impl_Cal_open (EGdbusCal *object, GDBusMethodInvocation *invocation, gboolean only_if_exists, const gchar *username, const gchar *password, EDataCal *cal)
+impl_Cal_remove (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
{
- e_cal_backend_open (cal->priv->backend, cal, invocation, only_if_exists, username, password);
+ OperationData *op;
+
+ op = op_new (OP_REMOVE, cal);
+
+ e_gdbus_cal_complete_remove (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::refresh method */
static gboolean
impl_Cal_refresh (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
{
- e_cal_backend_refresh (cal->priv->backend, cal, invocation);
+ OperationData *op;
+
+ op = op_new (OP_REFRESH, cal);
+
+ e_gdbus_cal_complete_refresh (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::close method */
static gboolean
-impl_Cal_close (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
+impl_Cal_getBackendProperty (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_prop_name, EDataCal *cal)
{
- e_cal_backend_remove_client (cal->priv->backend, cal);
- e_gdbus_cal_complete_close (object, invocation);
+ OperationData *op;
- g_object_unref (cal);
+ op = op_new (OP_GET_BACKEND_PROPERTY, cal);
+ op->d.prop_name = g_strdup (in_prop_name);
+
+ e_gdbus_cal_complete_get_backend_property (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::remove method */
static gboolean
-impl_Cal_remove (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
+impl_Cal_setBackendProperty (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_prop_name_value, EDataCal *cal)
{
- e_cal_backend_remove (cal->priv->backend, cal, invocation);
+ OperationData *op;
- return TRUE;
-}
+ op = op_new (OP_SET_BACKEND_PROPERTY, cal);
+ g_return_val_if_fail (e_gdbus_cal_decode_set_backend_property (in_prop_name_value, &op->d.sbp.prop_name, &op->d.sbp.prop_value), FALSE);
-/* EDataCal::isReadOnly method */
-static gboolean
-impl_Cal_isReadOnly (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
-{
- e_cal_backend_is_read_only (cal->priv->backend, cal);
- e_gdbus_cal_complete_is_read_only (object, invocation);
+ e_gdbus_cal_complete_set_backend_property (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::getCalAddress method */
static gboolean
-impl_Cal_getCalAddress (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
+impl_Cal_getObject (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_uid_rid, EDataCal *cal)
{
- e_cal_backend_get_cal_address (cal->priv->backend, cal, invocation);
+ OperationData *op;
- return TRUE;
-}
+ op = op_new (OP_GET_OBJECT, cal);
+ g_return_val_if_fail (e_gdbus_cal_decode_get_object (in_uid_rid, &op->d.ur.uid, &op->d.ur.rid), FALSE);
-/* EDataCal::getAlarmEmailAddress method */
-static gboolean
-impl_Cal_getAlarmEmailAddress (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
-{
- e_cal_backend_get_alarm_email_address (cal->priv->backend, cal, invocation);
+ e_gdbus_cal_complete_get_object (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::getLdapAttribute method */
static gboolean
-impl_Cal_getLdapAttribute (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
+impl_Cal_getObjectList (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_sexp, EDataCal *cal)
{
- e_cal_backend_get_ldap_attribute (cal->priv->backend, cal, invocation);
+ OperationData *op;
- return TRUE;
-}
+ op = op_new (OP_GET_OBJECT_LIST, cal);
+ op->d.sexp = g_strdup (in_sexp);
-/* EDataCal::getSchedulingInformation method */
-static gboolean
-impl_Cal_getSchedulingInformation (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
-{
- e_cal_backend_get_static_capabilities (cal->priv->backend, cal, invocation);
+ e_gdbus_cal_complete_get_object_list (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::setMode method */
static gboolean
-impl_Cal_setMode (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCalMode mode, EDataCal *cal)
+impl_Cal_getFreeBusy (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_start_end_userlist, EDataCal *cal)
{
- e_cal_backend_set_mode (cal->priv->backend, mode);
- e_gdbus_cal_complete_set_mode (object, invocation);
+ OperationData *op;
+ guint start, end;
- return TRUE;
-}
+ op = op_new (OP_GET_FREE_BUSY, cal);
+ g_return_val_if_fail (e_gdbus_cal_decode_get_free_busy (in_start_end_userlist, &start, &end, &op->d.fb.users), FALSE);
-/* EDataCal::getDefaultObject method */
-static gboolean
-impl_Cal_getDefaultObject (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
-{
- e_cal_backend_get_default_object (cal->priv->backend, cal, invocation);
+ op->d.fb.start = (time_t) start;
+ op->d.fb.end = (time_t) end;
+
+ e_gdbus_cal_complete_get_free_busy (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::getObject method */
static gboolean
-impl_Cal_getObject (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *uid, const gchar *rid, EDataCal *cal)
+impl_Cal_createObject (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_calobj, EDataCal *cal)
{
- e_cal_backend_get_object (cal->priv->backend, cal, invocation, uid, rid);
+ OperationData *op;
- return TRUE;
-}
+ op = op_new (OP_CREATE_OBJECT, cal);
+ op->d.co.calobj = g_strdup (in_calobj);
-/* EDataCal::getObjectList method */
-static gboolean
-impl_Cal_getObjectList (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *sexp, EDataCal *cal)
-{
- e_cal_backend_get_object_list (cal->priv->backend, cal, invocation, sexp);
+ e_gdbus_cal_complete_create_object (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::getChanges method */
static gboolean
-impl_Cal_getChanges (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *change_id, EDataCal *cal)
+impl_Cal_modifyObject (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_calobj_mod, EDataCal *cal)
{
- e_cal_backend_get_changes (cal->priv->backend, cal, invocation, change_id);
+ OperationData *op;
+ guint mod;
+
+ op = op_new (OP_MODIFY_OBJECT, cal);
+ g_return_val_if_fail (e_gdbus_cal_decode_modify_object (in_calobj_mod, &op->d.mo.calobj, &mod), FALSE);
+ op->d.mo.mod = mod;
+
+ e_gdbus_cal_complete_modify_object (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::getFreeBusy method */
static gboolean
-impl_Cal_getFreeBusy (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar **user_list, guint start, guint end, EDataCal *cal)
+impl_Cal_removeObject (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_uid_rid_mod, EDataCal *cal)
{
- GList *users = NULL;
+ OperationData *op;
+ guint mod = 0;
- if (user_list) {
- gint i;
+ op = op_new (OP_REMOVE_OBJECT, cal);
+ g_return_val_if_fail (e_gdbus_cal_decode_remove_object (in_uid_rid_mod, &op->d.ro.uid, &op->d.ro.rid, &mod), FALSE);
+ op->d.ro.mod = mod;
- for (i = 0; user_list[i]; i++)
- users = g_list_append (users, (gpointer) user_list[i]);
- }
-
- /* call the backend's get_free_busy method */
- e_cal_backend_get_free_busy (cal->priv->backend, cal, invocation, users, (time_t) start, (time_t) end);
+ e_gdbus_cal_complete_remove_object (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::discardAlarm method */
static gboolean
-impl_Cal_discardAlarm (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *uid, const gchar *auid, EDataCal *cal)
+impl_Cal_receiveObjects (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_calobj, EDataCal *cal)
{
- e_cal_backend_discard_alarm (cal->priv->backend, cal, invocation, uid, auid);
+ OperationData *op;
- return TRUE;
-}
+ op = op_new (OP_RECEIVE_OBJECTS, cal);
+ op->d.co.calobj = g_strdup (in_calobj);
-/* EDataCal::createObject method */
-static gboolean
-impl_Cal_createObject (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *calobj, EDataCal *cal)
-{
- e_cal_backend_create_object (cal->priv->backend, cal, invocation, calobj);
+ e_gdbus_cal_complete_receive_objects (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::modifyObject method */
static gboolean
-impl_Cal_modifyObject (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *calobj, EDataCalObjModType mod, EDataCal *cal)
+impl_Cal_sendObjects (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_calobj, EDataCal *cal)
{
- e_cal_backend_modify_object (cal->priv->backend, cal, invocation, calobj, mod);
+ OperationData *op;
+
+ op = op_new (OP_SEND_OBJECTS, cal);
+ op->d.co.calobj = g_strdup (in_calobj);
+
+ e_gdbus_cal_complete_send_objects (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::removeObject method */
static gboolean
-impl_Cal_removeObject (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *uid, const gchar *rid, EDataCalObjModType mod, EDataCal *cal)
+impl_Cal_getAttachmentUris (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_uid_rid, EDataCal *cal)
{
- if (rid[0] == '\0')
- rid = NULL;
+ OperationData *op;
+
+ op = op_new (OP_GET_ATTACHMENT_URIS, cal);
+ g_return_val_if_fail (e_gdbus_cal_decode_get_attachment_uris (in_uid_rid, &op->d.ur.uid, &op->d.ur.rid), FALSE);
- e_cal_backend_remove_object (cal->priv->backend, cal, invocation, uid, rid, mod);
+ e_gdbus_cal_complete_get_attachment_uris (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::receiveObjects method */
static gboolean
-impl_Cal_receiveObjects (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *calobj, EDataCal *cal)
+impl_Cal_discardAlarm (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_uid_rid_auid, EDataCal *cal)
{
- e_cal_backend_receive_objects (cal->priv->backend, cal, invocation, calobj);
+ OperationData *op;
+
+ op = op_new (OP_DISCARD_ALARM, cal);
+ g_return_val_if_fail (e_gdbus_cal_decode_discard_alarm (in_uid_rid_auid, &op->d.ura.uid, &op->d.ura.rid, &op->d.ura.auid), FALSE);
+
+ e_gdbus_cal_complete_discard_alarm (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::sendObjects method */
static gboolean
-impl_Cal_sendObjects (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *calobj, EDataCal *cal)
+impl_Cal_getView (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_sexp, EDataCal *cal)
{
- e_cal_backend_send_objects (cal->priv->backend, cal, invocation, calobj);
+ OperationData *op;
+
+ op = op_new (OP_GET_VIEW, cal);
+ op->d.sexp = g_strdup (in_sexp);
+
+ e_gdbus_cal_complete_get_view (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::getAttachmentList method */
static gboolean
-impl_Cal_getAttachmentList (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *uid, const gchar *rid, EDataCal *cal)
+impl_Cal_getTimezone (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_tzid, EDataCal *cal)
{
- e_cal_backend_get_attachment_list (cal->priv->backend, cal, invocation, uid, rid);
+ OperationData *op;
- return TRUE;
-}
+ op = op_new (OP_GET_TIMEZONE, cal);
+ op->d.tzid = g_strdup (in_tzid);
-/* Function to get a new EDataCalView path, used by getQuery below */
-static gchar *
-construct_calview_path (void)
-{
- static guint counter = 1;
- return g_strdup_printf ("/org/gnome/evolution/dataserver/CalendarView/%d/%d", getpid(), counter++);
+ e_gdbus_cal_complete_get_timezone (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
+
+ return TRUE;
}
-/* EDataCal::getQuery method */
static gboolean
-impl_Cal_getQuery (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *sexp, EDataCal *cal)
+impl_Cal_addTimezone (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_tzobject, EDataCal *cal)
{
- EDataCalView *query;
- ECalBackendSExp *obj_sexp;
- gchar *path;
- GError *error = NULL;
-
- /* we handle this entirely here, since it doesn't require any
- backend involvement now that we have e_cal_view_start to
- actually kick off the search. */
+ OperationData *op;
- obj_sexp = e_cal_backend_sexp_new (sexp);
- if (!obj_sexp) {
- e_data_cal_notify_query (cal, invocation, EDC_ERROR (InvalidQuery), NULL);
- return TRUE;
- }
+ op = op_new (OP_ADD_TIMEZONE, cal);
+ op->d.tzobject = g_strdup (in_tzobject);
- query = e_data_cal_view_new (cal->priv->backend, obj_sexp);
- e_debug_log (FALSE, E_DEBUG_LOG_DOMAIN_CAL_QUERIES, "%p;%p;NEW;%s;%s", cal, query, sexp, G_OBJECT_TYPE_NAME (cal->priv->backend));
- if (!query) {
- g_object_unref (obj_sexp);
- e_data_cal_notify_query (cal, invocation, EDC_ERROR (OtherError), NULL);
- return TRUE;
- }
+ e_gdbus_cal_complete_add_timezone (cal->priv->gdbus_object, invocation, op->id);
+ e_operation_pool_push (ops_pool, op);
- /* log query to evaluate cache performance */
- e_debug_log (FALSE, E_DEBUG_LOG_DOMAIN_CAL_QUERIES, "%p;%p;REUSED;%s;%s", cal, query, sexp, G_OBJECT_TYPE_NAME (cal->priv->backend));
+ return TRUE;
+}
- path = construct_calview_path ();
- e_data_cal_view_register_gdbus_object (query, g_dbus_method_invocation_get_connection (invocation), path, &error);
+static gboolean
+impl_Cal_authenticateUser (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_credentials, EDataCal *cal)
+{
+ OperationData *op;
- if (error) {
- g_object_unref (query);
- e_data_cal_notify_query (cal, invocation, EDC_ERROR_EX (OtherError, error->message), NULL);
+ if (in_credentials == NULL) {
+ GError *error = e_data_cal_create_error (InvalidArg, NULL);
+ /* Translators: This is prefix to a detailed error message */
+ data_cal_return_error (invocation, error, _("Cannot authenticate user: "));
g_error_free (error);
- g_free (path);
-
return TRUE;
}
- e_cal_backend_add_query (cal->priv->backend, query);
-
- e_data_cal_notify_query (cal, invocation, EDC_ERROR (Success), path);
+ op = op_new (OP_AUTHENTICATE, cal);
+ op->d.credentials = e_credentials_new_strv (in_credentials);
- g_free (path);
+ e_gdbus_cal_complete_authenticate_user (cal->priv->gdbus_object, invocation, NULL);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::getTimezone method */
static gboolean
-impl_Cal_getTimezone (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *tzid, EDataCal *cal)
+impl_Cal_cancelOperation (EGdbusCal *object, GDBusMethodInvocation *invocation, guint in_opid, EDataCal *cal)
{
- e_cal_backend_get_timezone (cal->priv->backend, cal, invocation, tzid);
+ OperationData *op;
+
+ op = op_new (OP_CANCEL_OPERATION, cal);
+ op->d.opid = in_opid;
+
+ e_gdbus_cal_complete_cancel_operation (cal->priv->gdbus_object, invocation, NULL);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::addTimezone method */
static gboolean
-impl_Cal_addTimezone (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *tz, EDataCal *cal)
+impl_Cal_cancelAll (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
{
- e_cal_backend_add_timezone (cal->priv->backend, cal, invocation, tz);
+ OperationData *op;
+
+ op = op_new (OP_CANCEL_ALL, cal);
+
+ e_gdbus_cal_complete_cancel_all (cal->priv->gdbus_object, invocation, NULL);
+ e_operation_pool_push (ops_pool, op);
return TRUE;
}
-/* EDataCal::setDefaultTimezone method */
static gboolean
-impl_Cal_setDefaultTimezone (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *tz, EDataCal *cal)
+impl_Cal_close (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
{
- e_cal_backend_set_default_zone (cal->priv->backend, cal, invocation, tz);
+ OperationData *op;
- return TRUE;
-}
+ op = op_new (OP_CLOSE, cal);
-/* free returned pointer with g_strfreev() */
-static gchar **
-create_str_array_from_glist (GList *lst)
-{
- gchar **seq;
- GList *l;
- gint i;
+ e_gdbus_cal_complete_close (cal->priv->gdbus_object, invocation, NULL);
+ e_operation_pool_push (ops_pool, op);
- seq = g_new0 (gchar *, g_list_length (lst) + 1);
- for (l = lst, i = 0; l; l = l->next, i++) {
- seq[i] = e_util_utf8_make_valid (l->data);
- }
+ g_object_unref (cal);
- return seq;
+ return TRUE;
}
/* free returned pointer with g_strfreev() */
static gchar **
-create_str_array_from_gslist (GSList *lst)
+gslist_to_strv (const GSList *lst)
{
gchar **seq;
- GSList *l;
+ const GSList *l;
gint i;
- seq = g_new0 (gchar *, g_slist_length (lst) + 1);
+ seq = g_new0 (gchar *, g_slist_length ((GSList *) lst) + 1);
for (l = lst, i = 0; l; l = l->next, i++) {
seq[i] = e_util_utf8_make_valid (l->data);
}
@@ -570,215 +894,223 @@ create_str_array_from_gslist (GSList *lst)
}
/**
- * e_data_cal_notify_read_only:
+ * e_data_cal_notify_open:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
- * @read_only: Read only value.
*
- * Notifies listeners of the completion of the is_read_only method call.
+ * Notifies listeners of the completion of the open method call.
*/
void
-e_data_cal_notify_read_only (EDataCal *cal, GError *error, gboolean read_only)
+e_data_cal_respond_open (EDataCal *cal, guint32 opid, GError *error)
{
- g_return_if_fail (cal != NULL);
- g_return_if_fail (E_IS_DATA_CAL (cal));
+ op_complete (cal, opid);
+
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot open calendar: "));
+
+ e_gdbus_cal_emit_open_done (cal->priv->gdbus_object, opid, error);
- if (error) {
- e_data_cal_notify_error (cal, error->message);
+ if (error)
g_error_free (error);
- } else {
- e_gdbus_cal_emit_readonly (cal->priv->gdbus_object, read_only);
- }
}
/**
- * e_data_cal_notify_cal_address:
+ * e_data_cal_respond_remove:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
- * @address: Calendar address.
*
- * Notifies listeners of the completion of the get_cal_address method call.
+ * Notifies listeners of the completion of the remove method call.
*/
void
-e_data_cal_notify_cal_address (EDataCal *cal, EServerMethodContext context, GError *error, const gchar *address)
+e_data_cal_respond_remove (EDataCal *cal, guint32 opid, GError *error)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot retrieve calendar address: %s"));
- g_error_free (error);
- } else {
- gchar *gdbus_address = NULL;
+ op_complete (cal, opid);
- e_gdbus_cal_complete_get_cal_address (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (address, &gdbus_address));
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot remove calendar: "));
- g_free (gdbus_address);
- }
+ e_gdbus_cal_emit_remove_done (cal->priv->gdbus_object, opid, error);
+
+ if (error)
+ g_error_free (error);
+ else
+ e_cal_backend_set_is_removed (cal->priv->backend, TRUE);
}
/**
- * e_data_cal_notify_alarm_email_address:
+ * e_data_cal_respond_refresh:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
- * @address: Alarm email address.
*
- * Notifies listeners of the completion of the get_alarm_email_address method call.
+ * Notifies listeners of the completion of the refresh method call.
+ *
+ * Since: 2.30
*/
void
-e_data_cal_notify_alarm_email_address (EDataCal *cal, EServerMethodContext context, GError *error, const gchar *address)
+e_data_cal_respond_refresh (EDataCal *cal, guint32 opid, GError *error)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot retrieve calendar alarm e-mail address: %s"));
- g_error_free (error);
- } else {
- gchar *gdbus_address = NULL;
+ op_complete (cal, opid);
- e_gdbus_cal_complete_get_alarm_email_address (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (address, &gdbus_address));
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot refresh calendar: "));
- g_free (gdbus_address);
- }
+ e_gdbus_cal_emit_refresh_done (cal->priv->gdbus_object, opid, error);
+
+ if (error)
+ g_error_free (error);
}
/**
- * e_data_cal_notify_ldap_attribute:
+ * e_data_cal_respond_get_backend_property:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
- * @attibute: LDAP attribute.
+ * @prop_value: Value of a property
*
- * Notifies listeners of the completion of the get_ldap_attribute method call.
+ * Notifies listeners of the completion of the get_backend_property method call.
*/
void
-e_data_cal_notify_ldap_attribute (EDataCal *cal, EServerMethodContext context, GError *error, const gchar *attribute)
+e_data_cal_respond_get_backend_property (EDataCal *cal, guint32 opid, GError *error, const gchar *prop_value)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot retrieve calendar's LDAP attribute: %s"));
- g_error_free (error);
- } else {
- gchar *gdbus_attribute = NULL;
+ gchar *gdbus_prop_value = NULL;
- e_gdbus_cal_complete_get_ldap_attribute (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (attribute, &gdbus_attribute));
+ op_complete (cal, opid);
- g_free (gdbus_attribute);
- }
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot retrieve backend property: "));
+
+ e_gdbus_cal_emit_get_backend_property_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (prop_value, &gdbus_prop_value));
+
+ g_free (gdbus_prop_value);
+ if (error)
+ g_error_free (error);
}
/**
- * e_data_cal_notify_static_capabilities:
+ * e_data_cal_respond_set_backend_property:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
- * @capabilities: Static capabilities from the backend.
*
- * Notifies listeners of the completion of the get_static_capabilities method call.
+ * Notifies listeners of the completion of the set_backend_property method call.
*/
void
-e_data_cal_notify_static_capabilities (EDataCal *cal, EServerMethodContext context, GError *error, const gchar *capabilities)
+e_data_cal_respond_set_backend_property (EDataCal *cal, guint32 opid, GError *error)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot retrieve calendar scheduling information: %s"));
- g_error_free (error);
- } else {
- gchar *gdbus_capabilities = NULL;
+ op_complete (cal, opid);
- e_gdbus_cal_complete_get_scheduling_information (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (capabilities, &gdbus_capabilities));
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot set backend property: "));
- g_free (gdbus_capabilities);
- }
+ e_gdbus_cal_emit_set_backend_property_done (cal->priv->gdbus_object, opid, error);
+
+ if (error)
+ g_error_free (error);
}
/**
- * e_data_cal_notify_open:
+ * e_data_cal_respond_get_object:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
+ * @object: The object retrieved as an iCalendar string.
*
- * Notifies listeners of the completion of the open method call.
+ * Notifies listeners of the completion of the get_object method call.
*/
void
-e_data_cal_notify_open (EDataCal *cal, EServerMethodContext context, GError *error)
+e_data_cal_respond_get_object (EDataCal *cal, guint32 opid, GError *error, const gchar *object)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot open calendar: %s"));
+ gchar *gdbus_object = NULL;
+
+ op_complete (cal, opid);
+
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot retrieve calendar object path: "));
+
+ e_gdbus_cal_emit_get_object_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (object, &gdbus_object));
+
+ g_free (gdbus_object);
+ if (error)
g_error_free (error);
- } else
- e_gdbus_cal_complete_open (cal->priv->gdbus_object, invocation);
}
/**
- * e_data_cal_notify_refresh:
+ * e_data_cal_respond_get_object_list:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
+ * @objects: List of retrieved objects.
*
- * Notifies listeners of the completion of the refresh method call.
- *
- * Since: 2.30
+ * Notifies listeners of the completion of the get_object_list method call.
*/
void
-e_data_cal_notify_refresh (EDataCal *cal, EServerMethodContext context, GError *error)
+e_data_cal_respond_get_object_list (EDataCal *cal, guint32 opid, GError *error, const GSList *objects)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot refresh calendar: %s"));
+ gchar **strv_objects;
+
+ op_complete (cal, opid);
+
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot retrieve calendar object list: "));
+
+ strv_objects = gslist_to_strv (objects);
+
+ e_gdbus_cal_emit_get_object_list_done (cal->priv->gdbus_object, opid, error, (const gchar * const *) strv_objects);
+
+ g_strfreev (strv_objects);
+ if (error)
g_error_free (error);
- } else
- e_gdbus_cal_complete_refresh (cal->priv->gdbus_object, invocation);
}
/**
- * e_data_cal_notify_remove:
+ * e_data_cal_respond_get_free_busy:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
*
- * Notifies listeners of the completion of the remove method call.
+ * Notifies listeners of the completion of the get_free_busy method call.
+ * To pass actual free/busy objects to the client use e_data_cal_report_free_busy_data().
*/
void
-e_data_cal_notify_remove (EDataCal *cal, EServerMethodContext context, GError *error)
+e_data_cal_respond_get_free_busy (EDataCal *cal, guint32 opid, GError *error)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot remove calendar: %s"));
+ op_complete (cal, opid);
+
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot retrieve calendar free/busy list: "));
+
+ e_gdbus_cal_emit_get_free_busy_done (cal->priv->gdbus_object, opid, error);
+
+ if (error)
g_error_free (error);
- } else
- e_gdbus_cal_complete_remove (cal->priv->gdbus_object, invocation);
}
/**
- * e_data_cal_notify_object_created:
+ * e_data_cal_respond_create_object:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
* @uid: UID of the object created.
* @object: The object created as an iCalendar string.
*
* Notifies listeners of the completion of the create_object method call.
- */void
-e_data_cal_notify_object_created (EDataCal *cal, EServerMethodContext context, GError *error,
+ */
+void
+e_data_cal_respond_create_object (EDataCal *cal, guint32 opid, GError *error,
const gchar *uid, const gchar *object)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot create calendar object: %s"));
- g_error_free (error);
- } else {
- gchar *gdbus_uid = NULL;
+ gchar *gdbus_uid = NULL;
- e_cal_backend_notify_object_created (cal->priv->backend, object);
- e_gdbus_cal_complete_create_object (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (uid, &gdbus_uid));
+ op_complete (cal, opid);
- g_free (gdbus_uid);
- }
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot create calendar object: "));
+
+ e_gdbus_cal_emit_create_object_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (uid, &gdbus_uid));
+
+ g_free (gdbus_uid);
+ if (error)
+ g_error_free (error);
+ else
+ e_cal_backend_notify_object_created (cal->priv->backend, object);
}
/**
- * e_data_cal_notify_object_modified:
+ * e_data_cal_respond_modify_object:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
* @old_object: The old object as an iCalendar string.
@@ -787,22 +1119,24 @@ e_data_cal_notify_object_created (EDataCal *cal, EServerMethodContext context, G
* Notifies listeners of the completion of the modify_object method call.
*/
void
-e_data_cal_notify_object_modified (EDataCal *cal, EServerMethodContext context, GError *error,
- const gchar *old_object, const gchar *object)
+e_data_cal_respond_modify_object (EDataCal *cal, guint32 opid, GError *error,
+ const gchar *old_object, const gchar *object)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot modify calendar object: %s"));
+ op_complete (cal, opid);
+
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot modify calendar object: "));
+
+ e_gdbus_cal_emit_modify_object_done (cal->priv->gdbus_object, opid, error);
+
+ if (error)
g_error_free (error);
- } else {
+ else
e_cal_backend_notify_object_modified (cal->priv->backend, old_object, object);
- e_gdbus_cal_complete_modify_object (cal->priv->gdbus_object, invocation);
- }
}
/**
- * e_data_cal_notify_object_removed:
+ * e_data_cal_respond_remove_object:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
* @uid: UID of the removed object.
@@ -813,60 +1147,45 @@ e_data_cal_notify_object_modified (EDataCal *cal, EServerMethodContext context,
* Notifies listeners of the completion of the remove_object method call.
*/
void
-e_data_cal_notify_object_removed (EDataCal *cal, EServerMethodContext context, GError *error,
+e_data_cal_respond_remove_object (EDataCal *cal, guint32 opid, GError *error,
const ECalComponentId *id, const gchar *old_object, const gchar *object)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot remove calendar object: %s"));
+ op_complete (cal, opid);
+
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot remove calendar object: "));
+
+ e_gdbus_cal_emit_remove_object_done (cal->priv->gdbus_object, opid, error);
+
+ if (error)
g_error_free (error);
- } else {
+ else
e_cal_backend_notify_object_removed (cal->priv->backend, id, old_object, object);
- e_gdbus_cal_complete_remove_object (cal->priv->gdbus_object, invocation);
- }
}
/**
- * e_data_cal_notify_objects_received:
+ * e_data_cal_respond_receive_objects:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
*
* Notifies listeners of the completion of the receive_objects method call.
*/
void
-e_data_cal_notify_objects_received (EDataCal *cal, EServerMethodContext context, GError *error)
+e_data_cal_respond_receive_objects (EDataCal *cal, guint32 opid, GError *error)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot receive calendar objects: %s"));
- g_error_free (error);
- } else
- e_gdbus_cal_complete_receive_objects (cal->priv->gdbus_object, invocation);
-}
+ op_complete (cal, opid);
-/**
- * e_data_cal_notify_alarm_discarded:
- * @cal: A calendar client interface.
- * @error: Operation error, if any, automatically freed if passed it.
- *
- * Notifies listeners of the completion of the discard_alarm method call.
- */
-void
-e_data_cal_notify_alarm_discarded (EDataCal *cal, EServerMethodContext context, GError *error)
-{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot discard calendar alarm: %s"));
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot receive calendar objects: "));
+
+ e_gdbus_cal_emit_receive_objects_done (cal->priv->gdbus_object, opid, error);
+
+ if (error)
g_error_free (error);
- } else
- e_gdbus_cal_complete_discard_alarm (cal->priv->gdbus_object, invocation);
}
/**
- * e_data_cal_notify_objects_sent:
+ * e_data_cal_respond_send_objects:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
* @users: List of users.
@@ -875,330 +1194,219 @@ e_data_cal_notify_alarm_discarded (EDataCal *cal, EServerMethodContext context,
* Notifies listeners of the completion of the send_objects method call.
*/
void
-e_data_cal_notify_objects_sent (EDataCal *cal, EServerMethodContext context, GError *error, GList *users, const gchar *calobj)
+e_data_cal_respond_send_objects (EDataCal *cal, guint32 opid, GError *error, const GSList *users, const gchar *calobj)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot send calendar objects: %s"));
- g_error_free (error);
- } else {
- gchar **users_array = create_str_array_from_glist (users);
- gchar *gdbus_calobj = NULL;
+ gchar **strv_users_calobj;
- e_gdbus_cal_complete_send_objects (cal->priv->gdbus_object, invocation, (const gchar * const *) users_array, e_util_ensure_gdbus_string (calobj, &gdbus_calobj));
+ op_complete (cal, opid);
- g_free (gdbus_calobj);
- g_strfreev (users_array);
- }
-}
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Cannot send calendar objects: "));
-/**
- * e_data_cal_notify_default_object:
- * @cal: A calendar client interface.
- * @error: Operation error, if any, automatically freed if passed it.
- * @object: The default object as an iCalendar string.
- *
- * Notifies listeners of the completion of the get_default_object method call.
- */
-void
-e_data_cal_notify_default_object (EDataCal *cal, EServerMethodContext context, GError *error, const gchar *object)
-{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot retrieve default calendar object path: %s"));
- g_error_free (error);
- } else {
- gchar *gdbus_object = NULL;
+ strv_users_calobj = e_gdbus_cal_encode_send_objects (calobj, users);
- e_gdbus_cal_complete_get_default_object (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (object, &gdbus_object));
+ e_gdbus_cal_emit_send_objects_done (cal->priv->gdbus_object, opid, error, (const gchar * const *) strv_users_calobj);
- g_free (gdbus_object);
- }
+ g_strfreev (strv_users_calobj);
+ if (error)
+ g_error_free (error);
}
/**
- * e_data_cal_notify_object:
+ * e_data_cal_respond_get_attachment_uris:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
- * @object: The object retrieved as an iCalendar string.
+ * @attachment_uris: List of retrieved attachment uri's.
*
- * Notifies listeners of the completion of the get_object method call.
- */
+ * Notifies listeners of the completion of the get_attachment_uris method call.
+ **/
void
-e_data_cal_notify_object (EDataCal *cal, EServerMethodContext context, GError *error, const gchar *object)
+e_data_cal_respond_get_attachment_uris (EDataCal *cal, guint32 opid, GError *error, const GSList *attachment_uris)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot retrieve calendar object path: %s"));
- g_error_free (error);
- } else {
- gchar *gdbus_object = NULL;
+ gchar **strv_attachment_uris;
- e_gdbus_cal_complete_get_object (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (object, &gdbus_object));
+ op_complete (cal, opid);
- g_free (gdbus_object);
- }
-}
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Could not retrieve attachment uris: "));
-/**
- * e_data_cal_notify_object_list:
- * @cal: A calendar client interface.
- * @error: Operation error, if any, automatically freed if passed it.
- * @objects: List of retrieved objects.
- *
- * Notifies listeners of the completion of the get_object_list method call.
- */
-void
-e_data_cal_notify_object_list (EDataCal *cal, EServerMethodContext context, GError *error, GList *objects)
-{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot retrieve calendar object list: %s"));
- g_error_free (error);
- } else {
- gchar **seq = create_str_array_from_glist (objects);
+ strv_attachment_uris = gslist_to_strv (attachment_uris);
- e_gdbus_cal_complete_get_object_list (cal->priv->gdbus_object, invocation, (const gchar * const *) seq);
+ e_gdbus_cal_emit_get_attachment_uris_done (cal->priv->gdbus_object, opid, error, (const gchar * const *) strv_attachment_uris);
- g_strfreev (seq);
- }
+ g_strfreev (strv_attachment_uris);
+ if (error)
+ g_error_free (error);
}
/**
- * e_data_cal_notify_attachment_list:
+ * e_data_cal_respond_discard_alarm:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
- * @attachments: List of retrieved attachment uri's.
*
- * Notifies listeners of the completion of the get_attachment_list method call.+ */
+ * Notifies listeners of the completion of the discard_alarm method call.
+ **/
void
-e_data_cal_notify_attachment_list (EDataCal *cal, EServerMethodContext context, GError *error, GSList *attachments)
+e_data_cal_respond_discard_alarm (EDataCal *cal, guint32 opid, GError *error)
{
- GDBusMethodInvocation *invocation = context;
- gchar **seq;
+ op_complete (cal, opid);
- seq = create_str_array_from_gslist (attachments);
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Could not discard alarm: "));
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Could not retrieve attachment list: %s"));
- g_error_free (error);
- } else
- e_gdbus_cal_complete_get_attachment_list (cal->priv->gdbus_object, invocation, (const gchar * const *) seq);
+ e_gdbus_cal_emit_discard_alarm_done (cal->priv->gdbus_object, opid, error);
- g_strfreev (seq);
+ if (error)
+ g_error_free (error);
}
/**
- * e_data_cal_notify_query:
+ * e_data_cal_respond_get_view:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
- * @query: The new live query.
+ * @view_path: The new live view path.
*
- * Notifies listeners of the completion of the get_query method call.
+ * Notifies listeners of the completion of the get_view method call.
*/
void
-e_data_cal_notify_query (EDataCal *cal, EServerMethodContext context, GError *error, const gchar *query)
-{
- /*
- * Only have a seperate notify function to follow suit with the rest of this
- * file - it'd be much easier to just do the return in the above function
- */
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Could not complete calendar query: %s"));
- g_error_free (error);
- } else {
- gchar *gdbus_query = NULL;
+e_data_cal_respond_get_view (EDataCal *cal, guint32 opid, GError *error, const gchar *view_path)
+{
+ gchar *gdbus_view_path = NULL;
- e_gdbus_cal_complete_get_query (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (query, &gdbus_query));
+ op_complete (cal, opid);
- g_free (gdbus_query);
- }
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Could not get calendar view path: "));
+
+ e_gdbus_cal_emit_get_view_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (view_path, &gdbus_view_path));
+
+ g_free (gdbus_view_path);
+ if (error)
+ g_error_free (error);
}
/**
- * e_data_cal_notify_timezone_requested:
+ * e_data_cal_respond_get_timezone:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
- * @object: The requested timezone as an iCalendar string.
+ * @tzobject: The requested timezone as an iCalendar string.
*
* Notifies listeners of the completion of the get_timezone method call.
*/
void
-e_data_cal_notify_timezone_requested (EDataCal *cal, EServerMethodContext context, GError *error, const gchar *object)
+e_data_cal_respond_get_timezone (EDataCal *cal, guint32 opid, GError *error, const gchar *tzobject)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Could not retrieve calendar time zone: %s"));
- g_error_free (error);
- } else {
- gchar *gdbus_object = NULL;
+ gchar *gdbus_tzobject = NULL;
- e_gdbus_cal_complete_get_timezone (cal->priv->gdbus_object, invocation, e_util_ensure_gdbus_string (object, &gdbus_object));
+ op_complete (cal, opid);
- g_free (gdbus_object);
- }
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Could not retrieve calendar time zone: "));
+
+ e_gdbus_cal_emit_get_timezone_done (cal->priv->gdbus_object, opid, error, e_util_ensure_gdbus_string (tzobject, &gdbus_tzobject));
+
+ g_free (gdbus_tzobject);
+ if (error)
+ g_error_free (error);
}
/**
* e_data_cal_notify_timezone_added:
* @cal: A calendar client interface.
* @error: Operation error, if any, automatically freed if passed it.
- * @tzid: ID of the added timezone.
*
* Notifies listeners of the completion of the add_timezone method call.
*/
void
-e_data_cal_notify_timezone_added (EDataCal *cal, EServerMethodContext context, GError *error, const gchar *tzid)
+e_data_cal_respond_add_timezone (EDataCal *cal, guint32 opid, GError *error)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Could not add calendar time zone: %s"));
+ op_complete (cal, opid);
+
+ /* Translators: This is prefix to a detailed error message */
+ g_prefix_error (&error, "%s", _("Could not add calendar time zone: "));
+
+ e_gdbus_cal_emit_add_timezone_done (cal->priv->gdbus_object, opid, error);
+
+ if (error)
g_error_free (error);
- } else
- e_gdbus_cal_complete_add_timezone (cal->priv->gdbus_object, invocation);
}
-/**
- * e_data_cal_notify_default_timezone_set:
- * @cal: A calendar client interface.
- * @error: Operation error, if any, automatically freed if passed it.
- *
- * Notifies listeners of the completion of the set_default_timezone method call.
- */
void
-e_data_cal_notify_default_timezone_set (EDataCal *cal, EServerMethodContext context, GError *error)
+e_data_cal_report_error (EDataCal *cal, const gchar *message)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Could not set default calendar time zone: %s"));
- g_error_free (error);
- } else
- e_gdbus_cal_complete_set_default_timezone (cal->priv->gdbus_object, invocation);
+ g_return_if_fail (cal != NULL);
+ g_return_if_fail (message != NULL);
+
+ e_gdbus_cal_emit_backend_error (cal->priv->gdbus_object, message);
}
-/**
- * e_data_cal_notify_changes:
- * @cal: A calendar client interface.
- * @error: Operation error, if any, automatically freed if passed it.
- * @adds: List of additions.
- * @modifies: List of modifications.
- * @deletes: List of removals.
- *
- * Notifies listeners of the completion of the get_changes method call.
- */
void
-e_data_cal_notify_changes (EDataCal *cal, EServerMethodContext context, GError *error,
- GList *adds, GList *modifies, GList *deletes)
+e_data_cal_report_readonly (EDataCal *cal, gboolean readonly)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot retrieve calendar changes: %s"));
- g_error_free (error);
- } else {
- gchar **additions, **modifications, **removals;
-
- additions = create_str_array_from_glist (adds);
- modifications = create_str_array_from_glist (modifies);
- removals = create_str_array_from_glist (deletes);
-
- e_gdbus_cal_complete_get_changes (cal->priv->gdbus_object, invocation, (const gchar * const *) additions, (const gchar * const *) modifications, (const gchar * const *) removals);
+ g_return_if_fail (cal != NULL);
- g_strfreev (additions);
- g_strfreev (modifications);
- g_strfreev (removals);
- }
+ e_gdbus_cal_emit_readonly (cal->priv->gdbus_object, readonly);
}
-/**
- * e_data_cal_notify_free_busy:
- * @cal: A calendar client interface.
- * @error: Operation error, if any, automatically freed if passed it.
- * @freebusy: List of free/busy objects.
- *
- * Notifies listeners of the completion of the get_free_busy method call.
- */
void
-e_data_cal_notify_free_busy (EDataCal *cal, EServerMethodContext context, GError *error, GList *freebusy)
+e_data_cal_report_online (EDataCal *cal, gboolean is_online)
{
- GDBusMethodInvocation *invocation = context;
- if (error) {
- /* Translators: The '%s' is replaced with a detailed error message */
- data_cal_return_error (invocation, error, _("Cannot retrieve calendar free/busy list: %s"));
- g_error_free (error);
- } else {
- gchar **seq;
-
- seq = create_str_array_from_glist (freebusy);
-
- e_gdbus_cal_complete_get_free_busy (cal->priv->gdbus_object, invocation, (const gchar * const *) seq);
+ g_return_if_fail (cal != NULL);
- g_strfreev (seq);
- }
+ e_gdbus_cal_emit_online (cal->priv->gdbus_object, is_online);
}
-/**
- * e_data_cal_notify_mode:
- * @cal: A calendar client interface.
- * @status: Status of the mode set.
- * @mode: The current mode.
- *
- * Notifies the listener of the results of a set_mode call.
- **/
+/* credentilas contains extra information for a source for which authentication is requested.
+ This parameter can be NULL to indicate "for this calendar".
+*/
void
-e_data_cal_notify_mode (EDataCal *cal,
- EDataCalViewListenerSetModeStatus status,
- EDataCalMode mode)
+e_data_cal_report_auth_required (EDataCal *cal, const ECredentials *credentials)
{
+ gchar *empty_strv[2];
+ gchar **strv = NULL;
+
g_return_if_fail (cal != NULL);
- g_return_if_fail (E_IS_DATA_CAL (cal));
- e_gdbus_cal_emit_mode (cal->priv->gdbus_object, mode);
+ empty_strv[0] = NULL;
+ empty_strv[1] = NULL;
+
+ if (credentials)
+ strv = e_credentials_to_strv (credentials);
+
+ e_gdbus_cal_emit_auth_required (cal->priv->gdbus_object, (const gchar * const *) (strv ? strv : empty_strv));
+
+ g_strfreev (strv);
}
-/**
- * e_data_cal_notify_auth_required:
- * @cal: A calendar client interface.
- *
- * Notifies listeners that authorization is required to open the calendar.
- */
+/* Reports to associated client that opening phase of the cal is finished.
+ error being NULL means successfully, otherwise reports an error which happened
+ during opening phase. By opening phase is meant a process including successfull
+ authentication to the server/storage.
+*/
void
-e_data_cal_notify_auth_required (EDataCal *cal)
+e_data_cal_report_opened (EDataCal *cal, const GError *error)
{
- g_return_if_fail (cal != NULL);
- g_return_if_fail (E_IS_DATA_CAL (cal));
+ gchar **strv_error;
- e_gdbus_cal_emit_auth_required (cal->priv->gdbus_object);
+ strv_error = e_gdbus_templates_encode_error (error);
+
+ e_gdbus_cal_emit_opened (cal->priv->gdbus_object, (const gchar * const *) strv_error);
+
+ g_strfreev (strv_error);
}
-/**
- * e_data_cal_notify_error
- * @cal: A calendar client interface.
- * @message: Error message.
- *
- * Notify a calendar client of an error occurred in the backend.
- */
void
-e_data_cal_notify_error (EDataCal *cal, const gchar *message)
+e_data_cal_report_free_busy_data (EDataCal *cal, const GSList *freebusy)
{
- gchar *gdbus_message = NULL;
+ gchar **strv_freebusy;
g_return_if_fail (cal != NULL);
- g_return_if_fail (E_IS_DATA_CAL (cal));
- e_gdbus_cal_emit_backend_error (cal->priv->gdbus_object, e_util_ensure_gdbus_string (message, &gdbus_message));
+ strv_freebusy = gslist_to_strv (freebusy);
- g_free (gdbus_message);
+ e_gdbus_cal_emit_free_busy_data (cal->priv->gdbus_object, (const gchar * const *) strv_freebusy);
+
+ g_strfreev (strv_freebusy);
}
/* Instance init */
@@ -1207,52 +1415,76 @@ e_data_cal_init (EDataCal *ecal)
{
EGdbusCal *gdbus_object;
- ecal->priv = G_TYPE_INSTANCE_GET_PRIVATE (
- ecal, E_TYPE_DATA_CAL, EDataCalPrivate);
+ ecal->priv = G_TYPE_INSTANCE_GET_PRIVATE (ecal, E_TYPE_DATA_CAL, EDataCalPrivate);
ecal->priv->gdbus_object = e_gdbus_cal_stub_new ();
+ ecal->priv->pending_ops = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
+ g_static_rec_mutex_init (&ecal->priv->pending_ops_lock);
gdbus_object = ecal->priv->gdbus_object;
- g_signal_connect (gdbus_object, "handle-get-uri", G_CALLBACK (impl_Cal_getUri), ecal);
- g_signal_connect (gdbus_object, "handle-get-cache-dir", G_CALLBACK (impl_Cal_getCacheDir), ecal);
g_signal_connect (gdbus_object, "handle-open", G_CALLBACK (impl_Cal_open), ecal);
- g_signal_connect (gdbus_object, "handle-refresh", G_CALLBACK (impl_Cal_refresh), ecal);
- g_signal_connect (gdbus_object, "handle-close", G_CALLBACK (impl_Cal_close), ecal);
+ g_signal_connect (gdbus_object, "handle-authenticate-user", G_CALLBACK (impl_Cal_authenticateUser), ecal);
g_signal_connect (gdbus_object, "handle-remove", G_CALLBACK (impl_Cal_remove), ecal);
- g_signal_connect (gdbus_object, "handle-is-read-only", G_CALLBACK (impl_Cal_isReadOnly), ecal);
- g_signal_connect (gdbus_object, "handle-get-cal-address", G_CALLBACK (impl_Cal_getCalAddress), ecal);
- g_signal_connect (gdbus_object, "handle-get-alarm-email-address", G_CALLBACK (impl_Cal_getAlarmEmailAddress), ecal);
- g_signal_connect (gdbus_object, "handle-get-ldap-attribute", G_CALLBACK (impl_Cal_getLdapAttribute), ecal);
- g_signal_connect (gdbus_object, "handle-get-scheduling-information", G_CALLBACK (impl_Cal_getSchedulingInformation), ecal);
- g_signal_connect (gdbus_object, "handle-set-mode", G_CALLBACK (impl_Cal_setMode), ecal);
- g_signal_connect (gdbus_object, "handle-get-default-object", G_CALLBACK (impl_Cal_getDefaultObject), ecal);
+ g_signal_connect (gdbus_object, "handle-refresh", G_CALLBACK (impl_Cal_refresh), ecal);
+ g_signal_connect (gdbus_object, "handle-get-backend-property", G_CALLBACK (impl_Cal_getBackendProperty), ecal);
+ g_signal_connect (gdbus_object, "handle-set-backend-property", G_CALLBACK (impl_Cal_setBackendProperty), ecal);
g_signal_connect (gdbus_object, "handle-get-object", G_CALLBACK (impl_Cal_getObject), ecal);
g_signal_connect (gdbus_object, "handle-get-object-list", G_CALLBACK (impl_Cal_getObjectList), ecal);
- g_signal_connect (gdbus_object, "handle-get-changes", G_CALLBACK (impl_Cal_getChanges), ecal);
g_signal_connect (gdbus_object, "handle-get-free-busy", G_CALLBACK (impl_Cal_getFreeBusy), ecal);
- g_signal_connect (gdbus_object, "handle-discard-alarm", G_CALLBACK (impl_Cal_discardAlarm), ecal);
g_signal_connect (gdbus_object, "handle-create-object", G_CALLBACK (impl_Cal_createObject), ecal);
g_signal_connect (gdbus_object, "handle-modify-object", G_CALLBACK (impl_Cal_modifyObject), ecal);
g_signal_connect (gdbus_object, "handle-remove-object", G_CALLBACK (impl_Cal_removeObject), ecal);
g_signal_connect (gdbus_object, "handle-receive-objects", G_CALLBACK (impl_Cal_receiveObjects), ecal);
g_signal_connect (gdbus_object, "handle-send-objects", G_CALLBACK (impl_Cal_sendObjects), ecal);
- g_signal_connect (gdbus_object, "handle-get-attachment-list", G_CALLBACK (impl_Cal_getAttachmentList), ecal);
- g_signal_connect (gdbus_object, "handle-get-query", G_CALLBACK (impl_Cal_getQuery), ecal);
+ g_signal_connect (gdbus_object, "handle-get-attachment-uris", G_CALLBACK (impl_Cal_getAttachmentUris), ecal);
+ g_signal_connect (gdbus_object, "handle-discard-alarm", G_CALLBACK (impl_Cal_discardAlarm), ecal);
+ g_signal_connect (gdbus_object, "handle-get-view", G_CALLBACK (impl_Cal_getView), ecal);
g_signal_connect (gdbus_object, "handle-get-timezone", G_CALLBACK (impl_Cal_getTimezone), ecal);
g_signal_connect (gdbus_object, "handle-add-timezone", G_CALLBACK (impl_Cal_addTimezone), ecal);
- g_signal_connect (gdbus_object, "handle-set-default-timezone", G_CALLBACK (impl_Cal_setDefaultTimezone), ecal);
+ g_signal_connect (gdbus_object, "handle-cancel-operation", G_CALLBACK (impl_Cal_cancelOperation), ecal);
+ g_signal_connect (gdbus_object, "handle-cancel-all", G_CALLBACK (impl_Cal_cancelAll), ecal);
+ g_signal_connect (gdbus_object, "handle-close", G_CALLBACK (impl_Cal_close), ecal);
}
static void
-e_data_cal_finalize (GObject *object)
+data_cal_dispose (GObject *object)
{
EDataCal *cal = E_DATA_CAL (object);
g_return_if_fail (cal != NULL);
- g_object_unref (cal->priv->gdbus_object);
+ if (cal->priv->backend) {
+ g_object_unref (cal->priv->backend);
+ cal->priv->backend = NULL;
+ }
+
+ if (cal->priv->source) {
+ g_object_unref (cal->priv->source);
+ cal->priv->source = NULL;
+ }
+
+ G_OBJECT_CLASS (e_data_cal_parent_class)->dispose (object);
+}
+
+static void
+data_cal_finalize (GObject *object)
+{
+ EDataCal *cal = E_DATA_CAL (object);
+
+ g_return_if_fail (cal != NULL);
+
+ if (cal->priv->pending_ops) {
+ g_hash_table_destroy (cal->priv->pending_ops);
+ cal->priv->pending_ops = NULL;
+ }
+
+ g_static_rec_mutex_free (&cal->priv->pending_ops_lock);
+
+ if (cal->priv->gdbus_object) {
+ g_object_unref (cal->priv->gdbus_object);
+ cal->priv->gdbus_object = NULL;
+ }
- /* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_data_cal_parent_class)->finalize (object);
}
@@ -1265,33 +1497,9 @@ e_data_cal_class_init (EDataCalClass *klass)
g_type_class_add_private (klass, sizeof (EDataCalPrivate));
object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = e_data_cal_finalize;
-}
-
-EDataCal *
-e_data_cal_new (ECalBackend *backend, ESource *source)
-{
- EDataCal *cal;
- cal = g_object_new (E_TYPE_DATA_CAL, NULL);
- cal->priv->backend = backend;
- cal->priv->source = source;
- return cal;
-}
+ object_class->dispose = data_cal_dispose;
+ object_class->finalize = data_cal_finalize;
-/**
- * e_data_cal_register_gdbus_object:
- *
- * Registers GDBus object of this EDataCal.
- *
- * Since: 2.32
- **/
-guint
-e_data_cal_register_gdbus_object (EDataCal *cal, GDBusConnection *connection, const gchar *object_path, GError **error)
-{
- g_return_val_if_fail (cal != NULL, 0);
- g_return_val_if_fail (E_IS_DATA_CAL (cal), 0);
- g_return_val_if_fail (connection != NULL, 0);
- g_return_val_if_fail (object_path != NULL, 0);
-
- return e_gdbus_cal_register_object (cal->priv->gdbus_object, connection, object_path, error);
+ if (!ops_pool)
+ ops_pool = e_operation_pool_new (10, operation_thread, NULL);
}
diff --git a/calendar/libedata-cal/e-data-cal.h b/calendar/libedata-cal/e-data-cal.h
index 05a270d..9d8b553 100644
--- a/calendar/libedata-cal/e-data-cal.h
+++ b/calendar/libedata-cal/e-data-cal.h
@@ -90,6 +90,28 @@ const gchar *e_data_cal_status_to_string (EDataCalCallStatus status);
} \
} G_STMT_END
+/**
+ * e_return_data_cal_error_val_if_fail:
+ *
+ * Same as e_return_data_cal_error_if_fail(), only returns FALSE on a failure
+ *
+ * Since: 3.2
+ **/
+#define e_return_data_cal_error_val_if_fail(expr, _code) \
+ G_STMT_START { \
+ if (G_LIKELY (expr)) { \
+ } else { \
+ g_log (G_LOG_DOMAIN, \
+ G_LOG_LEVEL_CRITICAL, \
+ "file %s: line %d (%s): assertion `%s' failed", \
+ __FILE__, __LINE__, G_STRFUNC, #expr); \
+ g_set_error (error, E_DATA_CAL_ERROR, (_code), \
+ "file %s: line %d (%s): assertion `%s' failed", \
+ __FILE__, __LINE__, G_STRFUNC, #expr); \
+ return FALSE; \
+ } \
+ } G_STMT_END
+
typedef struct _EDataCalPrivate EDataCalPrivate;
struct _EDataCal {
@@ -103,70 +125,36 @@ struct _EDataCalClass {
GType e_data_cal_get_type (void);
-EDataCal *e_data_cal_new (ECalBackend *backend, ESource *source);
-
-guint e_data_cal_register_gdbus_object (EDataCal *cal, GDBusConnection *connection, const gchar *object_path, GError **error);
-
-ECalBackend *e_data_cal_get_backend (EDataCal *cal);
-ESource* e_data_cal_get_source (EDataCal *cal);
-
-void e_data_cal_notify_read_only (EDataCal *cal, GError *error,
- gboolean read_only);
-void e_data_cal_notify_cal_address (EDataCal *cal, EServerMethodContext context, GError *error,
- const gchar *address);
-void e_data_cal_notify_alarm_email_address (EDataCal *cal, EServerMethodContext context, GError *error,
- const gchar *address);
-void e_data_cal_notify_ldap_attribute (EDataCal *cal, EServerMethodContext context, GError *error,
- const gchar *attribute);
-void e_data_cal_notify_static_capabilities (EDataCal *cal, EServerMethodContext context, GError *error,
- const gchar *capabilities);
-
-void e_data_cal_notify_open (EDataCal *cal, EServerMethodContext context, GError *error);
-void e_data_cal_notify_refresh (EDataCal *cal, EServerMethodContext context, GError *error);
-void e_data_cal_notify_remove (EDataCal *cal, EServerMethodContext context, GError *error);
-
-void e_data_cal_notify_object_created (EDataCal *cal, EServerMethodContext context, GError *error,
- const gchar *uid, const gchar *object);
-void e_data_cal_notify_object_modified (EDataCal *cal, EServerMethodContext context, GError *error,
- const gchar *old_object, const gchar *object);
-void e_data_cal_notify_object_removed (EDataCal *cal, EServerMethodContext context, GError *error,
- const ECalComponentId *id, const gchar *old_object, const gchar *object);
-void e_data_cal_notify_alarm_discarded (EDataCal *cal, EServerMethodContext context, GError *error);
-
-void e_data_cal_notify_objects_received (EDataCal *cal, EServerMethodContext context, GError *error);
-void e_data_cal_notify_objects_sent (EDataCal *cal, EServerMethodContext context, GError *error, GList *users,
- const gchar *calobj);
-
-void e_data_cal_notify_default_object (EDataCal *cal, EServerMethodContext context, GError *error,
- const gchar *object);
-void e_data_cal_notify_object (EDataCal *cal, EServerMethodContext context, GError *error,
- const gchar *object);
-void e_data_cal_notify_object_list (EDataCal *cal, EServerMethodContext context, GError *error,
- GList *objects);
-
-void e_data_cal_notify_query (EDataCal *cal, EServerMethodContext context, GError *error,
- const gchar *query_path);
-
-void e_data_cal_notify_timezone_requested (EDataCal *cal, EServerMethodContext context, GError *error,
- const gchar *object);
-void e_data_cal_notify_timezone_added (EDataCal *cal, EServerMethodContext context, GError *error,
- const gchar *tzid);
-void e_data_cal_notify_default_timezone_set (EDataCal *cal, EServerMethodContext context, GError *error);
-
-void e_data_cal_notify_changes (EDataCal *cal, EServerMethodContext context, GError *error,
- GList *adds, GList *modifies, GList *deletes);
-void e_data_cal_notify_free_busy (EDataCal *cal, EServerMethodContext context, GError *error,
- GList *freebusy);
-
-void e_data_cal_notify_mode (EDataCal *cal,
- EDataCalViewListenerSetModeStatus status,
- EDataCalMode mode);
-
-void e_data_cal_notify_auth_required (EDataCal *cal);
-
-void e_data_cal_notify_error (EDataCal *cal, const gchar *message);
-
-void e_data_cal_notify_attachment_list (EDataCal *cal, EServerMethodContext context, GError *error, GSList *objects);
+EDataCal * e_data_cal_new (ECalBackend *backend, ESource *source);
+ECalBackend * e_data_cal_get_backend (EDataCal *cal);
+ESource * e_data_cal_get_source (EDataCal *cal);
+guint e_data_cal_register_gdbus_object (EDataCal *cal, GDBusConnection *connection, const gchar *object_path, GError **error);
+
+void e_data_cal_respond_open (EDataCal *cal, guint32 opid, GError *error);
+void e_data_cal_respond_remove (EDataCal *cal, guint32 opid, GError *error);
+void e_data_cal_respond_refresh (EDataCal *cal, guint32 opid, GError *error);
+void e_data_cal_respond_get_backend_property (EDataCal *cal, guint32 opid, GError *error, const gchar *prop_value);
+void e_data_cal_respond_set_backend_property (EDataCal *cal, guint32 opid, GError *error);
+void e_data_cal_respond_get_object (EDataCal *cal, guint32 opid, GError *error, const gchar *object);
+void e_data_cal_respond_get_object_list (EDataCal *cal, guint32 opid, GError *error, const GSList *objects);
+void e_data_cal_respond_get_free_busy (EDataCal *cal, guint32 opid, GError *error);
+void e_data_cal_respond_create_object (EDataCal *cal, guint32 opid, GError *error, const gchar *uid, const gchar *object);
+void e_data_cal_respond_modify_object (EDataCal *cal, guint32 opid, GError *error, const gchar *old_object, const gchar *object);
+void e_data_cal_respond_remove_object (EDataCal *cal, guint32 opid, GError *error, const ECalComponentId *id, const gchar *old_object, const gchar *object);
+void e_data_cal_respond_receive_objects (EDataCal *cal, guint32 opid, GError *error);
+void e_data_cal_respond_send_objects (EDataCal *cal, guint32 opid, GError *error, const GSList *users, const gchar *calobj);
+void e_data_cal_respond_get_attachment_uris (EDataCal *cal, guint32 opid, GError *error, const GSList *attachments);
+void e_data_cal_respond_discard_alarm (EDataCal *cal, guint32 opid, GError *error);
+void e_data_cal_respond_get_view (EDataCal *cal, guint32 opid, GError *error, const gchar *view_path);
+void e_data_cal_respond_get_timezone (EDataCal *cal, guint32 opid, GError *error, const gchar *tzobject);
+void e_data_cal_respond_add_timezone (EDataCal *cal, guint32 opid, GError *error);
+
+void e_data_cal_report_error (EDataCal *cal, const gchar *message);
+void e_data_cal_report_readonly (EDataCal *cal, gboolean is_readonly);
+void e_data_cal_report_online (EDataCal *cal, gboolean is_online);
+void e_data_cal_report_auth_required (EDataCal *cal, const ECredentials *credentials);
+void e_data_cal_report_opened (EDataCal *cal, const GError *error);
+void e_data_cal_report_free_busy_data (EDataCal *cal, const GSList *freebusy);
G_END_DECLS
diff --git a/calendar/libegdbus/Makefile.am b/calendar/libegdbus/Makefile.am
index 82f2b1b..e29a27c 100644
--- a/calendar/libegdbus/Makefile.am
+++ b/calendar/libegdbus/Makefile.am
@@ -1,13 +1,3 @@
-GDBUS_XML_FILES = \
- ../libedata-cal/e-data-cal-factory.xml \
- ../libedata-cal/e-data-cal-view.xml \
- ../libedata-cal/e-data-cal.xml
-
-gdbus-files: $(GDBUS_XML_FILES)
- gdbus-codegen --namespace=EGdbus --strip-prefix=org.gnome.evolution.dataserver.calendar --output-prefix=e-gdbus $(GDBUS_XML_FILES)
- rm e-gdbus-bindings.h
- rm e-gdbus-bindings.stamp
-
# The library
noinst_LTLIBRARIES = libegdbus-cal.la
@@ -19,21 +9,16 @@ libegdbus_cal_la_CPPFLAGS = \
$(E_DATA_SERVER_CFLAGS)
libegdbus_cal_la_SOURCES = \
- e-gdbus-egdbuscal.h \
- e-gdbus-egdbuscal.c \
- e-gdbus-egdbuscalfactory.h \
- e-gdbus-egdbuscalfactory.c \
- e-gdbus-egdbuscalview.h \
- e-gdbus-egdbuscalview.c \
- e-gdbus-marshallers.h \
- e-gdbus-marshallers.c \
- e-gdbus-typemappers.h
+ e-gdbus-cal.h \
+ e-gdbus-cal.c \
+ e-gdbus-cal-factory.h \
+ e-gdbus-cal-factory.c \
+ e-gdbus-cal-view.h \
+ e-gdbus-cal-view.c
libegdbus_cal_la_LIBADD = \
$(E_DATA_SERVER_LIBS)
libegdbus_cal_la_LDFLAGS = $(NO_UNDEFINED)
-EXTRA_DIST = e-gdbus-marshallers.list
-
-include $(top_srcdir)/git.mk
diff --git a/calendar/libegdbus/e-gdbus-cal-factory.c b/calendar/libegdbus/e-gdbus-cal-factory.c
new file mode 100644
index 0000000..e241828
--- /dev/null
+++ b/calendar/libegdbus/e-gdbus-cal-factory.c
@@ -0,0 +1,604 @@
+/*
+ * e-gdbus-cal-factory.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gio/gio.h>
+
+#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-gdbus-marshallers.h>
+
+#include "e-gdbus-cal-factory.h"
+
+#define GDBUS_CAL_FACTORY_INTERFACE_NAME "org.gnome.evolution.dataserver.CalendarFactory"
+
+typedef EGdbusCalFactoryIface EGdbusCalFactoryInterface;
+G_DEFINE_INTERFACE (EGdbusCalFactory, e_gdbus_cal_factory, G_TYPE_OBJECT);
+
+enum
+{
+ _0_SIGNAL,
+ __GET_CAL_METHOD,
+ __LAST_SIGNAL
+};
+
+static guint signals[__LAST_SIGNAL] = {0};
+
+/* ------------------------------------------------------------------------- */
+
+/* Various lookup tables */
+
+static GHashTable *_method_name_to_id = NULL;
+static GHashTable *_method_name_to_type = NULL;
+
+static guint
+lookup_method_id_from_method_name (const gchar *method_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_method_name_to_id, method_name));
+}
+
+static guint
+lookup_method_type_from_method_name (const gchar *method_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_method_name_to_type, method_name));
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void
+e_gdbus_cal_factory_default_init (EGdbusCalFactoryIface *iface)
+{
+ /* Build lookup structures */
+ _method_name_to_id = g_hash_table_new (g_str_hash, g_str_equal);
+ _method_name_to_type = g_hash_table_new (g_str_hash, g_str_equal);
+
+ E_INIT_GDBUS_METHOD_STRV (EGdbusCalFactoryIface, "getCal", get_cal, __GET_CAL_METHOD)
+}
+
+/* encodes source and source type into a strv usable for a wire transfer;
+ Free returned pointer with g_strfreev() */
+gchar **
+e_gdbus_cal_factory_encode_get_cal (const gchar *in_source, guint in_type)
+{
+ gchar **strv;
+
+ g_return_val_if_fail (in_source != NULL, NULL);
+
+ strv = g_new0 (gchar *, 3);
+ strv[0] = g_strdup (in_source);
+ strv[1] = g_strdup_printf ("%u", (guint32) in_type);
+ strv[2] = NULL;
+
+ return strv;
+}
+
+/* decodes source and source type from a strv recevied from a wire transfer;
+ free out_source with g_free(); returns TRUE is successful. */
+gboolean
+e_gdbus_cal_factory_decode_get_cal (const gchar * const * in_strv, gchar **out_source, guint *out_type)
+{
+ g_return_val_if_fail (in_strv != NULL, FALSE);
+ g_return_val_if_fail (in_strv[0] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[1] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[2] == NULL, FALSE);
+ g_return_val_if_fail (out_source != NULL, FALSE);
+ g_return_val_if_fail (out_type != NULL, FALSE);
+
+ *out_source = g_strdup (in_strv[0]);
+ *out_type = atoi (in_strv[1]);
+
+ return TRUE;
+}
+
+/* C Bindings for properties */
+
+void
+e_gdbus_cal_factory_call_get_cal (GDBusProxy *proxy, const gchar * const *in_source_type, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ /* in_source_type has only two items, the first is ESource, the second is source type */
+ /* use e_gdbus_cal_factory_encode_get_cal() to encode them */
+
+ g_return_if_fail (in_source_type != NULL);
+ g_return_if_fail (in_source_type[0] != NULL);
+ g_return_if_fail (in_source_type[1] != NULL);
+ g_return_if_fail (in_source_type[2] == NULL);
+
+ e_gdbus_proxy_method_call_strv ("getCal", proxy, in_source_type, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_factory_call_get_cal_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_path, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_string (proxy, result, out_path, error);
+}
+
+gboolean
+e_gdbus_cal_factory_call_get_cal_sync (GDBusProxy *proxy, const gchar * const *in_source_type, gchar **out_path, GCancellable *cancellable, GError **error)
+{
+ /* in_source_type has only two items, the first is ESource, the second is source type */
+ /* use e_gdbus_cal_factory_encode_get_cal() to encode them */
+
+ g_return_val_if_fail (in_source_type != NULL, FALSE);
+ g_return_val_if_fail (in_source_type[0] != NULL, FALSE);
+ g_return_val_if_fail (in_source_type[1] != NULL, FALSE);
+ g_return_val_if_fail (in_source_type[2] == NULL, FALSE);
+
+ return e_gdbus_proxy_method_call_sync_strv__string ("getCal", proxy, in_source_type, out_path, cancellable, error);
+}
+
+void
+e_gdbus_cal_factory_complete_get_cal (EGdbusCalFactory *object, GDBusMethodInvocation *invocation, const gchar *out_path, const GError *error)
+{
+ e_gdbus_complete_sync_method_string (object, invocation, out_path, error);
+}
+
+E_DECLARE_GDBUS_SYNC_METHOD_1_WITH_RETURN (cal_factory, getCal, source_type, "as", path, "s")
+
+static const GDBusMethodInfo * const e_gdbus_cal_factory_method_info_pointers[] =
+{
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal_factory, getCal),
+ NULL
+};
+
+static const GDBusInterfaceInfo _e_gdbus_cal_factory_interface_info =
+{
+ -1,
+ (gchar *) GDBUS_CAL_FACTORY_INTERFACE_NAME,
+ (GDBusMethodInfo **) &e_gdbus_cal_factory_method_info_pointers,
+ (GDBusSignalInfo **) NULL,
+ (GDBusPropertyInfo **) NULL,
+};
+
+static void
+handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ guint method_id, method_type;
+
+ method_id = lookup_method_id_from_method_name (method_name);
+ method_type = lookup_method_type_from_method_name (method_name);
+
+ g_return_if_fail (method_id != 0);
+ g_return_if_fail (method_type != 0);
+
+ e_gdbus_stub_handle_method_call (user_data, invocation, parameters, method_name, signals[method_id], method_type);
+}
+
+static GVariant *
+get_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data)
+{
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This implementation does not support property `%s'", property_name);
+ return NULL;
+}
+
+static gboolean
+set_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GVariant *value, GError **error, gpointer user_data)
+{
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This implementation does not support property `%s'", property_name);
+ return FALSE;
+}
+
+static const GDBusInterfaceVTable e_gdbus_cal_factory_interface_vtable =
+{
+ handle_method_call,
+ get_property,
+ set_property
+};
+
+static gboolean
+emit_notifications_in_idle (gpointer user_data)
+{
+ GObject *object = G_OBJECT (user_data);
+ GDBusConnection *connection;
+ const gchar *path;
+ GHashTable *notification_queue;
+ GHashTableIter iter;
+ const gchar *property_name;
+ GVariant *value;
+ GVariantBuilder *builder;
+ GVariantBuilder *invalidated_builder;
+ GHashTable *pvc;
+ gboolean has_changes;
+
+ notification_queue = g_object_get_data (object, "gdbus-codegen-notification-queue");
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ pvc = g_object_get_data (object, "gdbus-codegen-pvc");
+ g_assert (notification_queue != NULL && path != NULL && connection != NULL && pvc != NULL);
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
+ invalidated_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ g_hash_table_iter_init (&iter, notification_queue);
+ has_changes = FALSE;
+ while (g_hash_table_iter_next (&iter, (gpointer) &property_name, (gpointer) &value)) {
+ GVariant *cached_value;
+ cached_value = g_hash_table_lookup (pvc, property_name);
+ if (cached_value == NULL || !g_variant_equal (cached_value, value)) {
+ g_hash_table_insert (pvc, (gpointer) property_name, (gpointer) g_variant_ref (value));
+ g_variant_builder_add (builder, "{sv}", property_name, value);
+ has_changes = TRUE;
+ }
+ }
+
+ if (has_changes) {
+ g_dbus_connection_emit_signal (connection,
+ NULL,
+ path,
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ g_variant_new ("(sa{sv}as)",
+ GDBUS_CAL_FACTORY_INTERFACE_NAME,
+ builder,
+ invalidated_builder),
+ NULL);
+ } else {
+ g_variant_builder_unref (builder);
+ g_variant_builder_unref (invalidated_builder);
+ }
+
+ g_hash_table_remove_all (notification_queue);
+ g_object_set_data (object, "gdbus-codegen-notification-idle-id", GUINT_TO_POINTER (0));
+ return FALSE;
+}
+
+/**
+ * e_gdbus_cal_factory_drain_notify:
+ * @object: A #EGdbusCalFactory that is exported.
+ *
+ * If @object has queued notifications, empty the queue forcing
+ * the <literal>PropertiesChanged</literal> signal to be emitted.
+ * See <xref linkend="EGdbusCalFactory.description"/> for more background information.
+ */
+void
+e_gdbus_cal_factory_drain_notify (EGdbusCalFactory *object)
+{
+ gint idle_id;
+ idle_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (object), "gdbus-codegen-notification-idle-id"));
+ if (idle_id > 0) {
+ emit_notifications_in_idle (object);
+ g_source_remove (idle_id);
+ }
+}
+
+static void
+on_object_unregistered (GObject *object)
+{
+ gint idle_id;
+ idle_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (object), "gdbus-codegen-notification-idle-id"));
+ if (idle_id > 0) {
+ g_source_remove (idle_id);
+ }
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-path", NULL);
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-connection", NULL);
+}
+
+/**
+ * e_gdbus_cal_factory_register_object:
+ * @object: An instance of a #GObject<!-- -->-derived type implementing the #EGdbusCalFactory interface.
+ * @connection: A #GDBusConnection.
+ * @object_path: The object to register the object at.
+ * @error: Return location for error or %NULL.
+ *
+ * Registers @object at @object_path on @connection.
+ *
+ * See <xref linkend="EGdbusCalFactory.description"/>
+ * for how properties, methods and signals are handled.
+ *
+ * Returns: 0 if @error is set, otherwise a registration id (never 0) that can be used with g_dbus_connection_unregister_object().
+ */
+guint
+e_gdbus_cal_factory_register_object (EGdbusCalFactory *object, GDBusConnection *connection, const gchar *object_path, GError **error)
+{
+ GHashTable *pvc;
+
+ pvc = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_variant_unref);
+
+ g_object_set_data_full (G_OBJECT (object), "gdbus-codegen-path", (gpointer) g_strdup (object_path), g_free);
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-connection", (gpointer) connection);
+ g_object_set_data_full (G_OBJECT (object), "gdbus-codegen-pvc", (gpointer) pvc, (GDestroyNotify) g_hash_table_unref);
+ return g_dbus_connection_register_object (connection,
+ object_path,
+ (GDBusInterfaceInfo *) &_e_gdbus_cal_factory_interface_info,
+ &e_gdbus_cal_factory_interface_vtable,
+ object,
+ (GDestroyNotify) on_object_unregistered,
+ error);
+}
+
+/**
+ * e_gdbus_cal_factory_interface_info:
+ *
+ * Gets interface description for the <literal>org.gnome.evolution.dataserver.CalendarFactory</literal> D-Bus interface.
+ *
+ * Returns: A #GDBusInterfaceInfo. Do not free, the object is statically allocated.
+ */
+const GDBusInterfaceInfo *
+e_gdbus_cal_factory_interface_info (void)
+{
+ return &_e_gdbus_cal_factory_interface_info;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void proxy_iface_init (EGdbusCalFactoryIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EGdbusCalFactoryProxy, e_gdbus_cal_factory_proxy, G_TYPE_DBUS_PROXY,
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_CAL_FACTORY, proxy_iface_init));
+
+static void
+e_gdbus_cal_factory_proxy_init (EGdbusCalFactoryProxy *proxy)
+{
+ g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), (GDBusInterfaceInfo *) &_e_gdbus_cal_factory_interface_info);
+}
+
+static void
+g_signal (GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters)
+{
+ /*
+ guint signal_id, signal_type;
+
+ signal_id = lookup_signal_id_from_signal_name (signal_name);
+ signal_type = lookup_signal_type_from_signal_name (signal_name);
+
+ g_return_if_fail (signal_id != 0);
+ g_return_if_fail (signal_type != 0);
+
+ e_gdbus_proxy_emit_signal (proxy, parameters, signals[signal_id], signal_type);
+ */
+}
+
+static void
+e_gdbus_cal_factory_proxy_class_init (EGdbusCalFactoryProxyClass *klass)
+{
+ GDBusProxyClass *proxy_class;
+
+ proxy_class = G_DBUS_PROXY_CLASS (klass);
+ proxy_class->g_signal = g_signal;
+}
+
+static void
+proxy_iface_init (EGdbusCalFactoryIface *iface)
+{
+}
+
+/**
+ * e_gdbus_cal_factory_proxy_new:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: Callback function to invoke when the proxy is ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_dbus_proxy_new() but returns a #EGdbusCalFactoryProxy.
+ *
+ * This is a failable asynchronous constructor - when the proxy is ready, callback will be invoked and you can use e_gdbus_cal_factory_proxy_new_finish() to get the result.
+ */
+void
+e_gdbus_cal_factory_proxy_new (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ g_async_initable_new_async (E_TYPE_GDBUS_CAL_FACTORY_PROXY,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "g-flags", flags,
+ "g-name", name,
+ "g-connection", connection,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_CAL_FACTORY_INTERFACE_NAME,
+ NULL);
+}
+
+/**
+ * e_gdbus_cal_factory_proxy_new_finish:
+ * @result: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to e_gdbus_cal_factory_proxy_new().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes creating a #EGdbusCalFactoryProxy.
+ *
+ * Returns: A #EGdbusCalFactoryProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+EGdbusCalFactory *
+e_gdbus_cal_factory_proxy_new_finish (GAsyncResult *result, GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (result);
+ g_assert (source_object != NULL);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error);
+ g_object_unref (source_object);
+ if (object != NULL)
+ return E_GDBUS_CAL_FACTORY (object);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_cal_factory_proxy_new_sync:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_proxy_new_sync() but returns a #EGdbusCalFactoryProxy.
+ *
+ * This is a synchronous failable constructor. See e_gdbus_cal_factory_proxy_new() and e_gdbus_cal_factory_proxy_new_finish() for the asynchronous version.
+ *
+ * Returns: A #EGdbusCalFactoryProxy or %NULL if error is set. Free with g_object_unref().
+ */
+EGdbusCalFactory *
+e_gdbus_cal_factory_proxy_new_sync (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error)
+{
+ GInitable *initable;
+ initable = g_initable_new (E_TYPE_GDBUS_CAL_FACTORY_PROXY,
+ cancellable,
+ error,
+ "g-flags", flags,
+ "g-name", name,
+ "g-connection", connection,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_CAL_FACTORY_INTERFACE_NAME,
+ NULL);
+ if (initable != NULL)
+ return E_GDBUS_CAL_FACTORY (initable);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_cal_factory_proxy_new_for_bus:
+ * @bus_type: A #GBusType.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: Callback function to invoke when the proxy is ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_dbus_proxy_new_for_bus() but returns a #EGdbusCalFactoryProxy.
+ *
+ * This is a failable asynchronous constructor - when the proxy is ready, callback will be invoked and you can use e_gdbus_cal_factory_proxy_new_for_bus_finish() to get the result.
+ */
+void
+e_gdbus_cal_factory_proxy_new_for_bus (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ g_async_initable_new_async (E_TYPE_GDBUS_CAL_FACTORY_PROXY,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "g-flags", flags,
+ "g-name", name,
+ "g-bus-type", bus_type,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_CAL_FACTORY_INTERFACE_NAME,
+ NULL);
+}
+
+/**
+ * e_gdbus_cal_factory_proxy_new_for_bus_finish:
+ * @result: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to e_gdbus_cal_factory_proxy_new_for_bus().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes creating a #EGdbusCalFactoryProxy.
+ *
+ * Returns: A #EGdbusCalFactoryProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+EGdbusCalFactory *
+e_gdbus_cal_factory_proxy_new_for_bus_finish (GAsyncResult *result, GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (result);
+ g_assert (source_object != NULL);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error);
+ g_object_unref (source_object);
+ if (object != NULL)
+ return E_GDBUS_CAL_FACTORY (object);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_cal_factory_proxy_new_for_bus_sync:
+ * @bus_type: A #GBusType.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_proxy_new_for_bus_sync() but returns a #EGdbusCalFactoryProxy.
+ *
+ * This is a synchronous failable constructor. See e_gdbus_cal_factory_proxy_new_for_bus() and e_gdbus_cal_factory_proxy_new_for_bus_finish() for the asynchronous version.
+ *
+ * Returns: A #EGdbusCalFactoryProxy or %NULL if error is set. Free with g_object_unref().
+ */
+EGdbusCalFactory *
+e_gdbus_cal_factory_proxy_new_for_bus_sync (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error)
+{
+ GInitable *initable;
+ initable = g_initable_new (E_TYPE_GDBUS_CAL_FACTORY_PROXY,
+ cancellable,
+ error,
+ "g-flags", flags,
+ "g-name", name,
+ "g-bus-type", bus_type,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_CAL_FACTORY_INTERFACE_NAME,
+ NULL);
+ if (initable != NULL)
+ return E_GDBUS_CAL_FACTORY (initable);
+ else
+ return NULL;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct _EGdbusCalFactoryStubPrivate
+{
+ gint foo;
+};
+
+static void stub_iface_init (EGdbusCalFactoryIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EGdbusCalFactoryStub, e_gdbus_cal_factory_stub, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_CAL_FACTORY, stub_iface_init));
+
+static void
+e_gdbus_cal_factory_stub_init (EGdbusCalFactoryStub *stub)
+{
+ stub->priv = G_TYPE_INSTANCE_GET_PRIVATE (stub, E_TYPE_GDBUS_CAL_FACTORY_STUB, EGdbusCalFactoryStubPrivate);
+}
+
+static void
+e_gdbus_cal_factory_stub_class_init (EGdbusCalFactoryStubClass *klass)
+{
+ g_type_class_add_private (klass, sizeof (EGdbusCalFactoryStubPrivate));
+}
+
+static void
+stub_iface_init (EGdbusCalFactoryIface *iface)
+{
+}
+
+/**
+ * e_gdbus_cal_factory_stub_new:
+ *
+ * Creates a new stub object that can be exported via e_gdbus_cal_factory_register_object().
+ *
+ * Returns: A #EGdbusCalFactoryStub instance. Free with g_object_unref().
+ */
+EGdbusCalFactory *
+e_gdbus_cal_factory_stub_new (void)
+{
+ return E_GDBUS_CAL_FACTORY (g_object_new (E_TYPE_GDBUS_CAL_FACTORY_STUB, NULL));
+}
diff --git a/calendar/libegdbus/e-gdbus-cal-factory.h b/calendar/libegdbus/e-gdbus-cal-factory.h
new file mode 100644
index 0000000..1977c35
--- /dev/null
+++ b/calendar/libegdbus/e-gdbus-cal-factory.h
@@ -0,0 +1,116 @@
+/*
+ * e-gdbus-cal-factory.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_GDBUS_CAL_FACTORY_H
+#define E_GDBUS_CAL_FACTORY_H
+
+#include <gio/gio.h>
+
+#include <libedataserver/e-gdbus-templates.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_GDBUS_CAL_FACTORY (e_gdbus_cal_factory_get_type ())
+#define E_GDBUS_CAL_FACTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_GDBUS_CAL_FACTORY, EGdbusCalFactory))
+#define E_IS_GDBUS_CAL_FACTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_GDBUS_CAL_FACTORY))
+#define E_GDBUS_CAL_FACTORY_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE((o), E_TYPE_GDBUS_CAL_FACTORY, EGdbusCalFactoryIface))
+
+typedef struct _EGdbusCalFactory EGdbusCalFactory; /* Dummy typedef */
+typedef struct _EGdbusCalFactoryIface EGdbusCalFactoryIface;
+
+GType e_gdbus_cal_factory_get_type (void) G_GNUC_CONST;
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct _EGdbusCalFactoryProxy EGdbusCalFactoryProxy;
+typedef struct _EGdbusCalFactoryProxyClass EGdbusCalFactoryProxyClass;
+typedef struct _EGdbusCalFactoryProxyPrivate EGdbusCalFactoryProxyPrivate;
+
+struct _EGdbusCalFactoryProxy
+{
+ GDBusProxy parent_instance;
+ EGdbusCalFactoryProxyPrivate *priv;
+};
+
+struct _EGdbusCalFactoryProxyClass
+{
+ GDBusProxyClass parent_class;
+};
+
+#define E_TYPE_GDBUS_CAL_FACTORY_PROXY (e_gdbus_cal_factory_proxy_get_type ())
+GType e_gdbus_cal_factory_proxy_get_type (void) G_GNUC_CONST;
+
+void e_gdbus_cal_factory_proxy_new (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+EGdbusCalFactory * e_gdbus_cal_factory_proxy_new_finish (GAsyncResult *result, GError **error);
+EGdbusCalFactory * e_gdbus_cal_factory_proxy_new_sync (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_factory_proxy_new_for_bus (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+EGdbusCalFactory * e_gdbus_cal_factory_proxy_new_for_bus_finish (GAsyncResult *result, GError **error);
+EGdbusCalFactory * e_gdbus_cal_factory_proxy_new_for_bus_sync (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error);
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct _EGdbusCalFactoryStub EGdbusCalFactoryStub;
+typedef struct _EGdbusCalFactoryStubClass EGdbusCalFactoryStubClass;
+typedef struct _EGdbusCalFactoryStubPrivate EGdbusCalFactoryStubPrivate;
+
+struct _EGdbusCalFactoryStub
+{
+ GObject parent_instance;
+ EGdbusCalFactoryStubPrivate *priv;
+};
+
+struct _EGdbusCalFactoryStubClass
+{
+ GObjectClass parent_class;
+};
+
+#define E_TYPE_GDBUS_CAL_FACTORY_STUB (e_gdbus_cal_factory_stub_get_type ())
+GType e_gdbus_cal_factory_stub_get_type (void) G_GNUC_CONST;
+
+EGdbusCalFactory *e_gdbus_cal_factory_stub_new (void);
+
+guint e_gdbus_cal_factory_register_object (EGdbusCalFactory *object, GDBusConnection *connection, const gchar *object_path, GError **error);
+void e_gdbus_cal_factory_drain_notify (EGdbusCalFactory *object);
+const GDBusInterfaceInfo *e_gdbus_cal_factory_interface_info (void) G_GNUC_CONST;
+
+struct _EGdbusCalFactoryIface
+{
+ GTypeInterface parent_iface;
+
+ /* Signal handlers for handling D-Bus method calls: */
+ gboolean (*handle_get_cal) (EGdbusCalFactory *object, GDBusMethodInvocation *invocation, const gchar * const *in_source_type);
+};
+
+gchar ** e_gdbus_cal_factory_encode_get_cal (const gchar *in_source, guint in_type);
+gboolean e_gdbus_cal_factory_decode_get_cal (const gchar * const * in_strv, gchar **out_source, guint *out_type);
+
+/* D-Bus Methods */
+void e_gdbus_cal_factory_call_get_cal (GDBusProxy *proxy, const gchar * const *in_source_type, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_factory_call_get_cal_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_path, GError **error);
+gboolean e_gdbus_cal_factory_call_get_cal_sync (GDBusProxy *proxy, const gchar * const *in_source_type, gchar **out_path, GCancellable *cancellable, GError **error);
+
+/* D-Bus Methods Completion Helpers */
+void e_gdbus_cal_factory_complete_get_cal (EGdbusCalFactory *object, GDBusMethodInvocation *invocation, const gchar *out_path, const GError *error);
+
+G_END_DECLS
+
+#endif /* E_GDBUS_CAL_FACTORY_H */
diff --git a/calendar/libegdbus/e-gdbus-cal-view.c b/calendar/libegdbus/e-gdbus-cal-view.c
new file mode 100644
index 0000000..efb3e86
--- /dev/null
+++ b/calendar/libegdbus/e-gdbus-cal-view.c
@@ -0,0 +1,690 @@
+/*
+ * e-gdbus-cal-view.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#include <stdio.h>
+#include <gio/gio.h>
+
+#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-gdbus-marshallers.h>
+
+#include "e-gdbus-cal-view.h"
+
+#define GDBUS_CAL_VIEW_INTERFACE_NAME "org.gnome.evolution.dataserver.CalendarView"
+
+typedef EGdbusCalViewIface EGdbusCalViewInterface;
+G_DEFINE_INTERFACE (EGdbusCalView, e_gdbus_cal_view, G_TYPE_OBJECT);
+
+enum
+{
+ _0_SIGNAL,
+ __OBJECTS_ADDED_SIGNAL,
+ __OBJECTS_MODIFIED_SIGNAL,
+ __OBJECTS_REMOVED_SIGNAL,
+ __PROGRESS_SIGNAL,
+ __COMPLETE_SIGNAL,
+ __START_METHOD,
+ __STOP_METHOD,
+ __DISPOSE_METHOD,
+ __SET_FIELDS_OF_INTEREST_METHOD,
+ __LAST_SIGNAL
+};
+
+static guint signals[__LAST_SIGNAL] = {0};
+
+/* ------------------------------------------------------------------------- */
+
+/* Various lookup tables */
+
+static GHashTable *_method_name_to_id = NULL;
+static GHashTable *_method_name_to_type = NULL;
+static GHashTable *_signal_name_to_id = NULL;
+static GHashTable *_signal_name_to_type = NULL;
+
+static guint
+lookup_method_id_from_method_name (const gchar *method_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_method_name_to_id, method_name));
+}
+
+static guint
+lookup_method_type_from_method_name (const gchar *method_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_method_name_to_type, method_name));
+}
+
+static guint
+lookup_signal_id_from_signal_name (const gchar *signal_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_signal_name_to_id, signal_name));
+}
+
+static guint
+lookup_signal_type_from_signal_name (const gchar *signal_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_signal_name_to_type, signal_name));
+}
+
+/* ------------------------------------------------------------------------- */
+
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV (GDBUS_CAL_VIEW_INTERFACE_NAME, objects_added)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV (GDBUS_CAL_VIEW_INTERFACE_NAME, objects_modified)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV (GDBUS_CAL_VIEW_INTERFACE_NAME, objects_removed)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_UINT_STRING (GDBUS_CAL_VIEW_INTERFACE_NAME, progress)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV (GDBUS_CAL_VIEW_INTERFACE_NAME, complete)
+
+static void
+e_gdbus_cal_view_default_init (EGdbusCalViewIface *iface)
+{
+ /* Build lookup structures */
+ _method_name_to_id = g_hash_table_new (g_str_hash, g_str_equal);
+ _method_name_to_type = g_hash_table_new (g_str_hash, g_str_equal);
+ _signal_name_to_id = g_hash_table_new (g_str_hash, g_str_equal);
+ _signal_name_to_type = g_hash_table_new (g_str_hash, g_str_equal);
+
+
+ /* GObject signals definitions for D-Bus signals: */
+ E_INIT_GDBUS_SIGNAL_STRV (EGdbusCalViewIface, "ObjectsAdded", objects_added, __OBJECTS_ADDED_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_STRV (EGdbusCalViewIface, "ObjectsModified", objects_modified, __OBJECTS_MODIFIED_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_STRV (EGdbusCalViewIface, "ObjectsRemoved", objects_removed, __OBJECTS_REMOVED_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_UINT_STRING (EGdbusCalViewIface, "Progress", progress, __PROGRESS_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_STRV (EGdbusCalViewIface, "Complete", complete, __COMPLETE_SIGNAL)
+
+ /* GObject signals definitions for D-Bus methods: */
+ E_INIT_GDBUS_METHOD_VOID (EGdbusCalViewIface, "start", start, __START_METHOD)
+ E_INIT_GDBUS_METHOD_VOID (EGdbusCalViewIface, "stop", stop, __STOP_METHOD)
+ E_INIT_GDBUS_METHOD_VOID (EGdbusCalViewIface, "dispose", dispose, __DISPOSE_METHOD)
+ E_INIT_GDBUS_METHOD_STRV (EGdbusCalViewIface, "setFieldsOfInterest", set_fields_of_interest, __SET_FIELDS_OF_INTEREST_METHOD)
+}
+
+void
+e_gdbus_cal_view_call_start (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_void ("start", proxy, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_view_call_start_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_cal_view_call_start_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_void__void ("start", proxy, cancellable, error);
+}
+
+void
+e_gdbus_cal_view_call_stop (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_void ("stop", proxy, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_view_call_stop_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_cal_view_call_stop_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_void__void ("stop", proxy, cancellable, error);
+}
+
+void
+e_gdbus_cal_view_call_dispose (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_void ("dispose", proxy, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_view_call_dispose_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_cal_view_call_dispose_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_void__void ("dispose", proxy, cancellable, error);
+}
+
+void
+e_gdbus_cal_view_call_set_fields_of_interest (GDBusProxy *proxy, const gchar * const *in_only_fields, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_strv ("setFieldsOfInterest", proxy, in_only_fields, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_view_call_set_fields_of_interest_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_cal_view_call_set_fields_of_interest_sync (GDBusProxy *proxy, const gchar * const *in_only_fields, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_strv__void ("setFieldsOfInterest", proxy, in_only_fields, cancellable, error);
+}
+
+void
+e_gdbus_cal_view_emit_objects_added (EGdbusCalView *object, const gchar * const *arg_objects)
+{
+ g_signal_emit (object, signals[__OBJECTS_ADDED_SIGNAL], 0, arg_objects);
+}
+
+void
+e_gdbus_cal_view_emit_objects_modified (EGdbusCalView *object, const gchar * const *arg_objects)
+{
+ g_signal_emit (object, signals[__OBJECTS_MODIFIED_SIGNAL], 0, arg_objects);
+}
+
+void
+e_gdbus_cal_view_emit_objects_removed (EGdbusCalView *object, const gchar * const *arg_uids)
+{
+ g_signal_emit (object, signals[__OBJECTS_REMOVED_SIGNAL], 0, arg_uids);
+}
+
+void
+e_gdbus_cal_view_emit_progress (EGdbusCalView *object, guint arg_percent, const gchar *arg_message)
+{
+ g_signal_emit (object, signals[__PROGRESS_SIGNAL], 0, arg_percent, arg_message);
+}
+
+void
+e_gdbus_cal_view_emit_complete (EGdbusCalView *object, const gchar * const *arg_error)
+{
+ g_signal_emit (object, signals[__COMPLETE_SIGNAL], 0, arg_error);
+}
+
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (cal_view, ObjectsAdded, objects, "as")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (cal_view, ObjectsModified, objects, "as")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (cal_view, ObjectsRemoved, uids, "as")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_2 (cal_view, Progress, percent, "u", message, "s")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (cal_view, Complete, error, "as")
+
+E_DECLARE_GDBUS_SYNC_METHOD_0 (cal_view, start)
+E_DECLARE_GDBUS_SYNC_METHOD_0 (cal_view, stop)
+E_DECLARE_GDBUS_SYNC_METHOD_0 (cal_view, dispose)
+E_DECLARE_GDBUS_SYNC_METHOD_1 (cal_view, setFieldsOfInterest, fields_of_interest, "as")
+
+static const GDBusMethodInfo * const e_gdbus_cal_view_method_info_pointers[] =
+{
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal_view, start),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal_view, stop),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal_view, dispose),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal_view, setFieldsOfInterest),
+ NULL
+};
+
+static const GDBusSignalInfo * const e_gdbus_cal_view_signal_info_pointers[] =
+{
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal_view, ObjectsAdded),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal_view, ObjectsModified),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal_view, ObjectsRemoved),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal_view, Progress),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal_view, Complete),
+ NULL
+};
+
+static const GDBusInterfaceInfo _e_gdbus_cal_view_interface_info =
+{
+ -1,
+ (gchar *) GDBUS_CAL_VIEW_INTERFACE_NAME,
+ (GDBusMethodInfo **) &e_gdbus_cal_view_method_info_pointers,
+ (GDBusSignalInfo **) &e_gdbus_cal_view_signal_info_pointers,
+ (GDBusPropertyInfo **) NULL
+};
+
+static void
+handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ guint method_id, method_type;
+
+ method_id = lookup_method_id_from_method_name (method_name);
+ method_type = lookup_method_type_from_method_name (method_name);
+
+ g_return_if_fail (method_id != 0);
+ g_return_if_fail (method_type != 0);
+
+ e_gdbus_stub_handle_method_call (user_data, invocation, parameters, method_name, signals[method_id], method_type);
+}
+
+static GVariant *
+get_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data)
+{
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This implementation does not support property `%s'", property_name);
+ return NULL;
+}
+
+static gboolean
+set_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GVariant *value, GError **error, gpointer user_data)
+{
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This implementation does not support property `%s'", property_name);
+ return FALSE;
+}
+
+static const GDBusInterfaceVTable e_gdbus_cal_view_interface_vtable =
+{
+ handle_method_call,
+ get_property,
+ set_property
+};
+
+static gboolean
+emit_notifications_in_idle (gpointer user_data)
+{
+ GObject *object = G_OBJECT (user_data);
+ GDBusConnection *connection;
+ const gchar *path;
+ GHashTable *notification_queue;
+ GHashTableIter iter;
+ const gchar *property_name;
+ GVariant *value;
+ GVariantBuilder *builder;
+ GVariantBuilder *invalidated_builder;
+ GHashTable *pvc;
+ gboolean has_changes;
+
+ notification_queue = g_object_get_data (object, "gdbus-codegen-notification-queue");
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ pvc = g_object_get_data (object, "gdbus-codegen-pvc");
+ g_assert (notification_queue != NULL && path != NULL && connection != NULL && pvc != NULL);
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
+ invalidated_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ g_hash_table_iter_init (&iter, notification_queue);
+ has_changes = FALSE;
+ while (g_hash_table_iter_next (&iter, (gpointer) &property_name, (gpointer) &value)) {
+ GVariant *cached_value;
+ cached_value = g_hash_table_lookup (pvc, property_name);
+ if (cached_value == NULL || !g_variant_equal (cached_value, value)) {
+ g_hash_table_insert (pvc, (gpointer) property_name, (gpointer) g_variant_ref (value));
+ g_variant_builder_add (builder, "{sv}", property_name, value);
+ has_changes = TRUE;
+ }
+ }
+
+ if (has_changes) {
+ g_dbus_connection_emit_signal (connection,
+ NULL,
+ path,
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ g_variant_new ("(sa{sv}as)",
+ GDBUS_CAL_VIEW_INTERFACE_NAME,
+ builder,
+ invalidated_builder),
+ NULL);
+ } else {
+ g_variant_builder_unref (builder);
+ g_variant_builder_unref (invalidated_builder);
+ }
+
+ g_hash_table_remove_all (notification_queue);
+ g_object_set_data (object, "gdbus-codegen-notification-idle-id", GUINT_TO_POINTER (0));
+ return FALSE;
+}
+
+/**
+ * e_gdbus_cal_view_drain_notify:
+ * @object: A #EGdbusCalView that is exported.
+ *
+ * If @object has queued notifications, empty the queue forcing
+ * the <literal>PropertiesChanged</literal> signal to be emitted.
+ * See <xref linkend="EGdbusCalView.description"/> for more background information.
+ */
+void
+e_gdbus_cal_view_drain_notify (EGdbusCalView *object)
+{
+ gint idle_id;
+ idle_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (object), "gdbus-codegen-notification-idle-id"));
+ if (idle_id > 0) {
+ emit_notifications_in_idle (object);
+ g_source_remove (idle_id);
+ }
+}
+
+static void
+on_object_unregistered (GObject *object)
+{
+ gint idle_id;
+ idle_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (object), "gdbus-codegen-notification-idle-id"));
+ if (idle_id > 0) {
+ g_source_remove (idle_id);
+ }
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-path", NULL);
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-connection", NULL);
+}
+
+/**
+ * e_gdbus_cal_view_register_object:
+ * @object: An instance of a #GObject<!-- -->-derived type implementing the #EGdbusCalView interface.
+ * @connection: A #GDBusConnection.
+ * @object_path: The object to register the object at.
+ * @error: Return location for error or %NULL.
+ *
+ * Registers @object at @object_path on @connection.
+ *
+ * See <xref linkend="EGdbusCalView.description"/>
+ * for how properties, methods and signals are handled.
+ *
+ * Returns: 0 if @error is set, otherwise a registration id (never 0) that can be used with g_dbus_connection_unregister_object().
+ */
+guint
+e_gdbus_cal_view_register_object (EGdbusCalView *object, GDBusConnection *connection, const gchar *object_path, GError **error)
+{
+ GHashTable *pvc;
+
+ pvc = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_variant_unref);
+
+ g_object_set_data_full (G_OBJECT (object), "gdbus-codegen-path", (gpointer) g_strdup (object_path), g_free);
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-connection", (gpointer) connection);
+ g_object_set_data_full (G_OBJECT (object), "gdbus-codegen-pvc", (gpointer) pvc, (GDestroyNotify) g_hash_table_unref);
+ return g_dbus_connection_register_object (connection,
+ object_path,
+ (GDBusInterfaceInfo *) &_e_gdbus_cal_view_interface_info,
+ &e_gdbus_cal_view_interface_vtable,
+ object,
+ (GDestroyNotify) on_object_unregistered,
+ error);
+}
+
+/**
+ * e_gdbus_cal_view_interface_info:
+ *
+ * Gets interface description for the <literal>org.gnome.evolution.dataserver.CalendarView</literal> D-Bus interface.
+ *
+ * Returns: A #GDBusInterfaceInfo. Do not free, the object is statically allocated.
+ */
+const GDBusInterfaceInfo *
+e_gdbus_cal_view_interface_info (void)
+{
+ return &_e_gdbus_cal_view_interface_info;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void proxy_iface_init (EGdbusCalViewIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EGdbusCalViewProxy, e_gdbus_cal_view_proxy, G_TYPE_DBUS_PROXY,
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_CAL_VIEW, proxy_iface_init));
+
+static void
+e_gdbus_cal_view_proxy_init (EGdbusCalViewProxy *proxy)
+{
+ g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), (GDBusInterfaceInfo *) &_e_gdbus_cal_view_interface_info);
+}
+
+static void
+g_signal (GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters)
+{
+ guint signal_id, signal_type;
+
+ signal_id = lookup_signal_id_from_signal_name (signal_name);
+ signal_type = lookup_signal_type_from_signal_name (signal_name);
+
+ g_return_if_fail (signal_id != 0);
+ g_return_if_fail (signal_type != 0);
+
+ e_gdbus_proxy_emit_signal (proxy, parameters, signals[signal_id], signal_type);
+}
+
+static void
+e_gdbus_cal_view_proxy_class_init (EGdbusCalViewProxyClass *klass)
+{
+ GDBusProxyClass *proxy_class;
+
+ proxy_class = G_DBUS_PROXY_CLASS (klass);
+ proxy_class->g_signal = g_signal;
+}
+
+static void
+proxy_iface_init (EGdbusCalViewIface *iface)
+{
+}
+
+/**
+ * e_gdbus_cal_view_proxy_new:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: Callback function to invoke when the proxy is ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_dbus_proxy_new() but returns a #EGdbusCalViewProxy.
+ *
+ * This is a failable asynchronous constructor - when the proxy is ready, callback will be invoked and you can use e_gdbus_cal_view_proxy_new_finish() to get the result.
+ */
+void
+e_gdbus_cal_view_proxy_new (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ g_async_initable_new_async (E_TYPE_GDBUS_CAL_VIEW_PROXY,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "g-flags", flags,
+ "g-name", name,
+ "g-connection", connection,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_CAL_VIEW_INTERFACE_NAME,
+ NULL);
+}
+
+/**
+ * e_gdbus_cal_view_proxy_new_finish:
+ * @result: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to e_gdbus_cal_view_proxy_new().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes creating a #EGdbusCalViewProxy.
+ *
+ * Returns: A #EGdbusCalViewProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+EGdbusCalView *
+e_gdbus_cal_view_proxy_new_finish (GAsyncResult *result, GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (result);
+ g_assert (source_object != NULL);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error);
+ g_object_unref (source_object);
+ if (object != NULL)
+ return E_GDBUS_CAL_VIEW (object);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_cal_view_proxy_new_sync:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_proxy_new_sync() but returns a #EGdbusCalViewProxy.
+ *
+ * This is a synchronous failable constructor. See e_gdbus_cal_view_proxy_new() and e_gdbus_cal_view_proxy_new_finish() for the asynchronous version.
+ *
+ * Returns: A #EGdbusCalViewProxy or %NULL if error is set. Free with g_object_unref().
+ */
+EGdbusCalView *
+e_gdbus_cal_view_proxy_new_sync (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error)
+{
+ GInitable *initable;
+ initable = g_initable_new (E_TYPE_GDBUS_CAL_VIEW_PROXY,
+ cancellable,
+ error,
+ "g-flags", flags,
+ "g-name", name,
+ "g-connection", connection,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_CAL_VIEW_INTERFACE_NAME,
+ NULL);
+ if (initable != NULL)
+ return E_GDBUS_CAL_VIEW (initable);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_cal_view_proxy_new_for_bus:
+ * @bus_type: A #GBusType.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: Callback function to invoke when the proxy is ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_dbus_proxy_new_for_bus() but returns a #EGdbusCalViewProxy.
+ *
+ * This is a failable asynchronous constructor - when the proxy is ready, callback will be invoked and you can use e_gdbus_cal_view_proxy_new_for_bus_finish() to get the result.
+ */
+void
+e_gdbus_cal_view_proxy_new_for_bus (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ g_async_initable_new_async (E_TYPE_GDBUS_CAL_VIEW_PROXY,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "g-flags", flags,
+ "g-name", name,
+ "g-bus-type", bus_type,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_CAL_VIEW_INTERFACE_NAME,
+ NULL);
+}
+
+/**
+ * e_gdbus_cal_view_proxy_new_for_bus_finish:
+ * @result: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to e_gdbus_cal_view_proxy_new_for_bus().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes creating a #EGdbusCalViewProxy.
+ *
+ * Returns: A #EGdbusCalViewProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+EGdbusCalView *
+e_gdbus_cal_view_proxy_new_for_bus_finish (GAsyncResult *result, GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (result);
+ g_assert (source_object != NULL);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error);
+ g_object_unref (source_object);
+ if (object != NULL)
+ return E_GDBUS_CAL_VIEW (object);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_cal_view_proxy_new_for_bus_sync:
+ * @bus_type: A #GBusType.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_proxy_new_for_bus_sync() but returns a #EGdbusCalViewProxy.
+ *
+ * This is a synchronous failable constructor. See e_gdbus_cal_view_proxy_new_for_bus() and e_gdbus_cal_view_proxy_new_for_bus_finish() for the asynchronous version.
+ *
+ * Returns: A #EGdbusCalViewProxy or %NULL if error is set. Free with g_object_unref().
+ */
+EGdbusCalView *
+e_gdbus_cal_view_proxy_new_for_bus_sync (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error)
+{
+ GInitable *initable;
+ initable = g_initable_new (E_TYPE_GDBUS_CAL_VIEW_PROXY,
+ cancellable,
+ error,
+ "g-flags", flags,
+ "g-name", name,
+ "g-bus-type", bus_type,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_CAL_VIEW_INTERFACE_NAME,
+ NULL);
+ if (initable != NULL)
+ return E_GDBUS_CAL_VIEW (initable);
+ else
+ return NULL;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct _EGdbusCalViewStubPrivate
+{
+ gint foo;
+};
+
+static void stub_iface_init (EGdbusCalViewIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EGdbusCalViewStub, e_gdbus_cal_view_stub, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_CAL_VIEW, stub_iface_init));
+
+static void
+e_gdbus_cal_view_stub_init (EGdbusCalViewStub *stub)
+{
+ stub->priv = G_TYPE_INSTANCE_GET_PRIVATE (stub, E_TYPE_GDBUS_CAL_VIEW_STUB, EGdbusCalViewStubPrivate);
+}
+
+static void
+e_gdbus_cal_view_stub_class_init (EGdbusCalViewStubClass *klass)
+{
+ g_type_class_add_private (klass, sizeof (EGdbusCalViewStubPrivate));
+}
+
+static void
+stub_iface_init (EGdbusCalViewIface *iface)
+{
+}
+
+/**
+ * e_gdbus_cal_view_stub_new:
+ *
+ * Creates a new stub object that can be exported via e_gdbus_cal_view_register_object().
+ *
+ * Returns: A #EGdbusCalViewStub instance. Free with g_object_unref().
+ */
+EGdbusCalView *
+e_gdbus_cal_view_stub_new (void)
+{
+ return E_GDBUS_CAL_VIEW (g_object_new (E_TYPE_GDBUS_CAL_VIEW_STUB, NULL));
+}
diff --git a/calendar/libegdbus/e-gdbus-cal-view.h b/calendar/libegdbus/e-gdbus-cal-view.h
new file mode 100644
index 0000000..c2a5345
--- /dev/null
+++ b/calendar/libegdbus/e-gdbus-cal-view.h
@@ -0,0 +1,147 @@
+/*
+ * e-gdbus-cal-view.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_GDBUS_CAL_VIEW_H
+#define E_GDBUS_CAL_VIEW_H
+
+#include <gio/gio.h>
+
+#include <libedataserver/e-gdbus-templates.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_GDBUS_CAL_VIEW (e_gdbus_cal_view_get_type ())
+#define E_GDBUS_CAL_VIEW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_GDBUS_CAL_VIEW, EGdbusCalView))
+#define E_IS_GDBUS_CAL_VIEW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_GDBUS_CAL_VIEW))
+#define E_GDBUS_CAL_VIEW_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE((o), E_TYPE_GDBUS_CAL_VIEW, EGdbusCalViewIface))
+
+typedef struct _EGdbusCalView EGdbusCalView; /* Dummy typedef */
+typedef struct _EGdbusCalViewIface EGdbusCalViewIface;
+
+GType e_gdbus_cal_view_get_type (void) G_GNUC_CONST;
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct _EGdbusCalViewProxy EGdbusCalViewProxy;
+typedef struct _EGdbusCalViewProxyClass EGdbusCalViewProxyClass;
+typedef struct _EGdbusCalViewProxyPrivate EGdbusCalViewProxyPrivate;
+
+struct _EGdbusCalViewProxy
+{
+ GDBusProxy parent_instance;
+ EGdbusCalViewProxyPrivate *priv;
+};
+
+struct _EGdbusCalViewProxyClass
+{
+ GDBusProxyClass parent_class;
+};
+
+#define E_TYPE_GDBUS_CAL_VIEW_PROXY (e_gdbus_cal_view_proxy_get_type ())
+GType e_gdbus_cal_view_proxy_get_type (void) G_GNUC_CONST;
+
+void e_gdbus_cal_view_proxy_new (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+EGdbusCalView * e_gdbus_cal_view_proxy_new_finish (GAsyncResult *result, GError **error);
+EGdbusCalView * e_gdbus_cal_view_proxy_new_sync (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_view_proxy_new_for_bus (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+EGdbusCalView * e_gdbus_cal_view_proxy_new_for_bus_finish (GAsyncResult *result, GError **error);
+EGdbusCalView * e_gdbus_cal_view_proxy_new_for_bus_sync (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error);
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct _EGdbusCalViewStub EGdbusCalViewStub;
+typedef struct _EGdbusCalViewStubClass EGdbusCalViewStubClass;
+typedef struct _EGdbusCalViewStubPrivate EGdbusCalViewStubPrivate;
+
+struct _EGdbusCalViewStub
+{
+ GObject parent_instance;
+ EGdbusCalViewStubPrivate *priv;
+};
+
+struct _EGdbusCalViewStubClass
+{
+ GObjectClass parent_class;
+};
+
+#define E_TYPE_GDBUS_CAL_VIEW_STUB (e_gdbus_cal_view_stub_get_type ())
+GType e_gdbus_cal_view_stub_get_type (void) G_GNUC_CONST;
+
+EGdbusCalView *e_gdbus_cal_view_stub_new (void);
+guint e_gdbus_cal_view_register_object (EGdbusCalView *object, GDBusConnection *connection, const gchar *object_path, GError **error);
+void e_gdbus_cal_view_drain_notify (EGdbusCalView *object);
+
+const GDBusInterfaceInfo *e_gdbus_cal_view_interface_info (void) G_GNUC_CONST;
+
+struct _EGdbusCalViewIface
+{
+ GTypeInterface parent_iface;
+
+ /* Signal handlers for receiving D-Bus signals: */
+ void (*objects_added) (EGdbusCalView *object, const gchar * const *arg_objects);
+ void (*objects_modified) (EGdbusCalView *object, const gchar * const *arg_objects);
+ void (*objects_removed) (EGdbusCalView *object, const gchar * const *arg_uids);
+
+ void (*progress) (EGdbusCalView *object, guint arg_percent, const gchar *arg_message);
+ void (*complete) (EGdbusCalView *object, guint arg_status, const gchar *arg_message);
+
+ /* Signal handlers for handling D-Bus method calls: */
+ gboolean (*handle_start) (EGdbusCalView *object, GDBusMethodInvocation *invocation);
+ gboolean (*handle_stop) (EGdbusCalView *object, GDBusMethodInvocation *invocation);
+ gboolean (*handle_dispose) (EGdbusCalView *object, GDBusMethodInvocation *invocation);
+ gboolean (*handle_set_fields_of_interest)(EGdbusCalView *object, GDBusMethodInvocation *invocation, const gchar * const *in_only_fields);
+};
+
+/* D-Bus Methods */
+void e_gdbus_cal_view_call_start (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_view_call_start_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_view_call_start_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_view_call_stop (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_view_call_stop_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_view_call_stop_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_view_call_dispose (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_view_call_dispose_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_view_call_dispose_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_view_call_set_fields_of_interest (GDBusProxy *proxy, const gchar * const *in_only_fileds, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_view_call_set_fields_of_interest_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_view_call_set_fields_of_interest_sync (GDBusProxy *proxy, const gchar * const *in_only_fileds, GCancellable *cancellable, GError **error);
+
+/* D-Bus Methods Completion Helpers */
+#define e_gdbus_cal_view_complete_start e_gdbus_complete_sync_method_void
+#define e_gdbus_cal_view_complete_stop e_gdbus_complete_sync_method_void
+#define e_gdbus_cal_view_complete_dispose e_gdbus_complete_sync_method_void
+#define e_gdbus_cal_view_complete_set_fields_of_interest e_gdbus_complete_sync_method_void
+
+/* D-Bus Signal Emission Helpers */
+void e_gdbus_cal_view_emit_objects_added (EGdbusCalView *object, const gchar * const *arg_objects);
+void e_gdbus_cal_view_emit_objects_modified (EGdbusCalView *object, const gchar * const *arg_objects);
+void e_gdbus_cal_view_emit_objects_removed (EGdbusCalView *object, const gchar * const *arg_uids);
+
+void e_gdbus_cal_view_emit_progress (EGdbusCalView *object, guint arg_percent, const gchar *arg_message);
+void e_gdbus_cal_view_emit_complete (EGdbusCalView *object, const gchar * const *arg_error);
+
+G_END_DECLS
+
+#endif /* E_GDBUS_CAL_VIEW_H */
diff --git a/calendar/libegdbus/e-gdbus-cal.c b/calendar/libegdbus/e-gdbus-cal.c
new file mode 100644
index 0000000..3604be0
--- /dev/null
+++ b/calendar/libegdbus/e-gdbus-cal.c
@@ -0,0 +1,1584 @@
+/*
+ * e-gdbus-cal.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gio/gio.h>
+
+#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-gdbus-marshallers.h>
+
+#include "e-gdbus-cal.h"
+
+#define GDBUS_CAL_INTERFACE_NAME "org.gnome.evolution.dataserver.Calendar"
+
+typedef EGdbusCalIface EGdbusCalInterface;
+G_DEFINE_INTERFACE (EGdbusCal, e_gdbus_cal, G_TYPE_OBJECT);
+
+enum
+{
+ _0_SIGNAL,
+ __BACKEND_ERROR_SIGNAL,
+ __READONLY_SIGNAL,
+ __ONLINE_SIGNAL,
+ __AUTH_REQUIRED_SIGNAL,
+ __OPENED_SIGNAL,
+ __FREE_BUSY_DATA_SIGNAL,
+ __OPEN_METHOD,
+ __OPEN_DONE_SIGNAL,
+ __REMOVE_METHOD,
+ __REMOVE_DONE_SIGNAL,
+ __REFRESH_METHOD,
+ __REFRESH_DONE_SIGNAL,
+ __GET_BACKEND_PROPERTY_METHOD,
+ __GET_BACKEND_PROPERTY_DONE_SIGNAL,
+ __SET_BACKEND_PROPERTY_METHOD,
+ __SET_BACKEND_PROPERTY_DONE_SIGNAL,
+ __GET_OBJECT_METHOD,
+ __GET_OBJECT_DONE_SIGNAL,
+ __GET_OBJECT_LIST_METHOD,
+ __GET_OBJECT_LIST_DONE_SIGNAL,
+ __GET_FREE_BUSY_METHOD,
+ __GET_FREE_BUSY_DONE_SIGNAL,
+ __CREATE_OBJECT_METHOD,
+ __CREATE_OBJECT_DONE_SIGNAL,
+ __MODIFY_OBJECT_METHOD,
+ __MODIFY_OBJECT_DONE_SIGNAL,
+ __REMOVE_OBJECT_METHOD,
+ __REMOVE_OBJECT_DONE_SIGNAL,
+ __RECEIVE_OBJECTS_METHOD,
+ __RECEIVE_OBJECTS_DONE_SIGNAL,
+ __SEND_OBJECTS_METHOD,
+ __SEND_OBJECTS_DONE_SIGNAL,
+ __GET_ATTACHMENT_URIS_METHOD,
+ __GET_ATTACHMENT_URIS_DONE_SIGNAL,
+ __DISCARD_ALARM_METHOD,
+ __DISCARD_ALARM_DONE_SIGNAL,
+ __GET_VIEW_METHOD,
+ __GET_VIEW_DONE_SIGNAL,
+ __GET_TIMEZONE_METHOD,
+ __GET_TIMEZONE_DONE_SIGNAL,
+ __ADD_TIMEZONE_METHOD,
+ __ADD_TIMEZONE_DONE_SIGNAL,
+ __AUTHENTICATE_USER_METHOD,
+ __CANCEL_OPERATION_METHOD,
+ __CANCEL_ALL_METHOD,
+ __CLOSE_METHOD,
+ __LAST_SIGNAL
+};
+
+static guint signals[__LAST_SIGNAL] = {0};
+
+struct _EGdbusCalProxyPrivate
+{
+ GHashTable *pending_ops;
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Various lookup tables */
+
+static GHashTable *_method_name_to_id = NULL;
+static GHashTable *_method_name_to_type = NULL;
+static GHashTable *_signal_name_to_id = NULL;
+static GHashTable *_signal_name_to_type = NULL;
+
+static guint
+lookup_method_id_from_method_name (const gchar *method_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_method_name_to_id, method_name));
+}
+
+static guint
+lookup_method_type_from_method_name (const gchar *method_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_method_name_to_type, method_name));
+}
+
+static guint
+lookup_signal_id_from_signal_name (const gchar *signal_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_signal_name_to_id, signal_name));
+}
+
+static guint
+lookup_signal_type_from_signal_name (const gchar *signal_name)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (_signal_name_to_type, signal_name));
+}
+
+/* ------------------------------------------------------------------------- */
+
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRING (GDBUS_CAL_INTERFACE_NAME, backend_error)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_BOOLEAN (GDBUS_CAL_INTERFACE_NAME, readonly)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_BOOLEAN (GDBUS_CAL_INTERFACE_NAME, online)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV (GDBUS_CAL_INTERFACE_NAME, auth_required)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV (GDBUS_CAL_INTERFACE_NAME, opened)
+E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV (GDBUS_CAL_INTERFACE_NAME, free_busy_data)
+
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_CAL_INTERFACE_NAME, open)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_CAL_INTERFACE_NAME, remove)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_CAL_INTERFACE_NAME, refresh)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING (GDBUS_CAL_INTERFACE_NAME, get_backend_property)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_CAL_INTERFACE_NAME, set_backend_property)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING (GDBUS_CAL_INTERFACE_NAME, get_object)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRV (GDBUS_CAL_INTERFACE_NAME, get_object_list)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_CAL_INTERFACE_NAME, get_free_busy)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING (GDBUS_CAL_INTERFACE_NAME, create_object)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_CAL_INTERFACE_NAME, modify_object)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_CAL_INTERFACE_NAME, remove_object)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_CAL_INTERFACE_NAME, receive_objects)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRV (GDBUS_CAL_INTERFACE_NAME, send_objects)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRV (GDBUS_CAL_INTERFACE_NAME, get_attachment_uris)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_CAL_INTERFACE_NAME, discard_alarm)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING (GDBUS_CAL_INTERFACE_NAME, get_view)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING (GDBUS_CAL_INTERFACE_NAME, get_timezone)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_CAL_INTERFACE_NAME, add_timezone)
+
+static void
+e_gdbus_cal_default_init (EGdbusCalIface *iface)
+{
+ /* Build lookup structures */
+ _method_name_to_id = g_hash_table_new (g_str_hash, g_str_equal);
+ _method_name_to_type = g_hash_table_new (g_str_hash, g_str_equal);
+ _signal_name_to_id = g_hash_table_new (g_str_hash, g_str_equal);
+ _signal_name_to_type = g_hash_table_new (g_str_hash, g_str_equal);
+
+ /* GObject signals definitions for D-Bus signals: */
+ E_INIT_GDBUS_SIGNAL_STRING (EGdbusCalIface, "backend_error", backend_error, __BACKEND_ERROR_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_BOOLEAN (EGdbusCalIface, "readonly", readonly, __READONLY_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_BOOLEAN (EGdbusCalIface, "online", online, __ONLINE_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_STRV (EGdbusCalIface, "auth_required", auth_required, __AUTH_REQUIRED_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_STRV (EGdbusCalIface, "opened", opened, __OPENED_SIGNAL)
+ E_INIT_GDBUS_SIGNAL_STRV (EGdbusCalIface, "free_busy_data", free_busy_data, __FREE_BUSY_DATA_SIGNAL)
+
+ /* GObject signals definitions for D-Bus methods: */
+ E_INIT_GDBUS_METHOD_ASYNC_BOOLEAN__VOID (EGdbusCalIface, "open", open, __OPEN_METHOD, __OPEN_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_VOID__VOID (EGdbusCalIface, "remove", remove, __REMOVE_METHOD, __REMOVE_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_VOID__VOID (EGdbusCalIface, "refresh", refresh, __REFRESH_METHOD, __REFRESH_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusCalIface, "getBackendProperty", get_backend_property, __GET_BACKEND_PROPERTY_METHOD, __GET_BACKEND_PROPERTY_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRV__VOID (EGdbusCalIface, "setBackendProperty", set_backend_property, __SET_BACKEND_PROPERTY_METHOD, __SET_BACKEND_PROPERTY_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRV__STRING (EGdbusCalIface, "getObject", get_object, __GET_OBJECT_METHOD, __GET_OBJECT_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__STRV (EGdbusCalIface, "getObjectList", get_object_list, __GET_OBJECT_LIST_METHOD, __GET_OBJECT_LIST_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRV__VOID (EGdbusCalIface, "getFreeBusy", get_free_busy, __GET_FREE_BUSY_METHOD, __GET_FREE_BUSY_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusCalIface, "createObject", create_object, __CREATE_OBJECT_METHOD, __CREATE_OBJECT_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRV__VOID (EGdbusCalIface, "modifyObject", modify_object, __MODIFY_OBJECT_METHOD, __MODIFY_OBJECT_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRV__VOID (EGdbusCalIface, "removeObject", remove_object, __REMOVE_OBJECT_METHOD, __REMOVE_OBJECT_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__VOID (EGdbusCalIface, "receiveObjects", receive_objects, __RECEIVE_OBJECTS_METHOD, __RECEIVE_OBJECTS_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__STRV (EGdbusCalIface, "sendObjects", send_objects, __SEND_OBJECTS_METHOD, __SEND_OBJECTS_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRV__STRV (EGdbusCalIface, "getAttachmentUris", get_attachment_uris, __GET_ATTACHMENT_URIS_METHOD, __GET_ATTACHMENT_URIS_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRV__VOID (EGdbusCalIface, "discardAlarm", discard_alarm, __DISCARD_ALARM_METHOD, __DISCARD_ALARM_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusCalIface, "getView", get_view, __GET_VIEW_METHOD, __GET_VIEW_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusCalIface, "getTimezone", get_timezone, __GET_TIMEZONE_METHOD, __GET_TIMEZONE_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_ASYNC_STRING__VOID (EGdbusCalIface, "addTimezone", add_timezone, __ADD_TIMEZONE_METHOD, __ADD_TIMEZONE_DONE_SIGNAL)
+ E_INIT_GDBUS_METHOD_STRV (EGdbusCalIface, "authenticateUser", authenticate_user, __AUTHENTICATE_USER_METHOD)
+ E_INIT_GDBUS_METHOD_UINT (EGdbusCalIface, "cancelOperation", cancel_operation, __CANCEL_OPERATION_METHOD)
+ E_INIT_GDBUS_METHOD_VOID (EGdbusCalIface, "cancelAll", cancel_all, __CANCEL_ALL_METHOD)
+ E_INIT_GDBUS_METHOD_VOID (EGdbusCalIface, "close", close, __CLOSE_METHOD)
+}
+
+static gchar **
+encode_string_string (const gchar *str1, const gchar *str2)
+{
+ gchar **strv;
+
+ strv = g_new0 (gchar *, 3);
+ strv[0] = e_util_utf8_make_valid (str1 ? str1 : "");
+ strv[1] = e_util_utf8_make_valid (str2 ? str2 : "");
+ strv[2] = NULL;
+
+ return strv;
+}
+
+static gboolean
+decode_string_string (const gchar * const *in_strv, gchar **out_str1, gchar **out_str2)
+{
+ g_return_val_if_fail (in_strv != NULL, FALSE);
+ g_return_val_if_fail (in_strv[0] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[1] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[2] == NULL, FALSE);
+ g_return_val_if_fail (out_str1 != NULL, FALSE);
+ g_return_val_if_fail (out_str2 != NULL, FALSE);
+
+ *out_str1 = g_strdup (in_strv[0]);
+ *out_str2 = g_strdup (in_strv[1]);
+
+ return TRUE;
+}
+
+void
+e_gdbus_cal_call_open (GDBusProxy *proxy, gboolean in_only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_boolean ("open", e_gdbus_cal_call_open, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_only_if_exists, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_open_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_cal_call_open);
+}
+
+gboolean
+e_gdbus_cal_call_open_sync (GDBusProxy *proxy, gboolean in_only_if_exists, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_boolean__void (proxy, in_only_if_exists, cancellable, error,
+ e_gdbus_cal_call_open,
+ e_gdbus_cal_call_open_finish);
+}
+
+void
+e_gdbus_cal_call_remove (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_void ("remove", e_gdbus_cal_call_remove, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_remove_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_cal_call_remove);
+}
+
+gboolean
+e_gdbus_cal_call_remove_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_void__void (proxy, cancellable, error,
+ e_gdbus_cal_call_remove,
+ e_gdbus_cal_call_remove_finish);
+}
+
+void
+e_gdbus_cal_call_refresh (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_void ("refresh", e_gdbus_cal_call_refresh, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_refresh_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_cal_call_refresh);
+}
+
+gboolean
+e_gdbus_cal_call_refresh_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_void__void (proxy, cancellable, error,
+ e_gdbus_cal_call_refresh,
+ e_gdbus_cal_call_refresh_finish);
+}
+
+void
+e_gdbus_cal_call_get_backend_property (GDBusProxy *proxy, const gchar *in_prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("getBackendProperty", e_gdbus_cal_call_get_backend_property, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_prop_name, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_get_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_prop_value, GError **error)
+{
+ return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_prop_value, error, e_gdbus_cal_call_get_backend_property);
+}
+
+gboolean
+e_gdbus_cal_call_get_backend_property_sync (GDBusProxy *proxy, const gchar *in_prop_name, gchar **out_prop_value, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__string (proxy, in_prop_name, out_prop_value, cancellable, error,
+ e_gdbus_cal_call_get_backend_property,
+ e_gdbus_cal_call_get_backend_property_finish);
+}
+
+/* free returned pointer with g_strfreev() */
+gchar **
+e_gdbus_cal_encode_set_backend_property (const gchar *in_prop_name, const gchar *in_prop_value)
+{
+ return encode_string_string (in_prop_name, in_prop_value);
+}
+
+/* free out_prop_name and out_prop_value with g_free() */
+gboolean
+e_gdbus_cal_decode_set_backend_property (const gchar * const *in_strv, gchar **out_prop_name, gchar **out_prop_value)
+{
+ return decode_string_string (in_strv, out_prop_name, out_prop_value);
+}
+
+void
+e_gdbus_cal_call_set_backend_property (GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_strv ("setBackendProperty", e_gdbus_cal_call_set_backend_property, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_prop_name_value, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_set_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_cal_call_set_backend_property);
+}
+
+gboolean
+e_gdbus_cal_call_set_backend_property_sync (GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_strv__void (proxy, in_prop_name_value, cancellable, error,
+ e_gdbus_cal_call_set_backend_property,
+ e_gdbus_cal_call_set_backend_property_finish);
+}
+
+/* free returned pointer with g_strfreev() */
+gchar **
+e_gdbus_cal_encode_get_object (const gchar *in_uid, const gchar *in_rid)
+{
+ return encode_string_string (in_uid, in_rid);
+}
+
+/* free out_uid and out_rid with g_free() */
+gboolean
+e_gdbus_cal_decode_get_object (const gchar * const *in_strv, gchar **out_uid, gchar **out_rid)
+{
+ return decode_string_string (in_strv, out_uid, out_rid);
+}
+
+void
+e_gdbus_cal_call_get_object (GDBusProxy *proxy, const gchar * const *in_uid_rid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_strv ("getObject", e_gdbus_cal_call_get_object, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_uid_rid, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_get_object_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_object, GError **error)
+{
+ return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_object, error, e_gdbus_cal_call_get_object);
+}
+
+gboolean
+e_gdbus_cal_call_get_object_sync (GDBusProxy *proxy, const gchar * const *in_uid_rid, gchar **out_object, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_strv__string (proxy, in_uid_rid, out_object, cancellable, error,
+ e_gdbus_cal_call_get_object,
+ e_gdbus_cal_call_get_object_finish);
+}
+
+void
+e_gdbus_cal_call_get_object_list (GDBusProxy *proxy, const gchar *in_sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("getObjectList", e_gdbus_cal_call_get_object_list, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_sexp, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_get_object_list_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_objects, GError **error)
+{
+ return e_gdbus_proxy_finish_call_strv (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_objects, error, e_gdbus_cal_call_get_object_list);
+}
+
+gboolean
+e_gdbus_cal_call_get_object_list_sync (GDBusProxy *proxy, const gchar *in_sexp, gchar ***out_objects, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__strv (proxy, in_sexp, out_objects, cancellable, error,
+ e_gdbus_cal_call_get_object_list,
+ e_gdbus_cal_call_get_object_list_finish);
+}
+
+/* free returned pointer with g_strfreev() */
+gchar **
+e_gdbus_cal_encode_get_free_busy (guint in_start, guint in_end, const GSList *in_users)
+{
+ gchar **strv;
+ gint ii;
+
+ g_return_val_if_fail (in_users != NULL, NULL);
+
+ strv = g_new0 (gchar *, g_slist_length ((GSList *) in_users) + 3);
+ strv[0] = g_strdup_printf ("%u", in_start);
+ strv[1] = g_strdup_printf ("%u", in_end);
+
+ for (ii = 0; in_users; ii++, in_users = in_users->next) {
+ strv[ii + 2] = e_util_utf8_make_valid (in_users->data);
+ }
+
+ strv[ii + 2] = NULL;
+
+ return strv;
+}
+
+/* free out_users with g_slist_foreach (out_users, (GFunc) g_free, NULL), g_slist_free (out_users); */
+gboolean
+e_gdbus_cal_decode_get_free_busy (const gchar * const *in_strv, guint *out_start, guint *out_end, GSList **out_users)
+{
+ gint ii;
+
+ g_return_val_if_fail (in_strv != NULL, FALSE);
+ g_return_val_if_fail (in_strv[0] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[1] != NULL, FALSE);
+ g_return_val_if_fail (out_start != NULL, FALSE);
+ g_return_val_if_fail (out_end != NULL, FALSE);
+ g_return_val_if_fail (out_users != NULL, FALSE);
+
+ *out_users = NULL;
+
+ for (ii = 0; in_strv[ii + 2]; ii++) {
+ *out_users = g_slist_prepend (*out_users, g_strdup (in_strv[ii + 2]));
+ }
+
+ *out_start = atoi (in_strv[0]);
+ *out_end = atoi (in_strv[1]);
+ *out_users = g_slist_reverse (*out_users);
+
+ return TRUE;
+}
+
+void
+e_gdbus_cal_call_get_free_busy (GDBusProxy *proxy, const gchar * const *in_start_end_userlist, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_strv ("getFreeBusy", e_gdbus_cal_call_get_free_busy, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_start_end_userlist, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_get_free_busy_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_cal_call_get_free_busy);
+}
+
+gboolean
+e_gdbus_cal_call_get_free_busy_sync (GDBusProxy *proxy, const gchar * const *in_start_end_userlist, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_strv__void (proxy, in_start_end_userlist, cancellable, error,
+ e_gdbus_cal_call_get_free_busy,
+ e_gdbus_cal_call_get_free_busy_finish);
+}
+
+void
+e_gdbus_cal_call_create_object (GDBusProxy *proxy, const gchar *in_calobj, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("createObject", e_gdbus_cal_call_create_object, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_calobj, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_create_object_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_uid, GError **error)
+{
+ return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_uid, error, e_gdbus_cal_call_create_object);
+}
+
+gboolean
+e_gdbus_cal_call_create_object_sync (GDBusProxy *proxy, const gchar *in_calobj, gchar **out_uid, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__string (proxy, in_calobj, out_uid, cancellable, error,
+ e_gdbus_cal_call_create_object,
+ e_gdbus_cal_call_create_object_finish);
+}
+
+/* free returned pointer with g_strfreev() */
+gchar **
+e_gdbus_cal_encode_modify_object (const gchar *in_calobj, guint in_mod)
+{
+ gchar **strv;
+
+ g_return_val_if_fail (in_calobj != NULL, NULL);
+
+ strv = g_new0 (gchar *, 3);
+ strv[0] = e_util_utf8_make_valid (in_calobj);
+ strv[1] = g_strdup_printf ("%u", (guint32) in_mod);
+ strv[2] = NULL;
+
+ return strv;
+}
+
+/* free out_calobj with g_free() */
+gboolean
+e_gdbus_cal_decode_modify_object (const gchar * const *in_strv, gchar **out_calobj, guint *out_mod)
+{
+ g_return_val_if_fail (in_strv != NULL, FALSE);
+ g_return_val_if_fail (in_strv[0] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[1] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[2] == NULL, FALSE);
+ g_return_val_if_fail (out_calobj != NULL, FALSE);
+ g_return_val_if_fail (out_mod != NULL, FALSE);
+
+ *out_calobj = g_strdup (in_strv[0]);
+ *out_mod = atoi (in_strv[1]);
+
+ return TRUE;
+}
+
+void
+e_gdbus_cal_call_modify_object (GDBusProxy *proxy, const gchar * const *in_calobj_mod, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_strv ("modifyObject", e_gdbus_cal_call_modify_object, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_calobj_mod, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_modify_object_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_cal_call_modify_object);
+}
+
+gboolean
+e_gdbus_cal_call_modify_object_sync (GDBusProxy *proxy, const gchar * const *in_calobj_mod, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_strv__void (proxy, in_calobj_mod, cancellable, error,
+ e_gdbus_cal_call_modify_object,
+ e_gdbus_cal_call_modify_object_finish);
+}
+
+/* free returned pointer with g_strfreev() */
+gchar **
+e_gdbus_cal_encode_remove_object (const gchar *in_uid, const gchar *in_rid, guint in_mod)
+{
+ gchar **strv;
+
+ g_return_val_if_fail (in_uid != NULL, NULL);
+
+ strv = g_new0 (gchar *, 4);
+ strv[0] = e_util_utf8_make_valid (in_uid);
+ strv[1] = e_util_utf8_make_valid (in_rid ? in_rid : "");
+ strv[2] = g_strdup_printf ("%u", (guint32) in_mod);
+ strv[3] = NULL;
+
+ return strv;
+}
+
+/* free out_uid and out_rid with g_free() */
+gboolean
+e_gdbus_cal_decode_remove_object (const gchar * const *in_strv, gchar **out_uid, gchar **out_rid, guint *out_mod)
+{
+ g_return_val_if_fail (in_strv != NULL, FALSE);
+ g_return_val_if_fail (in_strv[0] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[1] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[2] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[3] == NULL, FALSE);
+ g_return_val_if_fail (out_uid != NULL, FALSE);
+ g_return_val_if_fail (out_rid != NULL, FALSE);
+ g_return_val_if_fail (out_mod != NULL, FALSE);
+
+ *out_uid = g_strdup (in_strv[0]);
+ *out_rid = g_strdup (in_strv[1]);
+ *out_mod = atoi (in_strv[2]);
+
+ return TRUE;
+}
+
+void
+e_gdbus_cal_call_remove_object (GDBusProxy *proxy, const gchar * const *in_uid_rid_mod, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_strv ("removeObject", e_gdbus_cal_call_remove_object, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_uid_rid_mod, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_remove_object_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_cal_call_remove_object);
+}
+
+gboolean
+e_gdbus_cal_call_remove_object_sync (GDBusProxy *proxy, const gchar * const *in_uid_rid_mod, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_strv__void (proxy, in_uid_rid_mod, cancellable, error,
+ e_gdbus_cal_call_remove_object,
+ e_gdbus_cal_call_remove_object_finish);
+}
+
+void
+e_gdbus_cal_call_receive_objects (GDBusProxy *proxy, const gchar *in_calobj, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("receiveObjects", e_gdbus_cal_call_receive_objects, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_calobj, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_receive_objects_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_cal_call_receive_objects);
+}
+
+gboolean
+e_gdbus_cal_call_receive_objects_sync (GDBusProxy *proxy, const gchar *in_calobj, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__void (proxy, in_calobj, cancellable, error,
+ e_gdbus_cal_call_receive_objects,
+ e_gdbus_cal_call_receive_objects_finish);
+}
+
+/* free returned pointer with g_strfreev() */
+gchar **
+e_gdbus_cal_encode_send_objects (const gchar *in_calobj, const GSList *in_users)
+{
+ gint ii;
+ gchar **strv;
+
+ g_return_val_if_fail (in_calobj != NULL, NULL);
+
+ strv = g_new0 (gchar *, g_slist_length ((GSList *) in_users) + 2);
+ strv[0] = e_util_utf8_make_valid (in_calobj);
+ for (ii = 0; in_users; ii++, in_users = in_users->next) {
+ strv[ii + 1] = e_util_utf8_make_valid (in_users->data);
+ }
+ strv[ii + 1] = NULL;
+
+ return strv;
+}
+
+/* free out_calobj with g_free() and out_users with g_strfreev() */
+gboolean
+e_gdbus_cal_decode_send_objects (const gchar * const *in_strv, gchar **out_calobj, GSList **out_users)
+{
+ gint ii;
+
+ g_return_val_if_fail (in_strv != NULL, FALSE);
+ g_return_val_if_fail (in_strv[0] != NULL, FALSE);
+ g_return_val_if_fail (out_calobj != NULL, FALSE);
+ g_return_val_if_fail (out_users != NULL, FALSE);
+
+ *out_users = NULL;
+
+ for (ii = 0; in_strv[ii + 1]; ii++) {
+ *out_users = g_slist_prepend (*out_users, g_strdup (in_strv[ii + 1]));
+ }
+
+ *out_calobj = g_strdup (in_strv[0]);
+ *out_users = g_slist_reverse (*out_users);
+
+ return TRUE;
+}
+
+void
+e_gdbus_cal_call_send_objects (GDBusProxy *proxy, const gchar *in_calobj, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("sendObjects", e_gdbus_cal_call_send_objects, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_calobj, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_send_objects_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_calobj_users, GError **error)
+{
+ return e_gdbus_proxy_finish_call_strv (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_calobj_users, error, e_gdbus_cal_call_send_objects);
+}
+
+gboolean
+e_gdbus_cal_call_send_objects_sync (GDBusProxy *proxy, const gchar *in_calobj, gchar ***out_calobj_users, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__strv (proxy, in_calobj, out_calobj_users, cancellable, error,
+ e_gdbus_cal_call_send_objects,
+ e_gdbus_cal_call_send_objects_finish);
+}
+
+/* free returned pointer with g_strfreev() */
+gchar **
+e_gdbus_cal_encode_get_attachment_uris (const gchar *in_uid, const gchar *in_rid)
+{
+ return encode_string_string (in_uid, in_rid);
+}
+
+/* free out_uid and out_rid with g_free() */
+gboolean
+e_gdbus_cal_decode_get_attachment_uris (const gchar * const *in_strv, gchar **out_uid, gchar **out_rid)
+{
+ return decode_string_string (in_strv, out_uid, out_rid);
+}
+
+void
+e_gdbus_cal_call_get_attachment_uris (GDBusProxy *proxy, const gchar * const *in_uid_rid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_strv ("getAttachmentUris", e_gdbus_cal_call_get_attachment_uris, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_uid_rid, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_get_attachment_uris_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_attachments, GError **error)
+{
+ return e_gdbus_proxy_finish_call_strv (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_attachments, error, e_gdbus_cal_call_get_attachment_uris);
+}
+
+gboolean
+e_gdbus_cal_call_get_attachment_uris_sync (GDBusProxy *proxy, const gchar * const *in_uid_rid, gchar ***out_attachments, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_strv__strv (proxy, in_uid_rid, out_attachments, cancellable, error,
+ e_gdbus_cal_call_get_attachment_uris,
+ e_gdbus_cal_call_get_attachment_uris_finish);
+}
+
+/* free returned pointer with g_strfreev() */
+gchar **
+e_gdbus_cal_encode_discard_alarm (const gchar *in_uid, const gchar *in_rid, const gchar *in_auid)
+{
+ gchar **strv;
+
+ strv = g_new0 (gchar *, 4);
+ strv[0] = e_util_utf8_make_valid (in_uid ? in_uid : "");
+ strv[1] = e_util_utf8_make_valid (in_rid ? in_rid : "");
+ strv[2] = e_util_utf8_make_valid (in_auid ? in_auid : "");
+ strv[3] = NULL;
+
+ return strv;
+}
+
+/* free out_uid, out_rid and out_auid with g_free() */
+gboolean
+e_gdbus_cal_decode_discard_alarm (const gchar * const *in_strv, gchar **out_uid, gchar **out_rid, gchar **out_auid)
+{
+ g_return_val_if_fail (in_strv != NULL, FALSE);
+ g_return_val_if_fail (in_strv[0] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[1] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[2] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[3] == NULL, FALSE);
+ g_return_val_if_fail (out_uid != NULL, FALSE);
+ g_return_val_if_fail (out_rid != NULL, FALSE);
+ g_return_val_if_fail (out_auid != NULL, FALSE);
+
+ *out_uid = g_strdup (in_strv[0]);
+ *out_rid = g_strdup (in_strv[1]);
+ *out_auid = g_strdup (in_strv[2]);
+
+ return TRUE;
+}
+
+void
+e_gdbus_cal_call_discard_alarm (GDBusProxy *proxy, const gchar * const *in_uid_rid_auid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_strv ("discardAlarm", e_gdbus_cal_call_discard_alarm, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_uid_rid_auid, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_discard_alarm_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_cal_call_discard_alarm);
+}
+
+gboolean
+e_gdbus_cal_call_discard_alarm_sync (GDBusProxy *proxy, const gchar * const *in_uid_rid_auid, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_strv__void (proxy, in_uid_rid_auid, cancellable, error,
+ e_gdbus_cal_call_discard_alarm,
+ e_gdbus_cal_call_discard_alarm_finish);
+}
+
+void
+e_gdbus_cal_call_get_view (GDBusProxy *proxy, const gchar *in_sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("getView", e_gdbus_cal_call_get_view, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_sexp, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_get_view_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_view_path, GError **error)
+{
+ return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_view_path, error, e_gdbus_cal_call_get_view);
+}
+
+gboolean
+e_gdbus_cal_call_get_view_sync (GDBusProxy *proxy, const gchar *in_sexp, gchar **out_view_path, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__string (proxy, in_sexp, out_view_path, cancellable, error,
+ e_gdbus_cal_call_get_view,
+ e_gdbus_cal_call_get_view_finish);
+}
+
+void
+e_gdbus_cal_call_get_timezone (GDBusProxy *proxy, const gchar *in_tzid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("getTimezone", e_gdbus_cal_call_get_timezone, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_tzid, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_get_timezone_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_tzobject, GError **error)
+{
+ return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_tzobject, error, e_gdbus_cal_call_get_timezone);
+}
+
+gboolean
+e_gdbus_cal_call_get_timezone_sync (GDBusProxy *proxy, const gchar *in_tzid, gchar **out_tzobject, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__string (proxy, in_tzid, out_tzobject, cancellable, error,
+ e_gdbus_cal_call_get_timezone,
+ e_gdbus_cal_call_get_timezone_finish);
+}
+
+void
+e_gdbus_cal_call_add_timezone (GDBusProxy *proxy, const gchar *in_tzobject, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_call_string ("addTimezone", e_gdbus_cal_call_add_timezone, E_GDBUS_ASYNC_OP_KEEPER (proxy), in_tzobject, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_add_timezone_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_finish_call_void (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, error, e_gdbus_cal_call_add_timezone);
+}
+
+gboolean
+e_gdbus_cal_call_add_timezone_sync (GDBusProxy *proxy, const gchar *in_tzobject, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_call_sync_string__void (proxy, in_tzobject, cancellable, error,
+ e_gdbus_cal_call_add_timezone,
+ e_gdbus_cal_call_add_timezone_finish);
+}
+
+void
+e_gdbus_cal_call_authenticate_user (GDBusProxy *proxy, const gchar * const *in_credentials, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_strv ("authenticateUser", proxy, in_credentials, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_authenticate_user_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_cal_call_authenticate_user_sync (GDBusProxy *proxy, const gchar * const *in_credentials, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_strv__void ("authenticateUser", proxy, in_credentials, cancellable, error);
+}
+
+void
+e_gdbus_cal_call_cancel_operation (GDBusProxy *proxy, guint in_opid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_uint ("cancelOperation", proxy, in_opid, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_cancel_operation_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_cal_call_cancel_operation_sync (GDBusProxy *proxy, guint in_opid, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_uint__void ("cancelOperation", proxy, in_opid, cancellable, error);
+}
+
+void
+e_gdbus_cal_call_cancel_all (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_void ("cancelAll", proxy, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_cancel_all_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_cal_call_cancel_all_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_void__void ("cancelAll", proxy, cancellable, error);
+}
+
+void
+e_gdbus_cal_call_close (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ e_gdbus_proxy_method_call_void ("close", proxy, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_close_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return e_gdbus_proxy_method_call_finish_void (proxy, result, error);
+}
+
+gboolean
+e_gdbus_cal_call_close_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_proxy_method_call_sync_void__void ("close", proxy, cancellable, error);
+}
+
+#define DECLARE_EMIT_DONE_SIGNAL_0(_mname, _sig_id) \
+void \
+e_gdbus_cal_emit_ ## _mname ## _done (EGdbusCal *object, guint arg_opid, const GError *arg_error) \
+{ \
+ g_signal_emit (object, signals[_sig_id], 0, arg_opid, arg_error); \
+}
+
+#define DECLARE_EMIT_DONE_SIGNAL_1(_mname, _sig_id, _par_type) \
+void \
+e_gdbus_cal_emit_ ## _mname ## _done (EGdbusCal *object, guint arg_opid, const GError *arg_error, _par_type out_par) \
+{ \
+ g_signal_emit (object, signals[_sig_id], 0, arg_opid, arg_error, out_par); \
+}
+
+DECLARE_EMIT_DONE_SIGNAL_0 (open, __OPEN_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_0 (remove, __REMOVE_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_0 (refresh, __REFRESH_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_1 (get_backend_property, __GET_BACKEND_PROPERTY_DONE_SIGNAL, const gchar *)
+DECLARE_EMIT_DONE_SIGNAL_0 (set_backend_property, __SET_BACKEND_PROPERTY_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_1 (get_object, __GET_OBJECT_DONE_SIGNAL, const gchar *)
+DECLARE_EMIT_DONE_SIGNAL_1 (get_object_list, __GET_OBJECT_LIST_DONE_SIGNAL, const gchar * const *)
+DECLARE_EMIT_DONE_SIGNAL_0 (get_free_busy, __GET_FREE_BUSY_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_1 (create_object, __CREATE_OBJECT_DONE_SIGNAL, const gchar *)
+DECLARE_EMIT_DONE_SIGNAL_0 (modify_object, __MODIFY_OBJECT_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_0 (remove_object, __REMOVE_OBJECT_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_0 (receive_objects, __RECEIVE_OBJECTS_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_1 (send_objects, __SEND_OBJECTS_DONE_SIGNAL, const gchar * const *)
+DECLARE_EMIT_DONE_SIGNAL_1 (get_attachment_uris, __GET_ATTACHMENT_URIS_DONE_SIGNAL, const gchar * const *)
+DECLARE_EMIT_DONE_SIGNAL_0 (discard_alarm, __DISCARD_ALARM_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_1 (get_view, __GET_VIEW_DONE_SIGNAL, const gchar *)
+DECLARE_EMIT_DONE_SIGNAL_1 (get_timezone, __GET_TIMEZONE_DONE_SIGNAL, const gchar *)
+DECLARE_EMIT_DONE_SIGNAL_0 (add_timezone, __ADD_TIMEZONE_DONE_SIGNAL)
+
+void
+e_gdbus_cal_emit_backend_error (EGdbusCal *object, const gchar *arg_message)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (arg_message != NULL);
+
+ g_signal_emit (object, signals[__BACKEND_ERROR_SIGNAL], 0, arg_message);
+}
+
+void
+e_gdbus_cal_emit_readonly (EGdbusCal *object, gboolean arg_is_readonly)
+{
+ g_signal_emit (object, signals[__READONLY_SIGNAL], 0, arg_is_readonly);
+}
+
+void
+e_gdbus_cal_emit_online (EGdbusCal *object, gboolean arg_is_online)
+{
+ g_signal_emit (object, signals[__ONLINE_SIGNAL], 0, arg_is_online);
+}
+
+void
+e_gdbus_cal_emit_auth_required (EGdbusCal *object, const gchar * const *arg_credentials)
+{
+ g_signal_emit (object, signals[__AUTH_REQUIRED_SIGNAL], 0, arg_credentials);
+}
+
+void
+e_gdbus_cal_emit_opened (EGdbusCal *object, const gchar * const *arg_error)
+{
+ g_signal_emit (object, signals[__OPENED_SIGNAL], 0, arg_error);
+}
+
+void
+e_gdbus_cal_emit_free_busy_data (EGdbusCal *object, const gchar * const *arg_free_busy)
+{
+ g_signal_emit (object, signals[__FREE_BUSY_DATA_SIGNAL], 0, arg_free_busy);
+}
+
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (cal, backend_error, message, "s")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (cal, readonly, is_readonly, "b")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (cal, online, is_online, "b")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (cal, auth_required, credentials, "as")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (cal, opened, error, "as")
+E_DECLARE_GDBUS_NOTIFY_SIGNAL_1 (cal, free_busy_data, free_busy_data, "as")
+
+E_DECLARE_GDBUS_ASYNC_METHOD_1 (cal, open, only_if_exists, "b")
+E_DECLARE_GDBUS_ASYNC_METHOD_0 (cal, remove)
+E_DECLARE_GDBUS_ASYNC_METHOD_0 (cal, refresh)
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (cal, getBackendProperty, propname, "s", propvalue, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_1 (cal, setBackendProperty, propnamevalue, "as")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (cal, getObject, uid_rid, "as", object, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (cal, getObjectList, sexp, "s", objects, "as")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (cal, getFreeBusy, start_stop_users, "as", freebusy, "as")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (cal, createObject, object, "s", uid, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_1 (cal, modifyObject, object_mod, "as")
+E_DECLARE_GDBUS_ASYNC_METHOD_1 (cal, removeObject, uid_rid_mod, "as")
+E_DECLARE_GDBUS_ASYNC_METHOD_1 (cal, receiveObjects, object, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (cal, sendObjects, object, "s", object_users, "as")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (cal, getAttachmentUris, uid_rid, "as", attachments, "as")
+E_DECLARE_GDBUS_ASYNC_METHOD_1 (cal, discardAlarm, uid_rid_auid, "as")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (cal, getView, sexp, "s", view_path, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN (cal, getTimezone, tzid, "s", tzobject, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_1 (cal, addTimezone, tzobject, "s")
+
+E_DECLARE_GDBUS_SYNC_METHOD_1 (cal, authenticateUser, credentials, "as")
+E_DECLARE_GDBUS_SYNC_METHOD_1 (cal, cancelOperation, opid, "u")
+E_DECLARE_GDBUS_SYNC_METHOD_0 (cal, cancelAll)
+E_DECLARE_GDBUS_SYNC_METHOD_0 (cal, close)
+
+static const GDBusMethodInfo * const e_gdbus_cal_method_info_pointers[] =
+{
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, open),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, remove),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, refresh),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getBackendProperty),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, setBackendProperty),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getObject),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getObjectList),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getFreeBusy),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, createObject),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, modifyObject),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, removeObject),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, receiveObjects),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, sendObjects),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getAttachmentUris),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, discardAlarm),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getView),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, getTimezone),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, addTimezone),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, authenticateUser),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, cancelOperation),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, cancelAll),
+ &E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, close),
+ NULL
+};
+
+static const GDBusSignalInfo * const e_gdbus_cal_signal_info_pointers[] =
+{
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, backend_error),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, readonly),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, online),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, auth_required),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, opened),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, free_busy_data),
+
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, open_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, remove_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, refresh_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getBackendProperty_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, setBackendProperty_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getObject_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getObjectList_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getFreeBusy_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, createObject_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, modifyObject_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, removeObject_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, receiveObjects_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, sendObjects_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getAttachmentUris_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, discardAlarm_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getView_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, getTimezone_done),
+ &E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, addTimezone_done),
+ NULL
+};
+
+static const GDBusInterfaceInfo _e_gdbus_cal_interface_info =
+{
+ -1,
+ (gchar *) GDBUS_CAL_INTERFACE_NAME,
+ (GDBusMethodInfo **) &e_gdbus_cal_method_info_pointers,
+ (GDBusSignalInfo **) &e_gdbus_cal_signal_info_pointers,
+ (GDBusPropertyInfo **) NULL
+};
+
+static void
+handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ guint method_id, method_type;
+
+ method_id = lookup_method_id_from_method_name (method_name);
+ method_type = lookup_method_type_from_method_name (method_name);
+
+ g_return_if_fail (method_id != 0);
+ g_return_if_fail (method_type != 0);
+
+ e_gdbus_stub_handle_method_call (user_data, invocation, parameters, method_name, signals[method_id], method_type);
+}
+
+static GVariant *
+get_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data)
+{
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This implementation does not support property `%s'", property_name);
+ return NULL;
+}
+
+static gboolean
+set_property (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GVariant *value, GError **error, gpointer user_data)
+{
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This implementation does not support property `%s'", property_name);
+ return FALSE;
+}
+
+static const GDBusInterfaceVTable e_gdbus_cal_interface_vtable =
+{
+ handle_method_call,
+ get_property,
+ set_property
+};
+
+static gboolean
+emit_notifications_in_idle (gpointer user_data)
+{
+ GObject *object = G_OBJECT (user_data);
+ GDBusConnection *connection;
+ const gchar *path;
+ GHashTable *notification_queue;
+ GHashTableIter iter;
+ const gchar *property_name;
+ GVariant *value;
+ GVariantBuilder *builder;
+ GVariantBuilder *invalidated_builder;
+ GHashTable *pvc;
+ gboolean has_changes;
+
+ notification_queue = g_object_get_data (object, "gdbus-codegen-notification-queue");
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ pvc = g_object_get_data (object, "gdbus-codegen-pvc");
+ g_assert (notification_queue != NULL && path != NULL && connection != NULL && pvc != NULL);
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
+ invalidated_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ g_hash_table_iter_init (&iter, notification_queue);
+ has_changes = FALSE;
+ while (g_hash_table_iter_next (&iter, (gpointer) &property_name, (gpointer) &value)) {
+ GVariant *cached_value;
+ cached_value = g_hash_table_lookup (pvc, property_name);
+ if (cached_value == NULL || !g_variant_equal (cached_value, value)) {
+ g_hash_table_insert (pvc, (gpointer) property_name, (gpointer) g_variant_ref (value));
+ g_variant_builder_add (builder, "{sv}", property_name, value);
+ has_changes = TRUE;
+ }
+ }
+
+ if (has_changes) {
+ g_dbus_connection_emit_signal (connection,
+ NULL,
+ path,
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ g_variant_new ("(sa{sv}as)",
+ GDBUS_CAL_INTERFACE_NAME,
+ builder,
+ invalidated_builder),
+ NULL);
+ } else {
+ g_variant_builder_unref (builder);
+ g_variant_builder_unref (invalidated_builder);
+ }
+
+ g_hash_table_remove_all (notification_queue);
+ g_object_set_data (object, "gdbus-codegen-notification-idle-id", GUINT_TO_POINTER (0));
+ return FALSE;
+}
+
+/**
+ * e_gdbus_cal_drain_notify:
+ * @object: A #EGdbusCal that is exported.
+ *
+ * If @object has queued notifications, empty the queue forcing
+ * the <literal>PropertiesChanged</literal> signal to be emitted.
+ * See <xref linkend="EGdbusCal.description"/> for more background information.
+ */
+void
+e_gdbus_cal_drain_notify (EGdbusCal *object)
+{
+ gint idle_id;
+ idle_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (object), "gdbus-codegen-notification-idle-id"));
+ if (idle_id > 0) {
+ emit_notifications_in_idle (object);
+ g_source_remove (idle_id);
+ }
+}
+
+static void
+on_object_unregistered (GObject *object)
+{
+ gint idle_id;
+ idle_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (object), "gdbus-codegen-notification-idle-id"));
+ if (idle_id > 0) {
+ g_source_remove (idle_id);
+ }
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-path", NULL);
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-connection", NULL);
+}
+
+/**
+ * e_gdbus_cal_register_object:
+ * @object: An instance of a #GObject<!-- -->-derived type implementing the #EGdbusCal interface.
+ * @connection: A #GDBusConnection.
+ * @object_path: The object to register the object at.
+ * @error: Return location for error or %NULL.
+ *
+ * Registers @object at @object_path on @connection.
+ *
+ * See <xref linkend="EGdbusCal.description"/>
+ * for how properties, methods and signals are handled.
+ *
+ * Returns: 0 if @error is set, otherwise a registration id (never 0) that can be used with g_dbus_connection_unregister_object().
+ */
+guint
+e_gdbus_cal_register_object (EGdbusCal *object, GDBusConnection *connection, const gchar *object_path, GError **error)
+{
+ GHashTable *pvc;
+
+ pvc = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_variant_unref);
+
+ g_object_set_data_full (G_OBJECT (object), "gdbus-codegen-path", (gpointer) g_strdup (object_path), g_free);
+ g_object_set_data (G_OBJECT (object), "gdbus-codegen-connection", (gpointer) connection);
+ g_object_set_data_full (G_OBJECT (object), "gdbus-codegen-pvc", (gpointer) pvc, (GDestroyNotify) g_hash_table_unref);
+
+ return g_dbus_connection_register_object (connection,
+ object_path,
+ (GDBusInterfaceInfo *) &_e_gdbus_cal_interface_info,
+ &e_gdbus_cal_interface_vtable,
+ object,
+ (GDestroyNotify) on_object_unregistered,
+ error);
+}
+
+/**
+ * e_gdbus_cal_interface_info:
+ *
+ * Gets interface description for the <literal>org.gnome.evolution.dataserver.Calendar</literal> D-Bus interface.
+ *
+ * Returns: A #GDBusInterfaceInfo. Do not free, the object is statically allocated.
+ */
+const GDBusInterfaceInfo *
+e_gdbus_cal_interface_info (void)
+{
+ return &_e_gdbus_cal_interface_info;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void proxy_iface_init (EGdbusCalIface *iface);
+static void async_op_keeper_iface_init (EGdbusAsyncOpKeeperInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EGdbusCalProxy, e_gdbus_cal_proxy, G_TYPE_DBUS_PROXY,
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_CAL, proxy_iface_init)
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_ASYNC_OP_KEEPER, async_op_keeper_iface_init));
+
+static void
+e_gdbus_cal_proxy_init (EGdbusCalProxy *proxy)
+{
+ g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), (GDBusInterfaceInfo *) &_e_gdbus_cal_interface_info);
+
+ proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, E_TYPE_GDBUS_CAL_PROXY, EGdbusCalProxyPrivate);
+ proxy->priv->pending_ops = e_gdbus_async_op_keeper_create_pending_ops (E_GDBUS_ASYNC_OP_KEEPER (proxy));
+
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (open);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (remove);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (refresh);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_backend_property);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (set_backend_property);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_object);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRV (get_object_list);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRV (get_free_busy);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (create_object);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (modify_object);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (remove_object);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (receive_objects);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRV (send_objects);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRV (get_attachment_uris);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (discard_alarm);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_view);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_timezone);
+ E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID (add_timezone);
+}
+
+static void
+g_signal (GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters)
+{
+ guint signal_id, signal_type;
+
+ signal_id = lookup_signal_id_from_signal_name (signal_name);
+ signal_type = lookup_signal_type_from_signal_name (signal_name);
+
+ g_return_if_fail (signal_id != 0);
+ g_return_if_fail (signal_type != 0);
+
+ e_gdbus_proxy_emit_signal (proxy, parameters, signals[signal_id], signal_type);
+}
+
+static void
+gdbus_cal_proxy_finalize (GObject *object)
+{
+ EGdbusCalProxy *proxy = E_GDBUS_CAL_PROXY (object);
+
+ g_return_if_fail (proxy != NULL);
+ g_return_if_fail (proxy->priv != NULL);
+
+ if (g_hash_table_size (proxy->priv->pending_ops))
+ g_debug ("%s: Kept %d items in pending_ops", G_STRFUNC, g_hash_table_size (proxy->priv->pending_ops));
+
+ g_hash_table_destroy (proxy->priv->pending_ops);
+
+ G_OBJECT_CLASS (e_gdbus_cal_proxy_parent_class)->finalize (object);
+}
+
+static void
+e_gdbus_cal_proxy_class_init (EGdbusCalProxyClass *klass)
+{
+ GObjectClass *object_class;
+ GDBusProxyClass *proxy_class;
+
+ g_type_class_add_private (klass, sizeof (EGdbusCalProxyPrivate));
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gdbus_cal_proxy_finalize;
+
+ proxy_class = G_DBUS_PROXY_CLASS (klass);
+ proxy_class->g_signal = g_signal;
+}
+
+static void
+proxy_iface_init (EGdbusCalIface *iface)
+{
+}
+
+static GHashTable *
+gdbus_cal_get_pending_ops (EGdbusAsyncOpKeeper *object)
+{
+ EGdbusCalProxy *proxy;
+
+ g_return_val_if_fail (object != NULL, NULL);
+ g_return_val_if_fail (E_IS_GDBUS_CAL_PROXY (object), NULL);
+
+ proxy = E_GDBUS_CAL_PROXY (object);
+ g_return_val_if_fail (proxy != NULL, NULL);
+ g_return_val_if_fail (proxy->priv != NULL, NULL);
+
+ return proxy->priv->pending_ops;
+}
+
+static gboolean
+gdbus_cal_call_cancel_operation_sync (EGdbusAsyncOpKeeper *object, guint in_opid, GCancellable *cancellable, GError **error)
+{
+ return e_gdbus_cal_call_cancel_operation_sync (G_DBUS_PROXY (object), in_opid, cancellable, error);
+}
+
+static void
+async_op_keeper_iface_init (EGdbusAsyncOpKeeperInterface *iface)
+{
+ g_return_if_fail (iface != NULL);
+
+ iface->get_pending_ops = gdbus_cal_get_pending_ops;
+ iface->cancel_op_sync = gdbus_cal_call_cancel_operation_sync;
+}
+
+/**
+ * e_gdbus_cal_proxy_new:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: Callback function to invoke when the proxy is ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_dbus_proxy_new() but returns a #EGdbusCalProxy.
+ *
+ * This is a failable asynchronous constructor - when the proxy is ready, callback will be invoked and you can use e_gdbus_cal_proxy_new_finish() to get the result.
+ */
+void
+e_gdbus_cal_proxy_new (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ g_async_initable_new_async (E_TYPE_GDBUS_CAL_PROXY,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "g-flags", flags,
+ "g-name", name,
+ "g-connection", connection,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_CAL_INTERFACE_NAME,
+ NULL);
+}
+
+/**
+ * e_gdbus_cal_proxy_new_finish:
+ * @result: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to e_gdbus_cal_proxy_new().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes creating a #EGdbusCalProxy.
+ *
+ * Returns: A #EGdbusCalProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+EGdbusCal *
+e_gdbus_cal_proxy_new_finish (GAsyncResult *result, GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (result);
+ g_assert (source_object != NULL);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error);
+ g_object_unref (source_object);
+ if (object != NULL)
+ return E_GDBUS_CAL (object);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_cal_proxy_new_sync:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_proxy_new_sync() but returns a #EGdbusCalProxy.
+ *
+ * This is a synchronous failable constructor. See e_gdbus_cal_proxy_new() and e_gdbus_cal_proxy_new_finish() for the asynchronous version.
+ *
+ * Returns: A #EGdbusCalProxy or %NULL if error is set. Free with g_object_unref().
+ */
+EGdbusCal *
+e_gdbus_cal_proxy_new_sync (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error)
+{
+ GInitable *initable;
+ initable = g_initable_new (E_TYPE_GDBUS_CAL_PROXY,
+ cancellable,
+ error,
+ "g-flags", flags,
+ "g-name", name,
+ "g-connection", connection,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_CAL_INTERFACE_NAME,
+ NULL);
+ if (initable != NULL)
+ return E_GDBUS_CAL (initable);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_cal_proxy_new_for_bus:
+ * @bus_type: A #GBusType.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: Callback function to invoke when the proxy is ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_dbus_proxy_new_for_bus() but returns a #EGdbusCalProxy.
+ *
+ * This is a failable asynchronous constructor - when the proxy is ready, callback will be invoked and you can use e_gdbus_cal_proxy_new_for_bus_finish() to get the result.
+ */
+void
+e_gdbus_cal_proxy_new_for_bus (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ g_async_initable_new_async (E_TYPE_GDBUS_CAL_PROXY,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "g-flags", flags,
+ "g-name", name,
+ "g-bus-type", bus_type,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_CAL_INTERFACE_NAME,
+ NULL);
+}
+
+/**
+ * e_gdbus_cal_proxy_new_for_bus_finish:
+ * @result: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to e_gdbus_cal_proxy_new_for_bus().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes creating a #EGdbusCalProxy.
+ *
+ * Returns: A #EGdbusCalProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+EGdbusCal *
+e_gdbus_cal_proxy_new_for_bus_finish (GAsyncResult *result, GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (result);
+ g_assert (source_object != NULL);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), result, error);
+ g_object_unref (source_object);
+ if (object != NULL)
+ return E_GDBUS_CAL (object);
+ else
+ return NULL;
+}
+
+/**
+ * e_gdbus_cal_proxy_new_for_bus_sync:
+ * @bus_type: A #GBusType.
+ * @flags: Flags used when constructing the proxy.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_proxy_new_for_bus_sync() but returns a #EGdbusCalProxy.
+ *
+ * This is a synchronous failable constructor. See e_gdbus_cal_proxy_new_for_bus() and e_gdbus_cal_proxy_new_for_bus_finish() for the asynchronous version.
+ *
+ * Returns: A #EGdbusCalProxy or %NULL if error is set. Free with g_object_unref().
+ */
+EGdbusCal *
+e_gdbus_cal_proxy_new_for_bus_sync (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error)
+{
+ GInitable *initable;
+ initable = g_initable_new (E_TYPE_GDBUS_CAL_PROXY,
+ cancellable,
+ error,
+ "g-flags", flags,
+ "g-name", name,
+ "g-bus-type", bus_type,
+ "g-object-path", object_path,
+ "g-interface-name", GDBUS_CAL_INTERFACE_NAME,
+ NULL);
+ if (initable != NULL)
+ return E_GDBUS_CAL (initable);
+ else
+ return NULL;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct _EGdbusCalStubPrivate
+{
+ gint foo;
+};
+
+static void stub_iface_init (EGdbusCalIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EGdbusCalStub, e_gdbus_cal_stub, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (E_TYPE_GDBUS_CAL, stub_iface_init));
+
+static void
+e_gdbus_cal_stub_init (EGdbusCalStub *stub)
+{
+ stub->priv = G_TYPE_INSTANCE_GET_PRIVATE (stub, E_TYPE_GDBUS_CAL_STUB, EGdbusCalStubPrivate);
+}
+
+static void
+e_gdbus_cal_stub_class_init (EGdbusCalStubClass *klass)
+{
+ g_type_class_add_private (klass, sizeof (EGdbusCalStubPrivate));
+}
+
+static void
+stub_iface_init (EGdbusCalIface *iface)
+{
+}
+
+/**
+ * e_gdbus_cal_stub_new:
+ *
+ * Creates a new stub object that can be exported via e_gdbus_cal_register_object().
+ *
+ * Returns: A #EGdbusCalStub instance. Free with g_object_unref().
+ */
+EGdbusCal *
+e_gdbus_cal_stub_new (void)
+{
+ return E_GDBUS_CAL (g_object_new (E_TYPE_GDBUS_CAL_STUB, NULL));
+}
+
+/* Returns GDBus connection associated with the stub object */
+GDBusConnection *
+e_gdbus_cal_stub_get_connection (EGdbusCal *stub)
+{
+ g_return_val_if_fail (stub != NULL, NULL);
+ g_return_val_if_fail (E_IS_GDBUS_CAL_STUB (stub), NULL);
+
+ return g_object_get_data (G_OBJECT (stub), "gdbus-codegen-connection");
+}
diff --git a/calendar/libegdbus/e-gdbus-cal.h b/calendar/libegdbus/e-gdbus-cal.h
new file mode 100644
index 0000000..21e2c7d
--- /dev/null
+++ b/calendar/libegdbus/e-gdbus-cal.h
@@ -0,0 +1,333 @@
+/*
+ * e-gdbus-cal.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_GDBUS_CAL_H
+#define E_GDBUS_CAL_H
+
+#include <gio/gio.h>
+
+#include <libedataserver/e-gdbus-templates.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_GDBUS_CAL (e_gdbus_cal_get_type ())
+#define E_GDBUS_CAL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_GDBUS_CAL, EGdbusCal))
+#define E_IS_GDBUS_CAL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_GDBUS_CAL))
+#define E_GDBUS_CAL_GET_IFACE(o)(G_TYPE_INSTANCE_GET_INTERFACE((o), E_TYPE_GDBUS_CAL, EGdbusCalIface))
+
+typedef struct _EGdbusCal EGdbusCal; /* Dummy typedef */
+typedef struct _EGdbusCalIface EGdbusCalIface;
+
+GType e_gdbus_cal_get_type (void) G_GNUC_CONST;
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct _EGdbusCalProxy EGdbusCalProxy;
+typedef struct _EGdbusCalProxyClass EGdbusCalProxyClass;
+typedef struct _EGdbusCalProxyPrivate EGdbusCalProxyPrivate;
+
+struct _EGdbusCalProxy
+{
+ GDBusProxy parent_instance;
+ EGdbusCalProxyPrivate *priv;
+};
+
+struct _EGdbusCalProxyClass
+{
+ GDBusProxyClass parent_class;
+};
+
+#define E_TYPE_GDBUS_CAL_PROXY (e_gdbus_cal_proxy_get_type ())
+#define E_GDBUS_CAL_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_GDBUS_CAL_PROXY, EGdbusCalProxy))
+#define E_IS_GDBUS_CAL_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_GDBUS_CAL_PROXY))
+GType e_gdbus_cal_proxy_get_type (void) G_GNUC_CONST;
+
+void e_gdbus_cal_proxy_new (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+EGdbusCal * e_gdbus_cal_proxy_new_finish (GAsyncResult *result, GError **error);
+EGdbusCal * e_gdbus_cal_proxy_new_sync (GDBusConnection *connection, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_proxy_new_for_bus (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+EGdbusCal * e_gdbus_cal_proxy_new_for_bus_finish (GAsyncResult *result, GError **error);
+EGdbusCal * e_gdbus_cal_proxy_new_for_bus_sync (GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error);
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct _EGdbusCalStub EGdbusCalStub;
+typedef struct _EGdbusCalStubClass EGdbusCalStubClass;
+typedef struct _EGdbusCalStubPrivate EGdbusCalStubPrivate;
+
+struct _EGdbusCalStub
+{
+ GObject parent_instance;
+ EGdbusCalStubPrivate *priv;
+};
+
+struct _EGdbusCalStubClass
+{
+ GObjectClass parent_class;
+};
+
+#define E_TYPE_GDBUS_CAL_STUB (e_gdbus_cal_stub_get_type ())
+#define E_GDBUS_CAL_STUB(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_GDBUS_CAL_STUB, EGdbusCalStub))
+#define E_IS_GDBUS_CAL_STUB(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_GDBUS_CAL_STUB))
+GType e_gdbus_cal_stub_get_type (void) G_GNUC_CONST;
+
+EGdbusCal *e_gdbus_cal_stub_new (void);
+GDBusConnection *e_gdbus_cal_stub_get_connection (EGdbusCal *stub);
+
+guint e_gdbus_cal_register_object (EGdbusCal *object, GDBusConnection *connection, const gchar *object_path, GError **error);
+void e_gdbus_cal_drain_notify (EGdbusCal *object);
+
+const GDBusInterfaceInfo *e_gdbus_cal_interface_info (void) G_GNUC_CONST;
+
+struct _EGdbusCalIface
+{
+ GTypeInterface parent_iface;
+
+ /* Signal handlers for receiving D-Bus signals: */
+ void (*backend_error) (EGdbusCal *object, const gchar *arg_message);
+ void (*readonly) (EGdbusCal *object, gboolean arg_is_readonly);
+ void (*online) (EGdbusCal *object, gboolean arg_is_online);
+ void (*auth_required) (EGdbusCal *object, const gchar * const *arg_credentials);
+ void (*opened) (EGdbusCal *object, const gchar * const *arg_error);
+ void (*free_busy_data) (EGdbusCal *object, const gchar * const *arg_free_busy);
+
+ /* Signal handlers for handling D-Bus method calls: */
+ gboolean (*handle_open) (EGdbusCal *object, GDBusMethodInvocation *invocation, gboolean in_only_if_exists);
+ void (*open_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_remove) (EGdbusCal *object, GDBusMethodInvocation *invocation);
+ void (*remove_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_refresh) (EGdbusCal *object, GDBusMethodInvocation *invocation);
+ void (*refresh_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_get_backend_property) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_prop_name);
+ void (*get_backend_property_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar **out_prop_value);
+
+ gboolean (*handle_set_backend_property) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_prop_name_value);
+ void (*set_backend_property_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_get_object) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_uid_rid);
+ void (*get_object_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar **out_object);
+
+ gboolean (*handle_get_object_list) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_sexp);
+ void (*get_object_list_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar ***out_objects);
+
+ gboolean (*handle_get_free_busy) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_start_end_userlist);
+ void (*get_free_busy_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_create_object) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_calobj);
+ void (*create_object_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar **out_uid);
+
+ gboolean (*handle_modify_object) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_calobj_mod);
+ void (*modify_object_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_remove_object) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_uid_rid_mod);
+ void (*remove_object_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_receive_objects) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_calobj);
+ void (*receive_objects_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_send_objects) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_calobj);
+ void (*send_objects_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar ***out_calobj_users);
+
+ gboolean (*handle_get_attachment_uris) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_uid_rid);
+ void (*get_attachment_uris_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar ***out_attachments);
+
+ gboolean (*handle_discard_alarm) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_uid_rid_auid);
+ void (*discard_alarm_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_get_view) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_sexp);
+ void (*get_view_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar **out_view_path);
+
+ gboolean (*handle_get_timezone) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_tzid);
+ void (*get_timezone_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar **out_tzobject);
+
+ gboolean (*handle_add_timezone) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_tzobject);
+ void (*add_timezone_done) (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+
+ gboolean (*handle_authenticate_user) (EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_credentials);
+ gboolean (*handle_cancel_operation) (EGdbusCal *object, GDBusMethodInvocation *invocation, guint in_opid);
+ gboolean (*handle_cancel_all) (EGdbusCal *object, GDBusMethodInvocation *invocation);
+ gboolean (*handle_close) (EGdbusCal *object, GDBusMethodInvocation *invocation);
+};
+
+/* D-Bus Methods */
+void e_gdbus_cal_call_open (GDBusProxy *proxy, gboolean in_only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_open_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_open_sync (GDBusProxy *proxy, gboolean in_only_if_exists, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_call_remove (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_remove_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_remove_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_call_refresh (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_refresh_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_refresh_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_call_get_backend_property (GDBusProxy *proxy, const gchar *in_prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_get_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_prop_value, GError **error);
+gboolean e_gdbus_cal_call_get_backend_property_sync (GDBusProxy *proxy, const gchar *in_prop_name, gchar **out_prop_value, GCancellable *cancellable, GError **error);
+
+gchar ** e_gdbus_cal_encode_set_backend_property (const gchar *in_prop_name, const gchar *in_prop_value);
+gboolean e_gdbus_cal_decode_set_backend_property (const gchar * const *in_strv, gchar **out_prop_name, gchar **out_prop_value);
+void e_gdbus_cal_call_set_backend_property (GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_set_backend_property_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_set_backend_property_sync (GDBusProxy *proxy, const gchar * const *in_prop_name_value, GCancellable *cancellable, GError **error);
+
+gchar ** e_gdbus_cal_encode_get_object (const gchar *in_uid, const gchar *in_rid);
+gboolean e_gdbus_cal_decode_get_object (const gchar * const *in_strv, gchar **out_uid, gchar **out_rid);
+void e_gdbus_cal_call_get_object (GDBusProxy *proxy, const gchar * const *in_uid_rid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_get_object_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_object, GError **error);
+gboolean e_gdbus_cal_call_get_object_sync (GDBusProxy *proxy, const gchar * const *in_uid_rid, gchar **out_object, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_call_get_object_list (GDBusProxy *proxy, const gchar *in_sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_get_object_list_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_objects, GError **error);
+gboolean e_gdbus_cal_call_get_object_list_sync (GDBusProxy *proxy, const gchar *in_sexp, gchar ***out_objects, GCancellable *cancellable, GError **error);
+
+gchar ** e_gdbus_cal_encode_get_free_busy (guint in_start, guint in_end, const GSList *in_users);
+gboolean e_gdbus_cal_decode_get_free_busy (const gchar * const *in_strv, guint *out_start, guint *out_end, GSList **out_users);
+void e_gdbus_cal_call_get_free_busy (GDBusProxy *proxy, const gchar * const *in_start_end_userlist, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_get_free_busy_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_get_free_busy_sync (GDBusProxy *proxy, const gchar * const *in_start_end_userlist, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_call_create_object (GDBusProxy *proxy, const gchar *in_calobj, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_create_object_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_uid, GError **error);
+gboolean e_gdbus_cal_call_create_object_sync (GDBusProxy *proxy, const gchar *in_calobj, gchar **out_uid, GCancellable *cancellable, GError **error);
+
+gchar ** e_gdbus_cal_encode_modify_object (const gchar *in_calobj, guint in_mod);
+gboolean e_gdbus_cal_decode_modify_object (const gchar * const *in_strv, gchar **out_calobj, guint *out_mod);
+void e_gdbus_cal_call_modify_object (GDBusProxy *proxy, const gchar * const *in_calobj_mod, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_modify_object_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_modify_object_sync (GDBusProxy *proxy, const gchar * const *in_calobj_mod, GCancellable *cancellable, GError **error);
+
+gchar ** e_gdbus_cal_encode_remove_object (const gchar *in_uid, const gchar *in_rid, guint in_mod);
+gboolean e_gdbus_cal_decode_remove_object (const gchar * const *in_strv, gchar **out_uid, gchar **out_rid, guint *out_mod);
+void e_gdbus_cal_call_remove_object (GDBusProxy *proxy, const gchar * const *in_uid_rid_mod, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_remove_object_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_remove_object_sync (GDBusProxy *proxy, const gchar * const *in_uid_rid_mod, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_call_receive_objects (GDBusProxy *proxy, const gchar *in_calobj, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_receive_objects_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_receive_objects_sync (GDBusProxy *proxy, const gchar *in_calobj, GCancellable *cancellable, GError **error);
+
+gchar ** e_gdbus_cal_encode_send_objects (const gchar *in_calobj, const GSList *in_users);
+gboolean e_gdbus_cal_decode_send_objects (const gchar * const *in_strv, gchar **out_calobj, GSList **out_users);
+void e_gdbus_cal_call_send_objects (GDBusProxy *proxy, const gchar *in_calobj, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_send_objects_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_calobj_users, GError **error);
+gboolean e_gdbus_cal_call_send_objects_sync (GDBusProxy *proxy, const gchar *in_calobj, gchar ***out_calobj_users, GCancellable *cancellable, GError **error);
+
+gchar ** e_gdbus_cal_encode_get_attachment_uris (const gchar *in_uid, const gchar *in_rid);
+gboolean e_gdbus_cal_decode_get_attachment_uris (const gchar * const *in_strv, gchar **out_uid, gchar **out_rid);
+void e_gdbus_cal_call_get_attachment_uris (GDBusProxy *proxy, const gchar * const *in_uid_rid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_get_attachment_uris_finish (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_attachments, GError **error);
+gboolean e_gdbus_cal_call_get_attachment_uris_sync (GDBusProxy *proxy, const gchar * const *in_uid_rid, gchar ***out_attachments, GCancellable *cancellable, GError **error);
+
+gchar ** e_gdbus_cal_encode_discard_alarm (const gchar *in_uid, const gchar *in_rid, const gchar *in_auid);
+gboolean e_gdbus_cal_decode_discard_alarm (const gchar * const *in_strv, gchar **out_uid, gchar **out_rid, gchar **out_auid);
+void e_gdbus_cal_call_discard_alarm (GDBusProxy *proxy, const gchar * const *in_uid_rid_auid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_discard_alarm_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_discard_alarm_sync (GDBusProxy *proxy, const gchar * const *in_uid_rid_auid, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_call_get_view (GDBusProxy *proxy, const gchar *in_sexp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_get_view_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_view_path, GError **error);
+gboolean e_gdbus_cal_call_get_view_sync (GDBusProxy *proxy, const gchar *in_sexp, gchar **out_view_path, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_call_get_timezone (GDBusProxy *proxy, const gchar *in_tzid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_get_timezone_finish (GDBusProxy *proxy, GAsyncResult *result, gchar **out_tzobject, GError **error);
+gboolean e_gdbus_cal_call_get_timezone_sync (GDBusProxy *proxy, const gchar *in_tzid, gchar **out_tzobject, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_call_add_timezone (GDBusProxy *proxy, const gchar *in_tzobject, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_add_timezone_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_add_timezone_sync (GDBusProxy *proxy, const gchar *in_tzobject, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_call_authenticate_user (GDBusProxy *proxy, const gchar * const *in_credentials, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_authenticate_user_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_authenticate_user_sync (GDBusProxy *proxy, const gchar * const *in_credentials, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_call_cancel_operation (GDBusProxy *proxy, guint in_opid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_cancel_operation_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_cancel_operation_sync (GDBusProxy *proxy, guint in_opid, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_call_cancel_all (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_cancel_all_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_cancel_all_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+void e_gdbus_cal_call_close (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_gdbus_cal_call_close_finish (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_cal_call_close_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+
+/* D-Bus Methods Completion Helpers */
+#define e_gdbus_cal_complete_open e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_remove e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_refresh e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_get_backend_property e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_set_backend_property e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_get_object e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_get_object_list e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_get_free_busy e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_create_object e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_modify_object e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_remove_object e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_receive_objects e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_send_objects e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_get_attachment_uris e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_discard_alarm e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_get_view e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_get_timezone e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_add_timezone e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_authenticate_user e_gdbus_complete_sync_method_void
+#define e_gdbus_cal_complete_cancel_operation e_gdbus_complete_sync_method_void
+#define e_gdbus_cal_complete_cancel_all e_gdbus_complete_sync_method_void
+#define e_gdbus_cal_complete_close e_gdbus_complete_sync_method_void
+
+void e_gdbus_cal_emit_open_done (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_cal_emit_remove_done (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_cal_emit_refresh_done (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_cal_emit_get_backend_property_done (EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_prop_value);
+void e_gdbus_cal_emit_set_backend_property_done (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_cal_emit_get_object_done (EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_object);
+void e_gdbus_cal_emit_get_object_list_done (EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar * const *out_objects);
+void e_gdbus_cal_emit_get_free_busy_done (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_cal_emit_get_free_busy_data (EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar * const *out_freebusy);
+void e_gdbus_cal_emit_create_object_done (EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_uid);
+void e_gdbus_cal_emit_modify_object_done (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_cal_emit_remove_object_done (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_cal_emit_receive_objects_done (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_cal_emit_send_objects_done (EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar * const *out_calobj_users);
+void e_gdbus_cal_emit_get_attachment_uris_done (EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar * const *out_attachments);
+void e_gdbus_cal_emit_discard_alarm_done (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_cal_emit_get_view_done (EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_view_path);
+void e_gdbus_cal_emit_get_timezone_done (EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_object);
+void e_gdbus_cal_emit_add_timezone_done (EGdbusCal *object, guint arg_opid, const GError *arg_error);
+
+/* D-Bus Signal Emission Helpers */
+void e_gdbus_cal_emit_backend_error (EGdbusCal *object, const gchar *arg_message);
+void e_gdbus_cal_emit_readonly (EGdbusCal *object, gboolean arg_is_readonly);
+void e_gdbus_cal_emit_online (EGdbusCal *object, gint arg_is_online);
+void e_gdbus_cal_emit_auth_required (EGdbusCal *object, const gchar * const *arg_credentials);
+void e_gdbus_cal_emit_opened (EGdbusCal *object, const gchar * const *arg_error);
+void e_gdbus_cal_emit_free_busy_data (EGdbusCal *object, const gchar * const *arg_free_busy);
+
+G_END_DECLS
+
+#endif /* E_GDBUS_CAL_H */
diff --git a/configure.ac b/configure.ac
index 5742537..5c85b29 100644
--- a/configure.ac
+++ b/configure.ac
@@ -55,8 +55,8 @@ EDS_MICRO_VERSION=eds_micro_version
dnl ******************************
dnl D-Bus versioning
dnl ******************************
-ADDRESS_BOOK_DBUS_SERVICE_NAME="org.gnome.evolution.dataserver.AddressBook0"
-CALENDAR_DBUS_SERVICE_NAME="org.gnome.evolution.dataserver.Calendar0"
+ADDRESS_BOOK_DBUS_SERVICE_NAME="org.gnome.evolution.dataserver.AddressBook1"
+CALENDAR_DBUS_SERVICE_NAME="org.gnome.evolution.dataserver.Calendar1"
AC_DEFINE_UNQUOTED(
ADDRESS_BOOK_DBUS_SERVICE_NAME,
@@ -82,19 +82,19 @@ LIBEDATASERVERUI_CURRENT=0
LIBEDATASERVERUI_REVISION=0
LIBEDATASERVERUI_AGE=0
-LIBECAL_CURRENT=10
+LIBECAL_CURRENT=11
LIBECAL_REVISION=2
LIBECAL_AGE=2
-LIBEDATACAL_CURRENT=11
+LIBEDATACAL_CURRENT=12
LIBEDATACAL_REVISION=0
LIBEDATACAL_AGE=0
-LIBEDATABOOK_CURRENT=9
+LIBEDATABOOK_CURRENT=10
LIBEDATABOOK_REVISION=0
LIBEDATABOOK_AGE=0
-LIBEBOOK_CURRENT=13
+LIBEBOOK_CURRENT=14
LIBEBOOK_REVISION=1
LIBEBOOK_AGE=3
@@ -1505,8 +1505,10 @@ libedataserverui/Makefile
libedataserverui/libedataserverui.pc
tests/Makefile
tests/libebook/Makefile
+tests/libebook/client/Makefile
tests/libebook/vcard/Makefile
tests/libecal/Makefile
+tests/libecal/client/Makefile
tests/libedata-cal/Makefile
tests/libedataserver/Makefile
tests/libedataserverui/Makefile
diff --git a/libedataserver/Makefile.am b/libedataserver/Makefile.am
index 4cc32fb..4253781 100644
--- a/libedataserver/Makefile.am
+++ b/libedataserver/Makefile.am
@@ -1,3 +1,7 @@
+# The marshallers
+MARSHAL_GENERATED = e-gdbus-marshallers.c e-gdbus-marshallers.h
+ EVO_MARSHAL_RULE@
+
lib_LTLIBRARIES = libedataserver-1.2.la
libedataserver_1_2_la_CPPFLAGS = \
@@ -14,14 +18,21 @@ libedataserver_1_2_la_CPPFLAGS = \
$(SOUP_CFLAGS)
libedataserver_1_2_la_SOURCES = \
+ $(MARSHAL_GENERATED) \
e-account-list.c \
e-account.c \
e-categories.c \
+ e-client.c \
+ e-client-private.h \
+ e-credentials.c \
e-flag.c \
+ e-gdbus-templates.h \
+ e-gdbus-templates.c \
e-iterator.c \
e-list.c \
e-list-iterator.c \
e-memory.c \
+ e-operation-pool.c \
e-proxy.c \
e-sexp.c \
e-source-group.c \
@@ -52,11 +63,14 @@ libedataserverinclude_HEADERS = \
e-account-list.h \
e-account.h \
e-categories.h \
+ e-client.h \
+ e-credentials.h \
e-flag.h \
e-iterator.h \
e-list.h \
e-list-iterator.h \
e-memory.h \
+ e-operation-pool.h \
e-proxy.h \
e-sexp.h \
e-source-group.h \
@@ -81,7 +95,8 @@ EXTRA_DIST = \
$(pkgconfig_DATA:-$(API_VERSION).pc=.pc.in) \
eds-version.h.in
-CLEANFILES =
+BUILT_SOURCES = $(MARSHAL_GENERATED)
+CLEANFILES = $(BUILT_SOURCES)
DISTCLEANFILES = eds-version.h $(pkgconfig_DATA)
-include $(INTROSPECTION_MAKEFILE)
diff --git a/libedataserver/e-client-private.h b/libedataserver/e-client-private.h
new file mode 100644
index 0000000..71091bf
--- /dev/null
+++ b/libedataserver/e-client-private.h
@@ -0,0 +1,122 @@
+/*
+ * e-client-private.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_CLIENT_PRIVATE_H
+#define E_CLIENT_PRIVATE_H
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "libedataserver/e-credentials.h"
+#include "libedataserver/e-source.h"
+#include "libedataserver/e-source-list.h"
+#include "libedataserver/e-client.h"
+
+G_BEGIN_DECLS
+
+void e_client_set_capabilities (EClient *client, const gchar *capabilities);
+void e_client_set_readonly (EClient *client, gboolean readonly);
+void e_client_set_online (EClient *client, gboolean is_online);
+guint32 e_client_register_op (EClient *client, GCancellable *cancellable);
+void e_client_unregister_op (EClient *client, guint32 opid);
+void e_client_process_authentication (EClient *client, const ECredentials *credentials);
+
+gboolean e_client_emit_authenticate (EClient *client, ECredentials *credentials);
+void e_client_emit_opened (EClient *client, const GError *error);
+void e_client_emit_backend_error (EClient *client, const gchar *error_msg);
+void e_client_emit_backend_died (EClient *client);
+
+ESource * e_client_util_get_system_source (ESourceList *source_list);
+gboolean e_client_util_set_default (ESourceList *source_list, ESource *source);
+ESource * e_client_util_get_source_for_uri(ESourceList *source_list, const gchar *uri);
+
+/* protected functions simplifying sync/async calls */
+GDBusProxy * e_client_get_dbus_proxy (EClient *client);
+void e_client_unwrap_dbus_error (EClient *client, GError *dbus_error, GError **out_error);
+
+void e_client_proxy_return_async_error (EClient *client, const GError *error, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag);
+
+#define e_client_return_async_if_fail(_expr, _client, _callback, _user_data, _source_tag) \
+ G_STMT_START { \
+ if (!G_LIKELY (_expr)) { \
+ GError *error; \
+ \
+ error = g_error_new ( \
+ E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG, \
+ "file %s:%d: %s: assertion `%s' failed", \
+ __FILE__, __LINE__, G_STRFUNC, # _expr); \
+ \
+ g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "%s", error->message); \
+ \
+ e_client_proxy_return_async_error ( \
+ _client, error, _callback, _user_data, _source_tag); \
+ \
+ g_error_free (error); \
+ } \
+ } G_STMT_END
+
+typedef gboolean (* EClientProxyFinishVoidFunc) (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+typedef gboolean (* EClientProxyFinishBooleanFunc) (GDBusProxy *proxy, GAsyncResult *result, gboolean *out_boolean, GError **error);
+typedef gboolean (* EClientProxyFinishStringFunc) (GDBusProxy *proxy, GAsyncResult *result, gchar **out_string, GError **error);
+typedef gboolean (* EClientProxyFinishStrvFunc) (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_strv, GError **error);
+typedef gboolean (* EClientProxyFinishUintFunc) (GDBusProxy *proxy, GAsyncResult *result, guint *out_uint, GError **error);
+
+void e_client_proxy_call_void (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
+void e_client_proxy_call_boolean (EClient *client, gboolean in_boolean, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
+void e_client_proxy_call_string (EClient *client, const gchar *in_string, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, const gchar * in_string, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
+void e_client_proxy_call_strv (EClient *client, const gchar * const *in_strv, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, const gchar * const * in_strv, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
+void e_client_proxy_call_uint (EClient *client, guint in_uint, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint);
+
+gboolean e_client_proxy_call_finish_void (EClient *client, GAsyncResult *result, GError **error, gpointer source_tag);
+gboolean e_client_proxy_call_finish_boolean (EClient *client, GAsyncResult *result, gboolean *out_boolean, GError **error, gpointer source_tag);
+gboolean e_client_proxy_call_finish_string (EClient *client, GAsyncResult *result, gchar **out_string, GError **error, gpointer source_tag);
+gboolean e_client_proxy_call_finish_strv (EClient *client, GAsyncResult *result, gchar ***out_strv, GError **error, gpointer source_tag);
+gboolean e_client_proxy_call_finish_uint (EClient *client, GAsyncResult *result, guint *out_uint, GError **error, gpointer source_tag);
+
+gboolean e_client_proxy_call_sync_void__void (EClient *client, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_void__boolean (EClient *client, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean *out_boolean, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_void__string (EClient *client, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gchar **out_string, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_void__strv (EClient *client, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gchar ***out_strv, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_void__uint (EClient *client, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint *out_uint, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_boolean__void (EClient *client, gboolean in_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_boolean__boolean (EClient *client, gboolean in_boolean, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, gboolean *out_boolean, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_boolean__string (EClient *client, gboolean in_boolean, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, gchar **out_string, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_boolean__strv (EClient *client, gboolean in_boolean, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, gchar ***out_strv, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_boolean__uint (EClient *client, gboolean in_boolean, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, guint *out_uint, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_string__void (EClient *client, const gchar *in_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_string__boolean (EClient *client, const gchar *in_string, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, gboolean *out_boolean, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_string__string (EClient *client, const gchar *in_string, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, gchar **out_string, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_string__strv (EClient *client, const gchar *in_string, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, gchar ***out_strv, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_string__uint (EClient *client, const gchar *in_string, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, guint *out_uint, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_strv__void (EClient *client, const gchar * const *in_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_strv__boolean (EClient *client, const gchar * const *in_strv, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, gboolean *out_boolean, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_strv__string (EClient *client, const gchar * const *in_strv, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, gchar **out_string, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_strv__strv (EClient *client, const gchar * const *in_strv, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, gchar ***out_strv, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_strv__uint (EClient *client, const gchar * const *in_strv, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, guint *out_uint, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_uint__void (EClient *client, guint in_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_uint__boolean (EClient *client, guint in_uint, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, gboolean *out_boolean, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_uint__string (EClient *client, guint in_uint, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, gchar **out_string, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_uint__strv (EClient *client, guint in_uint, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, gchar ***out_strv, GCancellable *cancellable, GError **error));
+gboolean e_client_proxy_call_sync_uint__uint (EClient *client, guint in_uint, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, guint *out_uint, GCancellable *cancellable, GError **error));
+
+G_END_DECLS
+
+#endif /* E_CLIENT_PRIVATE_H */
diff --git a/libedataserver/e-client.c b/libedataserver/e-client.c
new file mode 100644
index 0000000..6d16d47
--- /dev/null
+++ b/libedataserver/e-client.c
@@ -0,0 +1,2489 @@
+/*
+ * e-client.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include "e-gdbus-marshallers.h"
+#include "e-operation-pool.h"
+
+#include "e-client.h"
+#include "e-client-private.h"
+
+struct _EClientPrivate
+{
+ GStaticRecMutex prop_mutex;
+
+ ESource *source;
+ gchar *uri;
+ gboolean online;
+ gboolean readonly;
+ gboolean opened;
+ gboolean capabilities_retrieved;
+ GSList *capabilities;
+
+ GStaticRecMutex ops_mutex;
+ guint32 last_opid;
+ GHashTable *ops; /* opid to GCancellable */
+};
+
+enum {
+ PROP_0,
+ PROP_SOURCE,
+ PROP_CAPABILITIES,
+ PROP_READONLY,
+ PROP_ONLINE,
+ PROP_OPENED
+};
+
+enum {
+ AUTHENTICATE,
+ OPENED,
+ BACKEND_ERROR,
+ BACKEND_DIED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+static EOperationPool *ops_pool = NULL;
+
+G_DEFINE_ABSTRACT_TYPE (EClient, e_client, G_TYPE_OBJECT)
+
+/**
+ * Well-known client backend properties, which are common for each #EClient:
+ * @CLIENT_BACKEND_PROPERTY_OPENED: Is set to "TRUE" or "FALSE" depending
+ * whether the backend is fully opened.
+ * @CLIENT_BACKEND_PROPERTY_OPENING: Is set to "TRUE" or "FALSE" depending
+ * whether the backend is processing its opening phase.
+ * @CLIENT_BACKEND_PROPERTY_ONLINE: Is set to "TRUE" or "FALSE" depending
+ * on the backend's loaded state. See also e_client_is_online().
+ * @CLIENT_BACKEND_PROPERTY_READONLY: Is set to "TRUE" or "FALSE" depending
+ * on the backend's readonly state. See also e_client_is_readonly().
+ * @CLIENT_BACKEND_PROPERTY_CACHE_DIR: Local folder with cached data used
+ * by the backend.
+ * @CLIENT_BACKEND_PROPERTY_CAPABILITIES: Retrieves comma-separated list
+ * of capabilities supported by the backend. Preferred method of retreiving
+ * and working with capabilities is e_client_get_capabilities() and
+ * e_client_check_capability().
+ **/
+
+GQuark
+e_client_error_quark (void)
+{
+ static GQuark q = 0;
+
+ if (q == 0)
+ q = g_quark_from_static_string ("e-client-error-quark");
+
+ return q;
+}
+
+const gchar *
+e_client_error_to_string (EClientError code)
+{
+ switch (code) {
+ case E_CLIENT_ERROR_INVALID_ARG:
+ return C_("ClientError", "Invalid argument");
+ case E_CLIENT_ERROR_BUSY:
+ return C_("ClientError", "Backend is busy");
+ case E_CLIENT_ERROR_SOURCE_NOT_LOADED:
+ return C_("ClientError", "Source not loaded");
+ case E_CLIENT_ERROR_SOURCE_ALREADY_LOADED:
+ return C_("ClientError", "Source already loaded");
+ case E_CLIENT_ERROR_AUTHENTICATION_FAILED:
+ return C_("ClientError", "Authentication failed");
+ case E_CLIENT_ERROR_AUTHENTICATION_REQUIRED:
+ return C_("ClientError", "Authentication required");
+ case E_CLIENT_ERROR_REPOSITORY_OFFLINE:
+ return C_("ClientError", "Repository offline");
+ case E_CLIENT_ERROR_PERMISSION_DENIED:
+ return C_("ClientError", "Permission denied");
+ case E_CLIENT_ERROR_CANCELLED:
+ return C_("ClientError", "Cancelled");
+ case E_CLIENT_ERROR_COULD_NOT_CANCEL:
+ return C_("ClientError", "Could not cancel");
+ case E_CLIENT_ERROR_NOT_SUPPORTED:
+ return C_("ClientError", "Not supported");
+ case E_CLIENT_ERROR_DBUS_ERROR:
+ return C_("ClientError", "D-Bus error");
+ case E_CLIENT_ERROR_OTHER_ERROR:
+ return C_("ClientError", "Other error");
+ }
+
+ return C_("ClientError", "Unknown error");
+}
+
+static void client_set_source (EClient *client, ESource *source);
+static void client_operation_thread (gpointer data, gpointer user_data);
+static void client_handle_authentication (EClient *client, const ECredentials *credentials);
+
+static void
+e_client_init (EClient *client)
+{
+ client->priv = G_TYPE_INSTANCE_GET_PRIVATE (client, E_TYPE_CLIENT, EClientPrivate);
+
+ client->priv->readonly = TRUE;
+
+ g_static_rec_mutex_init (&client->priv->prop_mutex);
+
+ g_static_rec_mutex_init (&client->priv->ops_mutex);
+ client->priv->last_opid = 0;
+ client->priv->ops = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
+}
+
+static void
+client_dispose (GObject *object)
+{
+ EClient *client;
+
+ client = E_CLIENT (object);
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (client->priv != NULL);
+
+ e_client_cancel_all (client);
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_client_parent_class)->dispose (object);
+}
+
+static void
+client_finalize (GObject *object)
+{
+ EClient *client;
+ EClientPrivate *priv;
+
+ client = E_CLIENT (object);
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (client->priv != NULL);
+
+ priv = client->priv;
+
+ g_static_rec_mutex_lock (&priv->prop_mutex);
+
+ if (priv->source) {
+ g_object_unref (priv->source);
+ priv->source = NULL;
+ }
+
+ if (priv->uri) {
+ g_free (priv->uri);
+ priv->uri = NULL;
+ }
+
+ if (priv->capabilities) {
+ g_slist_foreach (priv->capabilities, (GFunc) g_free, NULL);
+ g_slist_free (priv->capabilities);
+ priv->capabilities = NULL;
+ }
+
+ if (priv->ops) {
+ g_hash_table_destroy (priv->ops);
+ priv->ops = NULL;
+ }
+
+ g_static_rec_mutex_unlock (&priv->prop_mutex);
+ g_static_rec_mutex_free (&priv->prop_mutex);
+ g_static_rec_mutex_free (&priv->ops_mutex);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_client_parent_class)->finalize (object);
+}
+
+static void
+client_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SOURCE:
+ client_set_source (E_CLIENT (object), g_value_get_object (value));
+ return;
+
+ case PROP_ONLINE:
+ e_client_set_online (E_CLIENT (object), g_value_get_boolean (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+client_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SOURCE:
+ g_value_set_object (value, e_client_get_source (E_CLIENT (object)));
+ return;
+
+ case PROP_CAPABILITIES:
+ g_value_set_pointer (value, (gpointer) e_client_get_capabilities (E_CLIENT (object)));
+ return;
+
+ case PROP_READONLY:
+ g_value_set_boolean (value, e_client_is_readonly (E_CLIENT (object)));
+ return;
+
+ case PROP_ONLINE:
+ g_value_set_boolean (value, e_client_is_online (E_CLIENT (object)));
+ return;
+
+ case PROP_OPENED:
+ g_value_set_boolean (value, e_client_is_opened (E_CLIENT (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_client_class_init (EClientClass *klass)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (klass, sizeof (EClientPrivate));
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->set_property = client_set_property;
+ object_class->get_property = client_get_property;
+ object_class->dispose = client_dispose;
+ object_class->finalize = client_finalize;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SOURCE,
+ g_param_spec_object (
+ "source",
+ NULL,
+ NULL,
+ E_TYPE_SOURCE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CAPABILITIES,
+ g_param_spec_pointer (
+ "capabilities",
+ NULL,
+ NULL,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_READONLY,
+ g_param_spec_boolean (
+ "readonly",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ONLINE,
+ g_param_spec_boolean (
+ "online",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_OPENED,
+ g_param_spec_boolean (
+ "opened",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READABLE));
+
+ signals[AUTHENTICATE] = g_signal_new (
+ "authenticate",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EClientClass, authenticate),
+ NULL, NULL,
+ e_gdbus_marshallers_BOOLEAN__POINTER,
+ G_TYPE_BOOLEAN, 1,
+ G_TYPE_POINTER);
+
+ signals[OPENED] = g_signal_new (
+ "opened",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EClientClass, opened),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1,
+ G_TYPE_ERROR);
+
+
+ signals[BACKEND_ERROR] = g_signal_new (
+ "backend-error",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EClientClass, backend_error),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ signals[BACKEND_DIED] = g_signal_new (
+ "backend-died",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EClientClass, backend_died),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ if (!ops_pool)
+ ops_pool = e_operation_pool_new (2, client_operation_thread, NULL);
+}
+
+typedef enum {
+ E_CLIENT_OP_AUTHENTICATE
+} EClientOp;
+
+typedef struct _EClientOpData {
+ EClient *client;
+ EClientOp op;
+
+ union {
+ ECredentials *credentials;
+ } d;
+} EClientOpData;
+
+static void
+client_operation_thread (gpointer data, gpointer user_data)
+{
+ EClientOpData *op_data = data;
+
+ g_return_if_fail (op_data != NULL);
+
+ switch (op_data->op) {
+ case E_CLIENT_OP_AUTHENTICATE:
+ if (e_client_emit_authenticate (op_data->client, op_data->d.credentials)) {
+ client_handle_authentication (op_data->client, op_data->d.credentials);
+ } else {
+ GError *error;
+
+ error = g_error_new_literal (E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_REQUIRED, e_client_error_to_string (E_CLIENT_ERROR_AUTHENTICATION_REQUIRED));
+ e_client_emit_opened (op_data->client, error);
+ g_error_free (error);
+ }
+ e_credentials_free (op_data->d.credentials);
+ break;
+ }
+
+ g_object_unref (op_data->client);
+ g_free (op_data);
+}
+
+static void
+client_set_source (EClient *client, ESource *source)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+ g_return_if_fail (source != NULL);
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ g_object_ref (source);
+
+ if (client->priv->source)
+ g_object_unref (client->priv->source);
+
+ client->priv->source = source;
+}
+
+/**
+ * e_client_get_source:
+ * @client: an #EClient
+ *
+ * Get the #ESource that this client has assigned.
+ *
+ * Returns: The source.
+ *
+ * Since: 3.2
+ **/
+ESource *
+e_client_get_source (EClient *client)
+{
+ g_return_val_if_fail (client != NULL, NULL);
+ g_return_val_if_fail (E_IS_CLIENT (client), NULL);
+ g_return_val_if_fail (client->priv != NULL, NULL);
+
+ return client->priv->source;
+}
+
+/**
+ * e_client_get_uri:
+ * @client: an #EClient
+ *
+ * Get the URI that this client has assigned. This string should not be freed.
+ *
+ * Returns: The URI.
+ *
+ * Since: 3.2
+ **/
+const gchar *
+e_client_get_uri (EClient *client)
+{
+ g_return_val_if_fail (client != NULL, NULL);
+ g_return_val_if_fail (E_IS_CLIENT (client), NULL);
+ g_return_val_if_fail (client->priv != NULL, NULL);
+
+ if (!client->priv->uri)
+ client->priv->uri = e_source_get_uri (e_client_get_source (client));
+
+ return client->priv->uri;
+}
+
+static void
+client_ensure_capabilities (EClient *client)
+{
+ EClientClass *klass;
+ gchar *capabilities;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_if_fail (klass != NULL);
+ g_return_if_fail (klass->retrieve_capabilities != NULL);
+
+ if (client->priv->capabilities_retrieved || client->priv->capabilities)
+ return;
+
+ g_static_rec_mutex_lock (&client->priv->prop_mutex);
+
+ capabilities = klass->retrieve_capabilities (client);
+
+ e_client_set_capabilities (client, capabilities);
+
+ g_free (capabilities);
+
+ client->priv->capabilities_retrieved = TRUE;
+
+ g_static_rec_mutex_unlock (&client->priv->prop_mutex);
+}
+
+/**
+ * e_client_get_capabilities:
+ * @client: an #EClient
+ *
+ * Get list of strings with capabilities advertised by a backend.
+ * This list, together with inner strings, is owned by the @client.
+ * To check for individual capabilities use e_client_check_capability().
+ *
+ * Returns: #GSList of const strings of capabilities
+ *
+ * Since: 3.2
+ **/
+const GSList *
+e_client_get_capabilities (EClient *client)
+{
+ g_return_val_if_fail (client != NULL, NULL);
+ g_return_val_if_fail (E_IS_CLIENT (client), NULL);
+ g_return_val_if_fail (client->priv != NULL, NULL);
+
+ client_ensure_capabilities (client);
+
+ return client->priv->capabilities;
+}
+
+/**
+ * e_client_check_capability:
+ * @client: an #EClient
+ * @capability: a capability
+ *
+ * Check if backend supports particular capability.
+ * To get all capabilities use e_client_get_capabilities().
+ *
+ * Returns: #GSList of const strings of capabilities
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_check_capability (EClient *client, const gchar *capability)
+{
+ GSList *iter;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (capability, FALSE);
+
+ g_static_rec_mutex_lock (&client->priv->prop_mutex);
+
+ client_ensure_capabilities (client);
+
+ for (iter = client->priv->capabilities; iter; iter = g_slist_next (iter)) {
+ const gchar *cap = iter->data;
+
+ if (cap && g_ascii_strcasecmp (cap, capability) == 0) {
+ g_static_rec_mutex_unlock (&client->priv->prop_mutex);
+ return TRUE;
+ }
+ }
+
+ g_static_rec_mutex_unlock (&client->priv->prop_mutex);
+
+ return FALSE;
+}
+
+/**
+ * e_client_check_refresh_supported:
+ * @client: A client.
+ *
+ * Checks whether a client supports explicit refreshing (see e_client_refresh()).
+ *
+ * Returns: TRUE if the client supports refreshing, FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_check_refresh_supported (EClient *client)
+{
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+
+ return e_client_check_capability (client, "refresh-supported");
+}
+
+/* capabilities - comma-separated list of capabilities; can be NULL to unset */
+void
+e_client_set_capabilities (EClient *client, const gchar *capabilities)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+
+ g_static_rec_mutex_lock (&client->priv->prop_mutex);
+
+ if (!capabilities)
+ client->priv->capabilities_retrieved = FALSE;
+
+ g_slist_foreach (client->priv->capabilities, (GFunc) g_free, NULL);
+ g_slist_free (client->priv->capabilities);
+ client->priv->capabilities = e_client_util_parse_comma_strings (capabilities);
+
+ g_static_rec_mutex_unlock (&client->priv->prop_mutex);
+
+ g_object_notify (G_OBJECT (client), "capabilities");
+}
+
+/**
+ * e_client_is_readonly:
+ * @client: an #EClient
+ *
+ * Check if this @client is read-only.
+ *
+ * Returns: %TRUE if this @client is read-only, otherwise %FALSE.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_is_readonly (EClient *client)
+{
+ g_return_val_if_fail (client != NULL, TRUE);
+ g_return_val_if_fail (E_IS_CLIENT (client), TRUE);
+ g_return_val_if_fail (client->priv != NULL, TRUE);
+
+ return client->priv->readonly;
+}
+
+void
+e_client_set_readonly (EClient *client, gboolean readonly)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+
+ g_static_rec_mutex_lock (&client->priv->prop_mutex);
+ if ((readonly ? 1 : 0) == (client->priv->readonly ? 1 : 0)) {
+ g_static_rec_mutex_unlock (&client->priv->prop_mutex);
+ return;
+ }
+
+ client->priv->readonly = readonly;
+
+ g_static_rec_mutex_unlock (&client->priv->prop_mutex);
+
+ g_object_notify (G_OBJECT (client), "readonly");
+}
+
+/**
+ * e_client_is_online:
+ * @client: an #EClient
+ *
+ * Check if this @client is connected.
+ *
+ * Returns: %TRUE if this @client is connected, otherwise %FALSE.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_is_online (EClient *client)
+{
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+
+ return client->priv->online;
+}
+
+void
+e_client_set_online (EClient *client, gboolean is_online)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+
+ /* newly connected/disconnected => make sure capabilities will be correct */
+ e_client_set_capabilities (client, NULL);
+
+ g_static_rec_mutex_lock (&client->priv->prop_mutex);
+ if ((is_online ? 1: 0) == (client->priv->online ? 1 : 0)) {
+ g_static_rec_mutex_unlock (&client->priv->prop_mutex);
+ return;
+ }
+
+ client->priv->online = is_online;
+
+ g_static_rec_mutex_unlock (&client->priv->prop_mutex);
+
+ g_object_notify (G_OBJECT (client), "online");
+}
+
+/**
+ * e_client_is_opened:
+ * @client: an #EClient
+ *
+ * Check if this @client is fully opened. This includes
+ * everything from e_client_open() call up to the authentication,
+ * if required by a backend. Client cannot do any other operation
+ * during the opening phase except of authenticate or cancel it.
+ * Every other operation results in an %E_CLIENT_ERROR_BUSY error.
+ *
+ * Returns: %TRUE if this @client is fully opened, otherwise %FALSE.
+ *
+ * Since: 3.2.
+ **/
+gboolean
+e_client_is_opened (EClient *client)
+{
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+
+ return client->priv->opened;
+}
+
+/*
+ * client_cancel_op:
+ * @client: an #EClient
+ * @opid: asynchronous operation ID
+ *
+ * Cancels particular asynchronous operation. The @opid is returned from
+ * an e_client_register_op(). The function does nothing if the asynchronous
+ * operation doesn't exist any more.
+ *
+ * Since: 3.2
+ */
+static void
+client_cancel_op (EClient *client, guint32 opid)
+{
+ GCancellable *cancellable;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+ g_return_if_fail (client->priv->ops != NULL);
+
+ g_static_rec_mutex_lock (&client->priv->ops_mutex);
+
+ cancellable = g_hash_table_lookup (client->priv->ops, GINT_TO_POINTER (opid));
+ if (cancellable)
+ g_cancellable_cancel (cancellable);
+
+ g_static_rec_mutex_unlock (&client->priv->ops_mutex);
+}
+
+static void
+gather_opids_cb (gpointer opid, gpointer cancellable, gpointer ids_list)
+{
+ GSList **ids = ids_list;
+
+ g_return_if_fail (ids_list != NULL);
+
+ *ids = g_slist_prepend (*ids, opid);
+}
+
+static void
+cancel_op_cb (gpointer opid, gpointer client)
+{
+ client_cancel_op (client, GPOINTER_TO_INT (opid));
+}
+
+/**
+ * e_client_cancel_all:
+ * @client: an #EClient
+ *
+ * Cancels all pending operations started on @client.
+ *
+ * Since: 3.2
+ **/
+void
+e_client_cancel_all (EClient *client)
+{
+ GSList *opids = NULL;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+ g_return_if_fail (client->priv->ops != NULL);
+
+ g_static_rec_mutex_lock (&client->priv->ops_mutex);
+
+ g_hash_table_foreach (client->priv->ops, gather_opids_cb, &opids);
+
+ g_slist_foreach (opids, cancel_op_cb, client);
+ g_slist_free (opids);
+
+ g_static_rec_mutex_unlock (&client->priv->ops_mutex);
+}
+
+guint32
+e_client_register_op (EClient *client, GCancellable *cancellable)
+{
+ guint32 opid;
+
+ g_return_val_if_fail (client != NULL, 0);
+ g_return_val_if_fail (E_IS_CLIENT (client), 0);
+ g_return_val_if_fail (client->priv != NULL, 0);
+ g_return_val_if_fail (client->priv->ops != NULL, 0);
+ g_return_val_if_fail (cancellable != NULL, 0);
+
+ g_static_rec_mutex_lock (&client->priv->ops_mutex);
+
+ client->priv->last_opid++;
+ if (!client->priv->last_opid)
+ client->priv->last_opid++;
+
+ while (g_hash_table_lookup (client->priv->ops, GINT_TO_POINTER (client->priv->last_opid)))
+ client->priv->last_opid++;
+
+ g_return_val_if_fail (client->priv->last_opid != 0, 0);
+
+ opid = client->priv->last_opid;
+ g_hash_table_insert (client->priv->ops, GINT_TO_POINTER (opid), g_object_ref (cancellable));
+
+ g_static_rec_mutex_unlock (&client->priv->ops_mutex);
+
+ return opid;
+}
+
+void
+e_client_unregister_op (EClient *client, guint32 opid)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+ g_return_if_fail (client->priv->ops != NULL);
+
+ g_static_rec_mutex_lock (&client->priv->ops_mutex);
+ g_hash_table_remove (client->priv->ops, GINT_TO_POINTER (opid));
+ g_static_rec_mutex_unlock (&client->priv->ops_mutex);
+}
+
+static void
+client_handle_authentication (EClient *client, const ECredentials *credentials)
+{
+ EClientClass *klass;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (credentials != NULL);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_if_fail (klass != NULL);
+ g_return_if_fail (klass->handle_authentication != NULL);
+
+ return klass->handle_authentication (client, credentials);
+}
+
+/* Processes authentication request in a new thread. Usual steps are:
+ a) backend sends an auth-required signal
+ b) EClient implementation calls this function
+ c) a new thread is run which emits authenticate signal by e_client_emit_authenticate()
+ d) if anyone responds (returns true), the EClient::handle_authentication
+ is called from the same extra thread with new credentials
+ e) EClient implementation passes results to backend in the EClient::handle_authentication
+*/
+void
+e_client_process_authentication (EClient *client, const ECredentials *credentials)
+{
+ EClientOpData *op_data;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+
+ op_data = g_new0 (EClientOpData, 1);
+ op_data->client = g_object_ref (client);
+ op_data->op = E_CLIENT_OP_AUTHENTICATE;
+ op_data->d.credentials = credentials ? e_credentials_new_clone (credentials) : e_credentials_new ();
+
+ e_operation_pool_push (ops_pool, op_data);
+}
+
+gboolean
+e_client_emit_authenticate (EClient *client, ECredentials *credentials)
+{
+ gboolean handled = FALSE;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (credentials != NULL, FALSE);
+
+ g_signal_emit (client, signals[AUTHENTICATE], 0, credentials, &handled);
+
+ return handled;
+}
+
+void
+e_client_emit_opened (EClient *client, const GError *dbus_error)
+{
+ GError *local_error = NULL;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+
+ client->priv->opened = dbus_error == NULL;
+
+ if (dbus_error) {
+ local_error = g_error_copy (dbus_error);
+ e_client_unwrap_dbus_error (client, local_error, &local_error);
+ }
+
+ g_signal_emit (client, signals[OPENED], 0, local_error);
+
+ if (local_error)
+ g_error_free (local_error);
+}
+
+void
+e_client_emit_backend_error (EClient *client, const gchar *error_msg)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (error_msg != NULL);
+
+ g_signal_emit (client, signals[BACKEND_ERROR], 0, error_msg);
+}
+
+void
+e_client_emit_backend_died (EClient *client)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+
+ g_signal_emit (client, signals[BACKEND_DIED], 0);
+}
+
+/**
+ * e_client_get_backend_property:
+ * @client: an #EClient
+ * @prop_name: property name, whose value to retrieve; cannot be %NULL
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Queries @client's backend for a property of name @prop_name.
+ * The call is finished by e_client_get_backend_property_finish()
+ * from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_client_get_backend_property (EClient *client, const gchar *prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ EClientClass *klass;
+
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+ g_return_if_fail (prop_name != NULL);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_if_fail (klass != NULL);
+ g_return_if_fail (klass->get_backend_property != NULL);
+
+ klass->get_backend_property (client, prop_name, cancellable, callback, user_data);
+}
+
+/**
+ * e_client_get_backend_property_finish:
+ * @client: an #EClient
+ * @result: a #GAsyncResult
+ * @prop_value: (out): Retrieved backend property value; cannot be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_client_get_backend_property().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_get_backend_property_finish (EClient *client, GAsyncResult *result, gchar **prop_value, GError **error)
+{
+ EClientClass *klass;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (prop_value != NULL, FALSE);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->get_backend_property_finish != NULL, FALSE);
+
+ return klass->get_backend_property_finish (client, result, prop_value, error);
+}
+
+/**
+ * e_client_get_backend_property_sync:
+ * @client: an #EClient
+ * @prop_name: property name, whose value to retrieve; cannot be %NULL
+ * @prop_value: (out): Retrieved backend property value; cannot be %NULL
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Queries @client's backend for a property of name @prop_name.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_get_backend_property_sync (EClient *client, const gchar *prop_name, gchar **prop_value, GCancellable *cancellable, GError **error)
+{
+ EClientClass *klass;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (prop_name != NULL, FALSE);
+ g_return_val_if_fail (prop_value != NULL, FALSE);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->get_backend_property_sync != NULL, FALSE);
+
+ return klass->get_backend_property_sync (client, prop_name, prop_value, cancellable, error);
+}
+
+/**
+ * e_client_set_backend_property:
+ * @client: an #EClient
+ * @prop_name: property name, whose value to change; cannot be %NULL
+ * @prop_value: property value, to set; cannot be %NULL
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Sets @client's backend property of name @prop_name
+ * to value @prop_value. The call is finished
+ * by e_client_set_backend_property_finish() from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_client_set_backend_property (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ EClientClass *klass;
+
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+ g_return_if_fail (prop_name != NULL);
+ g_return_if_fail (prop_value != NULL);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_if_fail (klass != NULL);
+ g_return_if_fail (klass->set_backend_property != NULL);
+
+ klass->set_backend_property (client, prop_name, prop_value, cancellable, callback, user_data);
+}
+
+/**
+ * e_client_set_backend_property_finish:
+ * @client: an #EClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_client_set_backend_property().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_set_backend_property_finish (EClient *client, GAsyncResult *result, GError **error)
+{
+ EClientClass *klass;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_backend_property_finish != NULL, FALSE);
+
+ return klass->set_backend_property_finish (client, result, error);
+}
+
+/**
+ * e_client_set_backend_property_sync:
+ * @client: an #EClient
+ * @prop_name: property name, whose value to change; cannot be %NULL
+ * @prop_value: property value, to set; cannot be %NULL
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Sets @client's backend property of name @prop_name
+ * to value @prop_value.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_set_backend_property_sync (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GError **error)
+{
+ EClientClass *klass;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (prop_name != NULL, FALSE);
+ g_return_val_if_fail (prop_value != NULL, FALSE);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->set_backend_property_sync != NULL, FALSE);
+
+ return klass->set_backend_property_sync (client, prop_name, prop_value, cancellable, error);
+}
+
+/**
+ * e_client_open:
+ * @client: an #EClient
+ * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Opens the @client, making it ready for queries and other operations.
+ * The call is finished by e_client_open_finish() from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_client_open (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ EClientClass *klass;
+
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_if_fail (klass != NULL);
+ g_return_if_fail (klass->open != NULL);
+
+ klass->open (client, only_if_exists, cancellable, callback, user_data);
+}
+
+/**
+ * e_client_open_finish:
+ * @client: an #EClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_client_open().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_open_finish (EClient *client, GAsyncResult *result, GError **error)
+{
+ EClientClass *klass;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->open_finish != NULL, FALSE);
+
+ return klass->open_finish (client, result, error);
+}
+
+/**
+ * e_client_open_sync:
+ * @client: an #EClient
+ * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Opens the @client, making it ready for queries and other operations.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_open_sync (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error)
+{
+ EClientClass *klass;
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->open_sync != NULL, FALSE);
+
+ return klass->open_sync (client, only_if_exists, cancellable, error);
+}
+
+/**
+ * e_client_remove:
+ * @client: an #EClient
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Removes the backing data for this #EClient. For example, with the file backend this
+ * deletes the database file. You cannot get it back!
+ * The call is finished by e_client_remove_finish() from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_client_remove (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ EClientClass *klass;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+ g_return_if_fail (callback != NULL);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_if_fail (klass != NULL);
+ g_return_if_fail (klass->remove != NULL);
+
+ klass->remove (client, cancellable, callback, user_data);
+}
+
+/**
+ * e_client_remove_finish:
+ * @client: an #EClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_client_remove().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_remove_finish (EClient *client, GAsyncResult *result, GError **error)
+{
+ EClientClass *klass;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->remove_finish != NULL, FALSE);
+
+ return klass->remove_finish (client, result, error);
+}
+
+/**
+ * e_client_remove_sync:
+ * @client: an #EClient
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Removes the backing data for this #EClient. For example, with the file backend this
+ * deletes the database file. You cannot get it back!
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_remove_sync (EClient *client, GCancellable *cancellable, GError **error)
+{
+ EClientClass *klass;
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->remove_sync != NULL, FALSE);
+
+ return klass->remove_sync (client, cancellable, error);
+}
+
+/**
+ * e_client_refresh:
+ * @client: an #EClient
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Initiates refresh on the @client. Finishing the method doesn't mean
+ * that the refresh is done, backend only notifies whether it started
+ * refreshing or not. Use e_client_check_refresh_supported() to check
+ * whether the backend supports this method.
+ * The call is finished by e_client_refresh_finish() from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_client_refresh (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ EClientClass *klass;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+ g_return_if_fail (callback != NULL);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_if_fail (klass != NULL);
+ g_return_if_fail (klass->refresh != NULL);
+
+ klass->refresh (client, cancellable, callback, user_data);
+}
+
+/**
+ * e_client_refresh_finish:
+ * @client: an #EClient
+ * @result: a #GAsyncResult
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_client_refresh().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_refresh_finish (EClient *client, GAsyncResult *result, GError **error)
+{
+ EClientClass *klass;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->refresh_finish != NULL, FALSE);
+
+ return klass->refresh_finish (client, result, error);
+}
+
+/**
+ * e_client_refresh_sync:
+ * @client: an #EClient
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Initiates refresh on the @client. Finishing the method doesn't mean
+ * that the refresh is done, backend only notifies whether it started
+ * refreshing or not. Use e_client_check_refresh_supported() to check
+ * whether the backend supports this method.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_refresh_sync (EClient *client, GCancellable *cancellable, GError **error)
+{
+ EClientClass *klass;
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->refresh_sync != NULL, FALSE);
+
+ return klass->refresh_sync (client, cancellable, error);
+}
+
+/**
+ * e_client_util_slist_to_strv:
+ * @strings: a #GSList of strings (const gchar *)
+ *
+ * Convert list of strings into NULL-terminates array of strings.
+ *
+ * Returns: Newly allocated NULL-terminated array of strings.
+ * Returned pointer should be freed with g_strfreev().
+ *
+ * Note: Pair function for this is e_client_util_strv_to_slist().
+ *
+ * Sice: 3.2
+ **/
+gchar **
+e_client_util_slist_to_strv (const GSList *strings)
+{
+ const GSList *iter;
+ GPtrArray *array;
+
+ array = g_ptr_array_sized_new (g_slist_length ((GSList *) strings) + 1);
+
+ for (iter = strings; iter; iter = iter->next) {
+ const gchar *str = iter->data;
+
+ if (str)
+ g_ptr_array_add (array, g_strdup (str));
+ }
+
+ /* NULL-terminated */
+ g_ptr_array_add (array, NULL);
+
+ return (gchar **) g_ptr_array_free (array, FALSE);
+}
+
+/**
+ * e_client_util_strv_to_slist:
+ * @strv: a NULL-terminated array of strings (const gchar *)
+ *
+ * Convert NULL-terminated array of strings to a list of strings.
+ *
+ * Returns: Newly allocated #GSList of newly allocated strings.
+ * Returned pointer should be freed with e_client_util_free_string_slist().
+ *
+ * Note: Pair function for this is e_client_util_slist_to_strv().
+ *
+ * Sice: 3.2
+ **/
+GSList *
+e_client_util_strv_to_slist (const gchar * const *strv)
+{
+ GSList *slist = NULL;
+ gint ii;
+
+ if (!strv)
+ return NULL;
+
+ for (ii = 0; strv[ii]; ii++) {
+ slist = g_slist_prepend (slist, g_strdup (strv[ii]));
+ }
+
+ return g_slist_reverse (slist);
+}
+
+/**
+ * e_client_util_copy_string_slist:
+ * @copy_to: Where to copy; can be NULL
+ * @strings: GSList of strings to be copied
+ *
+ * Copies GSList of strings at the end of @copy_to.
+ *
+ * Returns: New head of @copy_to.
+ * Returned pointer can be freed with e_client_util_free_string_slist().
+ *
+ * Since: 3.2
+ **/
+GSList *
+e_client_util_copy_string_slist (GSList *copy_to, const GSList *strings)
+{
+ GSList *res = copy_to;
+ const GSList *iter;
+
+ for (iter = strings; iter; iter = iter->next) {
+ res = g_slist_append (res, g_strdup (iter->data));
+ }
+
+ return res;
+}
+
+/**
+ * e_client_util_copy_object_slist:
+ * @copy_to: Where to copy; can be NULL
+ * @objects: GSList of GObject-s to be copied
+ *
+ * Copies GSList of GObject-s at the end of @copy_to.
+ *
+ * Returns: New head of @copy_to.
+ * Returned pointer can be freed with e_client_util_free_object_slist().
+ *
+ * Since: 3.2
+ **/
+GSList *
+e_client_util_copy_object_slist (GSList *copy_to, const GSList *objects)
+{
+ GSList *res = copy_to;
+ const GSList *iter;
+
+ for (iter = objects; iter; iter = iter->next) {
+ res = g_slist_append (res, g_object_ref (iter->data));
+ }
+
+ return res;
+}
+
+/**
+ * e_client_util_free_string_slist:
+ * @strings: a #GSList of strings (gchar *)
+ *
+ * Frees memory previously allocated by e_client_util_strv_to_slist().
+ *
+ * Sice: 3.2
+ **/
+void
+e_client_util_free_string_slist (GSList *strings)
+{
+ if (!strings)
+ return;
+
+ g_slist_foreach (strings, (GFunc) g_free, NULL);
+ g_slist_free (strings);
+}
+
+/**
+ * e_client_util_free_object_slist:
+ * @objects: a #GSList of #GObject-s
+ *
+ * Calls g_object_unref() on each member of @objects and then frees
+ * also @objects itself.
+ *
+ * Sice: 3.2
+ **/
+void
+e_client_util_free_object_slist (GSList *objects)
+{
+ if (!objects)
+ return;
+
+ g_slist_foreach (objects, (GFunc) g_object_unref, NULL);
+ g_slist_free (objects);
+}
+
+/**
+ * e_client_util_parse_comma_strings:
+ * @strings: string of comma-separated values
+ *
+ * Parses comma-separated list of values into #GSList.
+ *
+ * Returns: Newly allocated #GSList of newly allocated strings
+ * corresponding to values parsed from @strings.
+ * Free returned pointer with e_client_util_free_string_slist().
+ *
+ * Since: 3.2
+ **/
+GSList *
+e_client_util_parse_comma_strings (const gchar *strings)
+{
+ GSList *strs_slist = NULL;
+ gchar **strs_strv = NULL;
+ gint ii;
+
+ if (!strings || !*strings)
+ return NULL;
+
+ strs_strv = g_strsplit (strings, ",", -1);
+ g_return_val_if_fail (strs_strv != NULL, NULL);
+
+ for (ii = 0; strs_strv && strs_strv[ii]; ii++) {
+ gchar *str = g_strstrip (strs_strv[ii]);
+
+ if (str && *str)
+ strs_slist = g_slist_prepend (strs_slist, g_strdup (str));
+ }
+
+ g_strfreev (strs_strv);
+
+ return g_slist_reverse (strs_slist);
+}
+
+/* for each known source calls check_func, which should return TRUE if the required
+ source have been found. Function returns NULL or the source on which was returned
+ TRUE by the check_func. Non-NULL pointer should be unreffed by g_object_unref. */
+static ESource *
+search_known_sources (ESourceList *sources, gboolean (*check_func)(ESource *source, gpointer user_data), gpointer user_data)
+{
+ ESource *res = NULL;
+ GSList *g;
+
+ g_return_val_if_fail (check_func != NULL, NULL);
+ g_return_val_if_fail (sources != NULL, NULL);
+
+ for (g = e_source_list_peek_groups (sources); g; g = g->next) {
+ ESourceGroup *group = E_SOURCE_GROUP (g->data);
+ GSList *s;
+
+ for (s = e_source_group_peek_sources (group); s; s = s->next) {
+ ESource *source = E_SOURCE (s->data);
+
+ if (check_func (source, user_data)) {
+ res = g_object_ref (source);
+ break;
+ }
+ }
+
+ if (res)
+ break;
+ }
+
+ return res;
+}
+
+static gboolean
+check_uri (ESource *source, gpointer uri)
+{
+ const gchar *suri;
+ gchar *suri2;
+ gboolean res;
+
+ g_return_val_if_fail (source != NULL, FALSE);
+ g_return_val_if_fail (uri != NULL, FALSE);
+
+ suri = e_source_peek_absolute_uri (source);
+
+ if (suri)
+ return g_ascii_strcasecmp (suri, uri) == 0;
+
+ suri2 = e_source_get_uri (source);
+ res = suri2 && g_ascii_strcasecmp (suri2, uri) == 0;
+ g_free (suri2);
+
+ return res;
+}
+
+struct check_system_data
+{
+ const gchar *uri;
+ ESource *uri_source;
+};
+
+static gboolean
+check_system (ESource *source, gpointer data)
+{
+ struct check_system_data *csd = data;
+
+ g_return_val_if_fail (source != NULL, FALSE);
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ if (e_source_get_property (source, "system")) {
+ return TRUE;
+ }
+
+ if (check_uri (source, (gpointer) csd->uri)) {
+ if (csd->uri_source)
+ g_object_unref (csd->uri_source);
+ csd->uri_source = g_object_ref (source);
+ }
+
+ return FALSE;
+}
+
+ESource *
+e_client_util_get_system_source (ESourceList *source_list)
+{
+ struct check_system_data csd;
+ ESource *system_source = NULL;
+
+ g_return_val_if_fail (source_list != NULL, NULL);
+ g_return_val_if_fail (E_IS_SOURCE_LIST (source_list), NULL);
+
+ csd.uri = "local:system";
+ csd.uri_source = NULL;
+
+ system_source = search_known_sources (source_list, check_system, &csd);
+
+ if (!system_source) {
+ system_source = csd.uri_source;
+ csd.uri_source = NULL;
+ }
+
+ if (csd.uri_source)
+ g_object_unref (csd.uri_source);
+
+ if (!system_source) {
+ /* create a new one, if not found */
+ ESourceGroup *on_this_computer;
+
+ on_this_computer = e_source_list_ensure_group (source_list,
+ _("On This Computer"),
+ "local:", TRUE);
+ if (on_this_computer) {
+ GError *error = NULL;
+
+ system_source = e_source_new (_("Personal"), "system");
+ e_source_set_color_spec (system_source, "#BECEDD");
+ e_source_group_add_source (on_this_computer, system_source, -1);
+
+ if (!e_source_list_sync (source_list, &error))
+ g_warning ("Cannot add system source to GConf: %s", error ? error->message : "Unknown error");
+
+ if (error)
+ g_error_free (error);
+ }
+ }
+
+ return system_source;
+}
+
+gboolean
+e_client_util_set_default (ESourceList *source_list, ESource *source)
+{
+ const gchar *uid;
+ GSList *g;
+
+ g_return_val_if_fail (source_list != NULL, FALSE);
+ g_return_val_if_fail (E_IS_SOURCE_LIST (source_list), FALSE);
+ g_return_val_if_fail (source != NULL, FALSE);
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+ uid = e_source_peek_uid (source);
+
+ /* make sure the source is actually in the ESourceList. If
+ it's not we don't bother adding it, just return an error */
+ source = e_source_list_peek_source_by_uid (source_list, uid);
+ if (!source)
+ return FALSE;
+
+ /* loop over all the sources clearing out any "default"
+ properties we find */
+ for (g = e_source_list_peek_groups (source_list); g; g = g->next) {
+ GSList *s;
+ for (s = e_source_group_peek_sources (E_SOURCE_GROUP (g->data));
+ s; s = s->next) {
+ e_source_set_property (E_SOURCE (s->data), "default", NULL);
+ }
+ }
+
+ /* set the "default" property on the source */
+ e_source_set_property (source, "default", "true");
+
+ return TRUE;
+}
+
+ESource *
+e_client_util_get_source_for_uri (ESourceList *source_list, const gchar *uri)
+{
+ ESource *source;
+
+ g_return_val_if_fail (source_list != NULL, NULL);
+ g_return_val_if_fail (E_IS_SOURCE_LIST (source_list), NULL);
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ source = search_known_sources (source_list, check_uri, (gpointer) uri);
+ if (!source)
+ source = e_source_new_with_absolute_uri ("", uri);
+
+ return source;
+}
+
+GDBusProxy *
+e_client_get_dbus_proxy (EClient *client)
+{
+ EClientClass *klass;
+
+ g_return_val_if_fail (client != NULL, NULL);
+ g_return_val_if_fail (E_IS_CLIENT (client), NULL);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->get_dbus_proxy != NULL, NULL);
+
+ return klass->get_dbus_proxy (client);
+}
+
+/**
+ * Unwraps D-Bus error to local error. dbus_error is automatically freed.
+ * dbus_erorr and out_error can point to the same variable.
+ **/
+void
+e_client_unwrap_dbus_error (EClient *client, GError *dbus_error, GError **out_error)
+{
+ EClientClass *klass;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_if_fail (klass != NULL);
+ g_return_if_fail (klass->unwrap_dbus_error != NULL);
+
+ if (!dbus_error || !out_error) {
+ if (dbus_error)
+ g_error_free (dbus_error);
+ } else {
+ klass->unwrap_dbus_error (client, dbus_error, out_error);
+ }
+}
+
+/**
+ * e_client_util_unwrap_dbus_error:
+ * @dbus_error: DBus #GError to unwrap
+ * @client_error: (out): Resulting #GError; can be %NULL
+ * @known_errors: List of known errors against which try to match
+ * @known_errors_count: How many items are stored in @known_errors
+ * @known_errors_domain: Error domain for @known_errors
+ * @fail_when_none_matched: Whether to fail when none of @known_errors matches
+ *
+ * The function takes a @dbus_error and tries to find a match in @known_errors for it,
+ * if it is a G_IO_ERROR, G_IO_ERROR_DBUS_ERROR. If it is anything else then the @dbus_error
+ * is moved to @client_error.
+ *
+ * The @fail_when_none_matched influences behaviour. If it's %TRUE, and none of @known_errors matches,
+ * or this is not a G_IO_ERROR_DBUS_ERROR, then %FALSE is returned and the @client_error
+ * is left without change. Otherwise, the @fail_when_none_matched is %FALSE, the error is always
+ * processed and will result in E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR if none of @known_error matches.
+ *
+ * Returns: Whether was @dbus_error processed into @client_error.
+ *
+ * Note: The @dbus_error is automatically freed if returned %TRUE.
+ **/
+gboolean
+e_client_util_unwrap_dbus_error (GError *dbus_error, GError **client_error, const struct EClientErrorsList *known_errors, guint known_errors_count, GQuark known_errors_domain, gboolean fail_when_none_matched)
+{
+ if (!client_error) {
+ if (dbus_error)
+ g_error_free (dbus_error);
+ return TRUE;
+ }
+
+ if (!dbus_error) {
+ *client_error = NULL;
+ return TRUE;
+ }
+
+ if (dbus_error->domain == known_errors_domain) {
+ *client_error = dbus_error;
+ return TRUE;
+ }
+
+ if (known_errors) {
+ if (g_error_matches (dbus_error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)) {
+ gchar *name;
+ gint ii;
+
+ name = g_dbus_error_get_remote_error (dbus_error);
+
+ for (ii = 0; ii < known_errors_count; ii++) {
+ if (g_ascii_strcasecmp (known_errors[ii].name, name) == 0) {
+ g_free (name);
+
+ g_dbus_error_strip_remote_error (dbus_error);
+ *client_error = g_error_new_literal (known_errors_domain, known_errors[ii].err_code, dbus_error->message);
+ g_error_free (dbus_error);
+ return TRUE;
+ }
+ }
+
+ g_free (name);
+ }
+ }
+
+ if (fail_when_none_matched)
+ return FALSE;
+
+ if (g_error_matches (dbus_error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)) {
+ g_dbus_error_strip_remote_error (dbus_error);
+ *client_error = g_error_new_literal (E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR, dbus_error->message);
+ g_error_free (dbus_error);
+ } else {
+ if (dbus_error->domain == G_DBUS_ERROR)
+ g_dbus_error_strip_remote_error (dbus_error);
+ *client_error = dbus_error;
+ }
+
+ return TRUE;
+}
+
+typedef struct _EClientAsyncOpData
+{
+ EClient *client;
+ guint32 opid;
+
+ gpointer source_tag;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+
+ gboolean result; /* result of the finish function call */
+
+ /* only one can be non-NULL, and the type is telling which 'out' value is valid */
+ EClientProxyFinishVoidFunc finish_void;
+ EClientProxyFinishBooleanFunc finish_boolean;
+ EClientProxyFinishStringFunc finish_string;
+ EClientProxyFinishStrvFunc finish_strv;
+ EClientProxyFinishUintFunc finish_uint;
+
+ union {
+ gboolean val_boolean;
+ gchar *val_string;
+ gchar **val_strv;
+ guint val_uint;
+ } out;
+} EClientAsyncOpData;
+
+static void
+async_data_free (EClientAsyncOpData *async_data)
+{
+ g_return_if_fail (async_data != NULL);
+ g_return_if_fail (async_data->client != NULL);
+
+ e_client_unregister_op (async_data->client, async_data->opid);
+
+ if (async_data->finish_string)
+ g_free (async_data->out.val_string);
+ else if (async_data->finish_strv)
+ g_strfreev (async_data->out.val_strv);
+
+ g_object_unref (async_data->client);
+ g_free (async_data);
+}
+
+static gboolean
+complete_async_op_in_idle_cb (gpointer user_data)
+{
+ GSimpleAsyncResult *simple = user_data;
+ gint run_main_depth;
+
+ g_return_val_if_fail (simple != NULL, FALSE);
+
+ run_main_depth = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (simple), "run-main-depth"));
+ if (run_main_depth < 1)
+ run_main_depth = 1;
+
+ /* do not receive in higher level than was initially run */
+ if (g_main_depth () > run_main_depth) {
+ return TRUE;
+ }
+
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ return FALSE;
+}
+
+static void
+finish_async_op (EClientAsyncOpData *async_data, const GError *error, gboolean in_idle)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_if_fail (async_data != NULL);
+ g_return_if_fail (async_data->source_tag != NULL);
+ g_return_if_fail (async_data->client != NULL);
+
+ simple = g_simple_async_result_new (G_OBJECT (async_data->client), async_data->callback, async_data->user_data, async_data->source_tag);
+ g_simple_async_result_set_op_res_gpointer (simple, async_data, (GDestroyNotify) async_data_free);
+
+ if (error != NULL)
+ g_simple_async_result_set_from_error (simple, error);
+
+ if (in_idle) {
+ g_object_set_data (G_OBJECT (simple), "run-main-depth", GINT_TO_POINTER (g_main_depth ()));
+ g_idle_add (complete_async_op_in_idle_cb, simple);
+ } else {
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ }
+}
+
+static void
+async_result_ready_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ GError *error = NULL;
+ EClientAsyncOpData *async_data;
+ EClient *client;
+
+ g_return_if_fail (result != NULL);
+ g_return_if_fail (source_object != NULL);
+
+ async_data = user_data;
+ g_return_if_fail (async_data != NULL);
+ g_return_if_fail (async_data->client != NULL);
+
+ client = async_data->client;
+ g_return_if_fail (e_client_get_dbus_proxy (client) == G_DBUS_PROXY (source_object));
+
+ if (async_data->finish_void)
+ async_data->result = async_data->finish_void (G_DBUS_PROXY (source_object), result, &error);
+ else if (async_data->finish_boolean)
+ async_data->result = async_data->finish_boolean (G_DBUS_PROXY (source_object), result, &async_data->out.val_boolean, &error);
+ else if (async_data->finish_string)
+ async_data->result = async_data->finish_string (G_DBUS_PROXY (source_object), result, &async_data->out.val_string, &error);
+ else if (async_data->finish_strv)
+ async_data->result = async_data->finish_strv (G_DBUS_PROXY (source_object), result, &async_data->out.val_strv, &error);
+ else if (async_data->finish_uint)
+ async_data->result = async_data->finish_uint (G_DBUS_PROXY (source_object), result, &async_data->out.val_uint, &error);
+ else
+ g_warning ("%s: Do not know how to finish async operation", G_STRFUNC);
+
+ finish_async_op (async_data, error, FALSE);
+
+ if (error != NULL)
+ g_error_free (error);
+}
+
+static EClientAsyncOpData *
+prepare_async_data (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, gboolean error_report_only, EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint, GDBusProxy **proxy, GCancellable **out_cancellable)
+{
+ EClientAsyncOpData *async_data;
+ GCancellable *use_cancellable;
+ guint32 opid;
+
+ g_return_val_if_fail (client != NULL, NULL);
+ g_return_val_if_fail (callback != NULL, NULL);
+ g_return_val_if_fail (source_tag != NULL, NULL);
+
+ if (!error_report_only) {
+ g_return_val_if_fail (proxy != NULL, NULL);
+ g_return_val_if_fail (out_cancellable != NULL, NULL);
+ g_return_val_if_fail (finish_void || finish_boolean || finish_string || finish_strv || finish_uint, NULL);
+
+ if (finish_void) {
+ g_return_val_if_fail (finish_boolean == NULL, NULL);
+ g_return_val_if_fail (finish_string == NULL, NULL);
+ g_return_val_if_fail (finish_strv == NULL, NULL);
+ g_return_val_if_fail (finish_uint == NULL, NULL);
+ }
+
+ if (finish_boolean) {
+ g_return_val_if_fail (finish_void == NULL, NULL);
+ g_return_val_if_fail (finish_string == NULL, NULL);
+ g_return_val_if_fail (finish_strv == NULL, NULL);
+ g_return_val_if_fail (finish_uint == NULL, NULL);
+ }
+
+ if (finish_string) {
+ g_return_val_if_fail (finish_void == NULL, NULL);
+ g_return_val_if_fail (finish_boolean == NULL, NULL);
+ g_return_val_if_fail (finish_strv == NULL, NULL);
+ g_return_val_if_fail (finish_uint == NULL, NULL);
+ }
+
+ if (finish_strv) {
+ g_return_val_if_fail (finish_void == NULL, NULL);
+ g_return_val_if_fail (finish_boolean == NULL, NULL);
+ g_return_val_if_fail (finish_string == NULL, NULL);
+ g_return_val_if_fail (finish_uint == NULL, NULL);
+ }
+
+ if (finish_uint) {
+ g_return_val_if_fail (finish_void == NULL, NULL);
+ g_return_val_if_fail (finish_boolean == NULL, NULL);
+ g_return_val_if_fail (finish_string == NULL, NULL);
+ g_return_val_if_fail (finish_strv == NULL, NULL);
+ }
+
+ *proxy = e_client_get_dbus_proxy (client);
+ if (!*proxy)
+ return NULL;
+ }
+
+ use_cancellable = cancellable;
+ if (!use_cancellable)
+ use_cancellable = g_cancellable_new ();
+
+ opid = e_client_register_op (client, use_cancellable);
+ async_data = g_new0 (EClientAsyncOpData, 1);
+ async_data->client = g_object_ref (client);
+ async_data->opid = opid;
+ async_data->source_tag = source_tag;
+ async_data->callback = callback;
+ async_data->user_data = user_data;
+ async_data->finish_void = finish_void;
+ async_data->finish_boolean = finish_boolean;
+ async_data->finish_string = finish_string;
+ async_data->finish_strv = finish_strv;
+ async_data->finish_uint = finish_uint;
+
+ /* EClient from e_client_register_op() took ownership of the use_cancellable */
+ if (use_cancellable != cancellable)
+ g_object_unref (use_cancellable);
+
+ if (out_cancellable)
+ *out_cancellable = use_cancellable;
+
+ return async_data;
+}
+
+void
+e_client_proxy_return_async_error (EClient *client, const GError *error, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag)
+{
+ EClientAsyncOpData *async_data;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (error != NULL);
+ g_return_if_fail (callback != NULL);
+
+ async_data = prepare_async_data (client, NULL, callback, user_data, source_tag, TRUE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ g_return_if_fail (async_data != NULL);
+
+ finish_async_op (async_data, error, TRUE);
+}
+
+void
+e_client_proxy_call_void (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint)
+{
+ EClientAsyncOpData *async_data;
+ GDBusProxy *proxy = NULL;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (source_tag != NULL);
+ e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
+
+ async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
+ e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
+
+ func (proxy, cancellable, async_result_ready_cb, async_data);
+}
+
+void
+e_client_proxy_call_boolean (EClient *client, gboolean in_boolean, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint)
+{
+ EClientAsyncOpData *async_data;
+ GDBusProxy *proxy = NULL;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (source_tag != NULL);
+ e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
+
+ async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
+ e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
+
+ func (proxy, in_boolean, cancellable, async_result_ready_cb, async_data);
+}
+
+void
+e_client_proxy_call_string (EClient *client, const gchar *in_string, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, const gchar * in_string, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint)
+{
+ EClientAsyncOpData *async_data;
+ GDBusProxy *proxy = NULL;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (source_tag != NULL);
+ e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
+ e_client_return_async_if_fail (in_string != NULL, client, callback, user_data, source_tag);
+
+ async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
+ e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
+
+ func (proxy, in_string, cancellable, async_result_ready_cb, async_data);
+}
+
+void
+e_client_proxy_call_strv (EClient *client, const gchar * const *in_strv, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, const gchar * const * in_strv, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint)
+{
+ EClientAsyncOpData *async_data;
+ GDBusProxy *proxy = NULL;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (source_tag != NULL);
+ e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
+ e_client_return_async_if_fail (in_strv != NULL, client, callback, user_data, source_tag);
+
+ async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
+ e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
+
+ func (proxy, in_strv, cancellable, async_result_ready_cb, async_data);
+}
+
+void
+e_client_proxy_call_uint (EClient *client, guint in_uint, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, void (*func) (GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data), EClientProxyFinishVoidFunc finish_void, EClientProxyFinishBooleanFunc finish_boolean, EClientProxyFinishStringFunc finish_string, EClientProxyFinishStrvFunc finish_strv, EClientProxyFinishUintFunc finish_uint)
+{
+ EClientAsyncOpData *async_data;
+ GDBusProxy *proxy = NULL;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (source_tag != NULL);
+ e_client_return_async_if_fail (func != NULL, client, callback, user_data, source_tag);
+
+ async_data = prepare_async_data (client, cancellable, callback, user_data, source_tag, FALSE, finish_void, finish_boolean, finish_string, finish_strv, finish_uint, &proxy, &cancellable);
+ e_client_return_async_if_fail (async_data != NULL, client, callback, user_data, source_tag);
+
+ func (proxy, in_uint, cancellable, async_result_ready_cb, async_data);
+}
+
+gboolean
+e_client_proxy_call_finish_void (EClient *client, GAsyncResult *result, GError **error, gpointer source_tag)
+{
+ GSimpleAsyncResult *simple;
+ GError *local_error = NULL;
+ EClientAsyncOpData *async_data;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (result != NULL, FALSE);
+ g_return_val_if_fail (source_tag != NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, &local_error)) {
+ e_client_unwrap_dbus_error (client, local_error, error);
+ return FALSE;
+ }
+
+ async_data = g_simple_async_result_get_op_res_gpointer (simple);
+ g_return_val_if_fail (async_data != NULL, FALSE);
+
+ return async_data->result;
+}
+
+gboolean
+e_client_proxy_call_finish_boolean (EClient *client, GAsyncResult *result, gboolean *out_boolean, GError **error, gpointer source_tag)
+{
+ GSimpleAsyncResult *simple;
+ GError *local_error = NULL;
+ EClientAsyncOpData *async_data;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (result != NULL, FALSE);
+ g_return_val_if_fail (source_tag != NULL, FALSE);
+ g_return_val_if_fail (out_boolean != NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, &local_error)) {
+ e_client_unwrap_dbus_error (client, local_error, error);
+ return FALSE;
+ }
+
+ async_data = g_simple_async_result_get_op_res_gpointer (simple);
+ g_return_val_if_fail (async_data != NULL, FALSE);
+
+ *out_boolean = async_data->out.val_boolean;
+
+ return async_data->result;
+}
+
+gboolean
+e_client_proxy_call_finish_string (EClient *client, GAsyncResult *result, gchar **out_string, GError **error, gpointer source_tag)
+{
+ GSimpleAsyncResult *simple;
+ GError *local_error = NULL;
+ EClientAsyncOpData *async_data;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (result != NULL, FALSE);
+ g_return_val_if_fail (source_tag != NULL, FALSE);
+ g_return_val_if_fail (out_string != NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, &local_error)) {
+ e_client_unwrap_dbus_error (client, local_error, error);
+ return FALSE;
+ }
+
+ async_data = g_simple_async_result_get_op_res_gpointer (simple);
+ g_return_val_if_fail (async_data != NULL, FALSE);
+
+ *out_string = async_data->out.val_string;
+ async_data->out.val_string = NULL;
+
+ return async_data->result;
+}
+
+gboolean
+e_client_proxy_call_finish_strv (EClient *client, GAsyncResult *result, gchar ***out_strv, GError **error, gpointer source_tag)
+{
+ GSimpleAsyncResult *simple;
+ GError *local_error = NULL;
+ EClientAsyncOpData *async_data;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (result != NULL, FALSE);
+ g_return_val_if_fail (source_tag != NULL, FALSE);
+ g_return_val_if_fail (out_strv != NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, &local_error)) {
+ e_client_unwrap_dbus_error (client, local_error, error);
+ return FALSE;
+ }
+
+ async_data = g_simple_async_result_get_op_res_gpointer (simple);
+ g_return_val_if_fail (async_data != NULL, FALSE);
+
+ *out_strv = async_data->out.val_strv;
+ async_data->out.val_strv = NULL;
+
+ return async_data->result;
+}
+
+gboolean
+e_client_proxy_call_finish_uint (EClient *client, GAsyncResult *result, guint *out_uint, GError **error, gpointer source_tag)
+{
+ GSimpleAsyncResult *simple;
+ GError *local_error = NULL;
+ EClientAsyncOpData *async_data;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (result != NULL, FALSE);
+ g_return_val_if_fail (source_tag != NULL, FALSE);
+ g_return_val_if_fail (out_uint != NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), source_tag), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, &local_error)) {
+ e_client_unwrap_dbus_error (client, local_error, error);
+ return FALSE;
+ }
+
+ async_data = g_simple_async_result_get_op_res_gpointer (simple);
+ g_return_val_if_fail (async_data != NULL, FALSE);
+
+ *out_uint = async_data->out.val_uint;
+
+ return async_data->result;
+}
+
+#define SYNC_CALL_TEMPLATE(_out_test,_the_call) \
+ GDBusProxy *proxy; \
+ GCancellable *use_cancellable; \
+ guint32 opid; \
+ gboolean result; \
+ GError *local_error = NULL; \
+ \
+ g_return_val_if_fail (client != NULL, FALSE); \
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE); \
+ g_return_val_if_fail (func != NULL, FALSE); \
+ g_return_val_if_fail (_out_test != NULL, FALSE); \
+ \
+ proxy = e_client_get_dbus_proxy (client); \
+ g_return_val_if_fail (proxy != NULL, FALSE); \
+ \
+ use_cancellable = cancellable; \
+ if (!use_cancellable) \
+ use_cancellable = g_cancellable_new (); \
+ \
+ g_object_ref (client); \
+ opid = e_client_register_op (client, use_cancellable); \
+ \
+ result = func _the_call; \
+ \
+ e_client_unregister_op (client, opid); \
+ g_object_unref (client); \
+ \
+ if (use_cancellable != cancellable) \
+ g_object_unref (use_cancellable); \
+ \
+ e_client_unwrap_dbus_error (client, local_error, error);\
+ \
+ return result;
+
+gboolean
+e_client_proxy_call_sync_void__void (EClient *client, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (client, (proxy, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_void__boolean (EClient *client, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean *out_boolean, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_boolean, (proxy, out_boolean, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_void__string (EClient *client, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gchar **out_string, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_string, (proxy, out_string, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_void__strv (EClient *client, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gchar ***out_strv, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_strv, (proxy, out_strv, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_void__uint (EClient *client, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint *out_uint, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_uint, (proxy, out_uint, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_boolean__void (EClient *client, gboolean in_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (client, (proxy, in_boolean, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_boolean__boolean (EClient *client, gboolean in_boolean, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, gboolean *out_boolean, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_boolean, (proxy, in_boolean, out_boolean, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_boolean__string (EClient *client, gboolean in_boolean, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, gchar **out_string, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_string, (proxy, in_boolean, out_string, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_boolean__strv (EClient *client, gboolean in_boolean, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, gchar ***out_strv, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_strv, (proxy, in_boolean, out_strv, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_boolean__uint (EClient *client, gboolean in_boolean, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, gboolean in_boolean, guint *out_uint, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_uint, (proxy, in_boolean, out_uint, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_string__void (EClient *client, const gchar *in_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (client, (proxy, in_string, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_string__boolean (EClient *client, const gchar *in_string, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, gboolean *out_boolean, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_boolean, (proxy, in_string, out_boolean, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_string__string (EClient *client, const gchar *in_string, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, gchar **out_string, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_string, (proxy, in_string, out_string, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_string__strv (EClient *client, const gchar *in_string, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, gchar ***out_strv, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_strv, (proxy, in_string, out_strv, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_string__uint (EClient *client, const gchar *in_string, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar *in_string, guint *out_uint, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_uint, (proxy, in_string, out_uint, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_strv__void (EClient *client, const gchar * const *in_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (client, (proxy, in_strv, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_strv__boolean (EClient *client, const gchar * const *in_strv, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, gboolean *out_boolean, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_boolean, (proxy, in_strv, out_boolean, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_strv__string (EClient *client, const gchar * const *in_strv, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, gchar **out_string, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_string, (proxy, in_strv, out_string, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_strv__strv (EClient *client, const gchar * const *in_strv, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, gchar ***out_strv, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_strv, (proxy, in_strv, out_strv, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_strv__uint (EClient *client, const gchar * const *in_strv, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, const gchar * const *in_strv, guint *out_uint, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_uint, (proxy, in_strv, out_uint, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_uint__void (EClient *client, guint in_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (client, (proxy, in_uint, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_uint__boolean (EClient *client, guint in_uint, gboolean *out_boolean, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, gboolean *out_boolean, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_boolean, (proxy, in_uint, out_boolean, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_uint__string (EClient *client, guint in_uint, gchar **out_string, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, gchar **out_string, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_string, (proxy, in_uint, out_string, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_uint__strv (EClient *client, guint in_uint, gchar ***out_strv, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, gchar ***out_strv, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_strv, (proxy, in_uint, out_strv, use_cancellable, &local_error))
+}
+
+gboolean
+e_client_proxy_call_sync_uint__uint (EClient *client, guint in_uint, guint *out_uint, GCancellable *cancellable, GError **error, gboolean (*func) (GDBusProxy *proxy, guint in_uint, guint *out_uint, GCancellable *cancellable, GError **error))
+{
+ SYNC_CALL_TEMPLATE (out_uint, (proxy, in_uint, out_uint, use_cancellable, &local_error))
+}
+
+#undef SYNC_CALL_TEMPLATE
diff --git a/libedataserver/e-client.h b/libedataserver/e-client.h
new file mode 100644
index 0000000..0d6f793
--- /dev/null
+++ b/libedataserver/e-client.h
@@ -0,0 +1,167 @@
+/*
+ * e-client.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_CLIENT_H
+#define E_CLIENT_H
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <libedataserver/e-credentials.h>
+#include <libedataserver/e-source.h>
+#include <libedataserver/e-source-list.h>
+
+#define E_TYPE_CLIENT (e_client_get_type ())
+#define E_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_CLIENT, EClient))
+#define E_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), E_TYPE_CLIENT, EClientClass))
+#define E_IS_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_CLIENT))
+#define E_IS_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_CLIENT))
+#define E_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_CLIENT, EClientClass))
+
+#define CLIENT_BACKEND_PROPERTY_OPENED "opened"
+#define CLIENT_BACKEND_PROPERTY_OPENING "opening"
+#define CLIENT_BACKEND_PROPERTY_ONLINE "online"
+#define CLIENT_BACKEND_PROPERTY_READONLY "readonly"
+#define CLIENT_BACKEND_PROPERTY_CACHE_DIR "cache-dir"
+#define CLIENT_BACKEND_PROPERTY_CAPABILITIES "capabilities"
+
+#define E_CLIENT_ERROR e_client_error_quark ()
+
+GQuark e_client_error_quark (void) G_GNUC_CONST;
+
+typedef enum {
+ E_CLIENT_ERROR_INVALID_ARG,
+ E_CLIENT_ERROR_BUSY,
+ E_CLIENT_ERROR_SOURCE_NOT_LOADED,
+ E_CLIENT_ERROR_SOURCE_ALREADY_LOADED,
+ E_CLIENT_ERROR_AUTHENTICATION_FAILED,
+ E_CLIENT_ERROR_AUTHENTICATION_REQUIRED,
+ E_CLIENT_ERROR_REPOSITORY_OFFLINE,
+ E_CLIENT_ERROR_PERMISSION_DENIED,
+ E_CLIENT_ERROR_CANCELLED,
+ E_CLIENT_ERROR_COULD_NOT_CANCEL,
+ E_CLIENT_ERROR_NOT_SUPPORTED,
+ E_CLIENT_ERROR_DBUS_ERROR,
+ E_CLIENT_ERROR_OTHER_ERROR
+} EClientError;
+
+const gchar *e_client_error_to_string (EClientError code);
+
+typedef struct _EClient EClient;
+typedef struct _EClientClass EClientClass;
+typedef struct _EClientPrivate EClientPrivate;
+
+struct _EClient {
+ GObject parent;
+
+ /*< private >*/
+ EClientPrivate *priv;
+};
+
+struct _EClientClass {
+ GObjectClass parent;
+
+ /* virtual methods */
+ GDBusProxy * (* get_dbus_proxy) (EClient *client);
+ void (* unwrap_dbus_error) (EClient *client, GError *dbus_error, GError **out_error);
+
+ void (* get_backend_property) (EClient *client, const gchar *prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+ gboolean (* get_backend_property_finish) (EClient *client, GAsyncResult *result, gchar **prop_value, GError **error);
+ gboolean (* get_backend_property_sync) (EClient *client, const gchar *prop_name, gchar **prop_value, GCancellable *cancellable, GError **error);
+
+ void (* set_backend_property) (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+ gboolean (* set_backend_property_finish) (EClient *client, GAsyncResult *result, GError **error);
+ gboolean (* set_backend_property_sync) (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GError **error);
+
+ void (* open) (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+ gboolean (* open_finish) (EClient *client, GAsyncResult *result, GError **error);
+ gboolean (* open_sync) (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error);
+
+ void (* remove) (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+ gboolean (* remove_finish) (EClient *client, GAsyncResult *result, GError **error);
+ gboolean (* remove_sync) (EClient *client, GCancellable *cancellable, GError **error);
+
+ void (* refresh) (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+ gboolean (* refresh_finish) (EClient *client, GAsyncResult *result, GError **error);
+ gboolean (* refresh_sync) (EClient *client, GCancellable *cancellable, GError **error);
+
+ void (* handle_authentication) (EClient *client, const ECredentials *credentials);
+ gchar * (* retrieve_capabilities) (EClient *client);
+
+ /* signals */
+ gboolean (* authenticate) (EClient *client, ECredentials *credentials);
+ void (* opened) (EClient *client, const GError *error);
+ void (* backend_error) (EClient *client, const gchar *error_msg);
+ void (* backend_died) (EClient *client);
+};
+
+GType e_client_get_type (void);
+
+ESource * e_client_get_source (EClient *client);
+const gchar * e_client_get_uri (EClient *client);
+const GSList * e_client_get_capabilities (EClient *client);
+gboolean e_client_check_capability (EClient *client, const gchar *capability);
+gboolean e_client_check_refresh_supported (EClient *client);
+gboolean e_client_is_readonly (EClient *client);
+gboolean e_client_is_online (EClient *client);
+gboolean e_client_is_opened (EClient *client);
+
+void e_client_cancel_all (EClient *client);
+
+void e_client_get_backend_property (EClient *client, const gchar *prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_client_get_backend_property_finish (EClient *client, GAsyncResult *result, gchar **prop_value, GError **error);
+gboolean e_client_get_backend_property_sync (EClient *client, const gchar *prop_name, gchar **prop_value, GCancellable *cancellable, GError **error);
+
+void e_client_set_backend_property (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_client_set_backend_property_finish (EClient *client, GAsyncResult *result, GError **error);
+gboolean e_client_set_backend_property_sync (EClient *client, const gchar *prop_name, const gchar *prop_value, GCancellable *cancellable, GError **error);
+
+void e_client_open (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_client_open_finish (EClient *client, GAsyncResult *result, GError **error);
+gboolean e_client_open_sync (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error);
+
+void e_client_remove (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_client_remove_finish (EClient *client, GAsyncResult *result, GError **error);
+gboolean e_client_remove_sync (EClient *client, GCancellable *cancellable, GError **error);
+
+void e_client_refresh (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_client_refresh_finish (EClient *client, GAsyncResult *result, GError **error);
+gboolean e_client_refresh_sync (EClient *client, GCancellable *cancellable, GError **error);
+
+/* utility functions */
+gchar ** e_client_util_slist_to_strv (const GSList *strings);
+GSList * e_client_util_strv_to_slist (const gchar * const *strv);
+GSList * e_client_util_copy_string_slist (GSList *copy_to, const GSList *strings);
+GSList * e_client_util_copy_object_slist (GSList *copy_to, const GSList *objects);
+void e_client_util_free_string_slist (GSList *strings);
+void e_client_util_free_object_slist (GSList *objects);
+GSList * e_client_util_parse_comma_strings (const gchar *capabilities);
+
+struct EClientErrorsList {
+ const gchar *name;
+ gint err_code;
+};
+
+gboolean e_client_util_unwrap_dbus_error (GError *dbus_error, GError **client_error, const struct EClientErrorsList *known_errors, guint known_errors_count, GQuark known_errors_domain, gboolean fail_when_none_matched);
+
+G_END_DECLS
+
+#endif /* E_CLIENT_H */
diff --git a/libedataserver/e-credentials.c b/libedataserver/e-credentials.c
new file mode 100644
index 0000000..ab4910c
--- /dev/null
+++ b/libedataserver/e-credentials.c
@@ -0,0 +1,560 @@
+/*
+ * e-credentials.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "e-data-server-util.h"
+
+#include "e-credentials.h"
+
+struct _ECredentialsPrivate
+{
+ GHashTable *keys;
+ GHashTable *peek_keys;
+};
+
+static gboolean
+key_equal (gconstpointer str1, gconstpointer str2)
+{
+ g_return_val_if_fail (str1 != NULL, FALSE);
+ g_return_val_if_fail (str2 != NULL, FALSE);
+
+ if (str1 == str2)
+ return TRUE;
+
+ return g_ascii_strcasecmp (str1, str2) == 0;
+}
+
+ECredentials *
+e_credentials_new (void)
+{
+ ECredentials *credentials;
+
+ credentials = g_new0 (ECredentials, 1);
+ credentials->priv = g_new0 (ECredentialsPrivate, 1);
+ credentials->priv->keys = g_hash_table_new_full (g_str_hash, key_equal, g_free, (GDestroyNotify) e_credentials_util_safe_free_string);
+ credentials->priv->peek_keys = g_hash_table_new_full (g_str_hash, key_equal, g_free, (GDestroyNotify) e_credentials_util_safe_free_string);
+
+ return credentials;
+}
+
+/* Expects @keys as NULL terminate list of strings "key:encoded_value".
+ The same can be returned from e_credentials_to_strv().
+*/
+ECredentials *
+e_credentials_new_strv (const gchar * const *keys)
+{
+ ECredentials *credentials;
+ gint ii;
+
+ g_return_val_if_fail (keys != NULL, NULL);
+
+ credentials = e_credentials_new ();
+
+ for (ii = 0; keys[ii]; ii++) {
+ const gchar *key = keys[ii], *sep;
+
+ sep = strchr (key, ':');
+
+ /* skip empty and invalid values */
+ if (sep)
+ g_hash_table_insert (credentials->priv->keys, g_strndup (key, sep - key), g_strdup (sep + 1));
+ }
+
+ return credentials;
+}
+
+/* NULL-terminated list of string pairs <key, value>; value is in a clear form */
+ECredentials *
+e_credentials_new_args (const gchar *key, ...)
+{
+ ECredentials *credentials;
+ va_list va;
+
+ g_return_val_if_fail (key != NULL, NULL);
+
+ credentials = e_credentials_new ();
+
+ va_start (va, key);
+
+ while (key) {
+ const gchar *value = va_arg (va, const gchar *);
+
+ if (key && *key && value && *value)
+ e_credentials_set (credentials, key, value);
+
+ key = va_arg (va, const gchar *);
+ }
+
+ va_end (va);
+
+ return credentials;
+}
+
+static void
+copy_keys_cb (gpointer key, gpointer value, gpointer hash_table)
+{
+ g_hash_table_insert (hash_table, g_strdup (key), g_strdup (value));
+}
+
+ECredentials *
+e_credentials_new_clone (const ECredentials *credentials)
+{
+ ECredentials *res;
+
+ g_return_val_if_fail (credentials != NULL, NULL);
+ g_return_val_if_fail (credentials->priv != NULL, NULL);
+ g_return_val_if_fail (credentials->priv->keys != NULL, NULL);
+
+ res = e_credentials_new ();
+
+ g_hash_table_foreach (credentials->priv->keys, copy_keys_cb, res->priv->keys);
+
+ return res;
+}
+
+void
+e_credentials_free (ECredentials *credentials)
+{
+ if (!credentials)
+ return;
+
+ g_return_if_fail (credentials->priv != NULL);
+
+ g_hash_table_destroy (credentials->priv->keys);
+ g_hash_table_destroy (credentials->priv->peek_keys);
+ g_free (credentials->priv);
+ g_free (credentials);
+}
+
+static void
+add_to_array_cb (gpointer key, gpointer value, gpointer ptr_array)
+{
+ if (key && value && ptr_array) {
+ gchar *str = g_strconcat (key, ":", value, NULL);
+
+ g_ptr_array_add (ptr_array, e_util_utf8_make_valid (str));
+
+ g_free (str);
+ }
+}
+
+/* Returns NULL-terminated array of strings with keys and encoded values;
+ To read them back pass this pointer to e_credentials_new(). As it returns
+ newly allocated string then this should be freed with g_strfreev()
+ when no longer needed.
+*/
+gchar **
+e_credentials_to_strv (const ECredentials *credentials)
+{
+ GPtrArray *array;
+
+ g_return_val_if_fail (credentials != NULL, NULL);
+ g_return_val_if_fail (credentials->priv != NULL, NULL);
+ g_return_val_if_fail (credentials->priv->keys != NULL, NULL);
+
+ array = g_ptr_array_sized_new (g_hash_table_size (credentials->priv->keys) + 1);
+
+ g_hash_table_foreach (credentials->priv->keys, add_to_array_cb, array);
+
+ /* NULL-terminated */
+ g_ptr_array_add (array, NULL);
+
+ return (gchar **) g_ptr_array_free (array, FALSE);
+}
+
+static gchar *
+encode_string (const gchar *decoded)
+{
+ gsize len, ii;
+ guchar xval, *copy;
+ gchar *res;
+
+ if (!decoded || !*decoded)
+ return NULL;
+
+ copy = (guchar *) g_strdup (decoded);
+ len = strlen ((const gchar *) copy);
+
+ xval = 17;
+ for (ii = 0; ii < len; ii++) {
+ copy[ii] = copy[ii] ^ xval;
+ xval += 17;
+ }
+
+ res = g_base64_encode (copy, len);
+
+ g_free (copy);
+
+ return res;
+}
+
+static gchar *
+decode_string (const gchar *encoded)
+{
+ guchar *data, xval;
+ gsize len = 0, ii;
+ gchar *res;
+
+ g_return_val_if_fail (encoded != NULL, NULL);
+ g_return_val_if_fail (*encoded, NULL);
+
+ data = g_base64_decode (encoded, &len);
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (len > 0, NULL);
+
+ xval = 17;
+ for (ii = 0; ii < len; ii++) {
+ data[ii] = data[ii] ^ xval;
+ xval += 17;
+ }
+
+ res = g_strndup ((const gchar *) data, len);
+
+ e_credentials_util_safe_free_string ((gchar *) data);
+
+ return res;
+}
+
+/* sets value for a key, if value is NULL or an empty string then the key is removed.
+ the value is supposed to be in a clear form (unencoded).
+ 'key' cannot contain colon.
+*/
+void
+e_credentials_set (ECredentials *credentials, const gchar *key, const gchar *value)
+{
+ g_return_if_fail (credentials != NULL);
+ g_return_if_fail (credentials->priv != NULL);
+ g_return_if_fail (credentials->priv->keys != NULL);
+ g_return_if_fail (credentials->priv->peek_keys != NULL);
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (*key);
+ g_return_if_fail (strchr (key, ':') == NULL);
+
+ g_hash_table_remove (credentials->priv->peek_keys, key);
+
+ if (!value) {
+ g_hash_table_remove (credentials->priv->keys, key);
+ } else {
+ g_hash_table_insert (credentials->priv->keys, g_strdup (key), encode_string (value));
+ }
+}
+
+/* Returned pointer should be freed with e_credentials_util_safe_free_string()
+ when no longer needed.
+*/
+gchar *
+e_credentials_get (const ECredentials *credentials, const gchar *key)
+{
+ const gchar *stored;
+
+ g_return_val_if_fail (credentials != NULL, NULL);
+ g_return_val_if_fail (credentials->priv != NULL, NULL);
+ g_return_val_if_fail (credentials->priv->keys != NULL, NULL);
+ g_return_val_if_fail (key != NULL, NULL);
+ g_return_val_if_fail (*key, NULL);
+
+ stored = g_hash_table_lookup (credentials->priv->keys, key);
+ if (!stored)
+ return NULL;
+
+ return decode_string (stored);
+}
+
+/* peeks value for a key, in a clear form. The value is valid until free
+ of the @credentials structure or until the key value is rewritten
+ by e_credentials_set()
+*/
+const gchar *
+e_credentials_peek (ECredentials *credentials, const gchar *key)
+{
+ gchar *value;
+
+ g_return_val_if_fail (credentials != NULL, NULL);
+ g_return_val_if_fail (credentials->priv != NULL, NULL);
+ g_return_val_if_fail (credentials->priv->peek_keys != NULL, NULL);
+ g_return_val_if_fail (key != NULL, NULL);
+ g_return_val_if_fail (*key, NULL);
+
+ value = g_hash_table_lookup (credentials->priv->peek_keys, key);
+ if (value)
+ return value;
+
+ value = e_credentials_get (credentials, key);
+ if (value)
+ g_hash_table_insert (credentials->priv->peek_keys, g_strdup (key), value);
+
+ return value;
+}
+
+struct equal_data
+{
+ gboolean equal;
+ GHashTable *keys;
+};
+
+static void
+check_equal_cb (gpointer key, gpointer value, gpointer user_data)
+{
+ struct equal_data *ed = user_data;
+
+ g_return_if_fail (ed != NULL);
+ g_return_if_fail (ed->keys != NULL);
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (value != NULL);
+
+ ed->equal = ed->equal && g_strcmp0 (value, g_hash_table_lookup (ed->keys, key)) == 0;
+}
+
+/* Returns whether two credential structurs contain the same keys with same values */
+gboolean
+e_credentials_equal (const ECredentials *credentials1, const ECredentials *credentials2)
+{
+ struct equal_data ed;
+
+ if (!credentials1 && !credentials2)
+ return TRUE;
+
+ if (credentials1 == credentials2)
+ return TRUE;
+
+ if (!credentials1 || !credentials2)
+ return FALSE;
+
+ g_return_val_if_fail (credentials1->priv != NULL, FALSE);
+ g_return_val_if_fail (credentials1->priv->keys != NULL, FALSE);
+ g_return_val_if_fail (credentials2->priv != NULL, FALSE);
+ g_return_val_if_fail (credentials2->priv->keys != NULL, FALSE);
+
+ if (g_hash_table_size (credentials1->priv->keys) != g_hash_table_size (credentials2->priv->keys))
+ return FALSE;
+
+ ed.equal = TRUE;
+ ed.keys = credentials2->priv->keys;
+
+ g_hash_table_foreach (credentials1->priv->keys, check_equal_cb, &ed);
+
+ return ed.equal;
+}
+
+/* Returns whether two credentials structures has same keys. Key names are NULL-terminated. */
+gboolean
+e_credentials_equal_keys (const ECredentials *credentials1, const ECredentials *credentials2, const gchar *key1, ...)
+{
+ va_list va;
+ gboolean equal = TRUE;
+
+ g_return_val_if_fail (credentials1 != NULL, FALSE);
+ g_return_val_if_fail (credentials1->priv != NULL, FALSE);
+ g_return_val_if_fail (credentials1->priv->keys != NULL, FALSE);
+ g_return_val_if_fail (credentials2 != NULL, FALSE);
+ g_return_val_if_fail (credentials2->priv != NULL, FALSE);
+ g_return_val_if_fail (credentials2->priv->keys != NULL, FALSE);
+ g_return_val_if_fail (key1 != NULL, FALSE);
+
+ va_start (va, key1);
+
+ while (key1 && equal) {
+ equal = g_strcmp0 (g_hash_table_lookup (credentials1->priv->keys, key1), g_hash_table_lookup (credentials2->priv->keys, key1)) == 0;
+
+ key1 = va_arg (va, const gchar *);
+ }
+
+ va_end (va);
+
+ return equal;
+}
+
+/**
+ * Returns whether @credentials contains @key.
+ * This key is non-NULL and non-empty string.
+ **/
+gboolean
+e_credentials_has_key (const ECredentials *credentials, const gchar *key)
+{
+ g_return_val_if_fail (credentials != NULL, FALSE);
+ g_return_val_if_fail (credentials->priv != NULL, FALSE);
+ g_return_val_if_fail (credentials->priv->keys != NULL, FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+ g_return_val_if_fail (*key, FALSE);
+
+ return g_hash_table_lookup (credentials->priv->keys, key) != NULL;
+}
+
+guint
+e_credentials_keys_size (const ECredentials *credentials)
+{
+ g_return_val_if_fail (credentials != NULL, 0);
+ g_return_val_if_fail (credentials->priv != NULL, 0);
+ g_return_val_if_fail (credentials->priv->keys != NULL, 0);
+
+ return g_hash_table_size (credentials->priv->keys);
+}
+
+static void
+gather_key_names (gpointer key, gpointer value, gpointer pslist)
+{
+ GSList **slist = pslist;
+
+ g_return_if_fail (pslist != NULL);
+ g_return_if_fail (key != NULL);
+
+ *slist = g_slist_prepend (*slist, key);
+}
+
+/* Returns newly allocated list of key names stored in the credentials strucutre;
+ strings are internal credentials values, only the list is newly allocated.
+ Free the list with g_slist_free() when no longer needed.
+*/
+GSList *
+e_credentials_list_keys (const ECredentials *credentials)
+{
+ GSList *keys = NULL;
+
+ g_return_val_if_fail (credentials != NULL, NULL);
+ g_return_val_if_fail (credentials->priv != NULL, NULL);
+ g_return_val_if_fail (credentials->priv->keys != NULL, NULL);
+
+ g_hash_table_foreach (credentials->priv->keys, gather_key_names, &keys);
+
+ return g_slist_reverse (keys);
+}
+
+/* Removes all keys in once. */
+void
+e_credentials_clear (ECredentials *credentials)
+{
+ g_return_if_fail (credentials != NULL);
+ g_return_if_fail (credentials->priv != NULL);
+ g_return_if_fail (credentials->priv->keys != NULL);
+ g_return_if_fail (credentials->priv->peek_keys != NULL);
+
+ g_hash_table_remove_all (credentials->priv->peek_keys);
+ g_hash_table_remove_all (credentials->priv->keys);
+}
+
+void
+e_credentials_clear_peek (ECredentials *credentials)
+{
+ g_return_if_fail (credentials != NULL);
+ g_return_if_fail (credentials->priv != NULL);
+ g_return_if_fail (credentials->priv->peek_keys != NULL);
+
+ g_hash_table_remove_all (credentials->priv->peek_keys);
+}
+
+void
+e_credentials_util_safe_free_string (gchar *str)
+{
+ if (!str)
+ return;
+
+ if (*str)
+ memset (str, 0, sizeof (gchar) * strlen (str));
+
+ g_free (str);
+}
+
+static struct _PromptFlags {
+ ECredentialsPromptFlags flag_uint;
+ const gchar *flag_string;
+ gboolean is_bit_flag; /* if false, then checked against E_CREDENTIALS_PROMPT_FLAG_REMEMBER_MASK */
+} PromptFlags[] = {
+ { E_CREDENTIALS_PROMPT_FLAG_REMEMBER_NEVER, "remember-never", FALSE },
+ { E_CREDENTIALS_PROMPT_FLAG_REMEMBER_SESSION, "remember-session", FALSE },
+ { E_CREDENTIALS_PROMPT_FLAG_REMEMBER_FOREVER, "remember-forever", FALSE },
+
+ { E_CREDENTIALS_PROMPT_FLAG_SECRET, "secret", TRUE },
+ { E_CREDENTIALS_PROMPT_FLAG_REPROMPT, "reprompt", TRUE },
+ { E_CREDENTIALS_PROMPT_FLAG_ONLINE, "online", TRUE },
+ { E_CREDENTIALS_PROMPT_FLAG_DISABLE_REMEMBER, "disable-remember", TRUE },
+ { E_CREDENTIALS_PROMPT_FLAG_PASSPHRASE, "passphrase", TRUE }
+};
+
+/* Returned pointer can be passed to e_credentials_util_string_to prompt_flags()
+ to decode it back to flags. Free returned pointer with g_free().
+*/
+gchar *
+e_credentials_util_prompt_flags_to_string (guint prompt_flags)
+{
+ gint ii;
+ guint masked = prompt_flags & E_CREDENTIALS_PROMPT_FLAG_REMEMBER_MASK;
+ GString *str = g_string_new ("");
+
+ for (ii = 0; ii < G_N_ELEMENTS (PromptFlags); ii++) {
+ const gchar *add = NULL;
+
+ if (PromptFlags[ii].is_bit_flag) {
+ if ((prompt_flags & PromptFlags[ii].flag_uint) != 0)
+ add = PromptFlags[ii].flag_string;
+ } else if (masked == PromptFlags[ii].flag_uint) {
+ add = PromptFlags[ii].flag_string;
+ }
+
+ if (!add)
+ continue;
+
+ if (str->len)
+ g_string_append (str, ",");
+
+ g_string_append (str, add);
+ }
+
+ return g_string_free (str, FALSE);
+}
+
+guint
+e_credentials_util_string_to_prompt_flags (const gchar *prompt_flags_string)
+{
+ gchar **strv;
+ gint ii, jj;
+ guint flags = 0;
+
+ if (!prompt_flags_string || !*prompt_flags_string)
+ return flags;
+
+ strv = g_strsplit (prompt_flags_string, ",", -1);
+ if (!strv)
+ return flags;
+
+ for (jj = 0; strv[jj]; jj++) {
+ const gchar *str = strv[jj];
+
+ for (ii = 0; ii < G_N_ELEMENTS (PromptFlags); ii++) {
+ if (g_str_equal (PromptFlags[ii].flag_string, str)) {
+ if (PromptFlags[ii].is_bit_flag)
+ flags |= PromptFlags[ii].flag_uint;
+ else
+ flags = (flags & (~E_CREDENTIALS_PROMPT_FLAG_REMEMBER_MASK)) | PromptFlags[ii].flag_uint;
+ }
+ }
+ }
+
+ g_strfreev (strv);
+
+ return flags;
+}
diff --git a/libedataserver/e-credentials.h b/libedataserver/e-credentials.h
new file mode 100644
index 0000000..06b0f26
--- /dev/null
+++ b/libedataserver/e-credentials.h
@@ -0,0 +1,87 @@
+/*
+ * e-credentials.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_CREDENTIALS_H
+#define E_CREDENTIALS_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ECredentialsPrivate ECredentialsPrivate;
+
+typedef struct _ECredentials
+{
+ ECredentialsPrivate *priv;
+} ECredentials;
+
+#define E_CREDENTIALS_KEY_USERNAME "username"
+#define E_CREDENTIALS_KEY_PASSWORD "password"
+#define E_CREDENTIALS_KEY_AUTH_METHOD "auth-method"
+#define E_CREDENTIALS_KEY_AUTH_DOMAIN "auth-domain"
+#define E_CREDENTIALS_KEY_PROMPT_TITLE "prompt-title"
+#define E_CREDENTIALS_KEY_PROMPT_TEXT "prompt-text"
+#define E_CREDENTIALS_KEY_PROMPT_REASON "prompt-reason"
+#define E_CREDENTIALS_KEY_PROMPT_KEY "prompt-key"
+#define E_CREDENTIALS_KEY_PROMPT_FLAGS "prompt-flags"
+
+#define E_CREDENTIALS_AUTH_DOMAIN_ADDRESSBOOK "Addressbook"
+#define E_CREDENTIALS_AUTH_DOMAIN_CALENDAR "Calendar"
+#define E_CREDENTIALS_AUTH_DOMAIN_MAIL "Mail"
+
+/* this is 1:1 with EPasswordsRememberType */
+typedef enum {
+ E_CREDENTIALS_PROMPT_FLAG_REMEMBER_NEVER,
+ E_CREDENTIALS_PROMPT_FLAG_REMEMBER_SESSION,
+ E_CREDENTIALS_PROMPT_FLAG_REMEMBER_FOREVER,
+ E_CREDENTIALS_PROMPT_FLAG_REMEMBER_MASK = 0xf,
+
+ E_CREDENTIALS_PROMPT_FLAG_SECRET = 1 << 8, /* whether hide password letters in the UI */
+ E_CREDENTIALS_PROMPT_FLAG_REPROMPT = 1 << 9, /* automatically set when username and password is provided */
+ E_CREDENTIALS_PROMPT_FLAG_ONLINE = 1 << 10, /* only ask if we're online */
+ E_CREDENTIALS_PROMPT_FLAG_DISABLE_REMEMBER = 1 << 11, /* disable the 'remember password' checkbox */
+ E_CREDENTIALS_PROMPT_FLAG_PASSPHRASE = 1 << 12 /* We are asking a passphrase */
+} ECredentialsPromptFlags;
+
+ECredentials * e_credentials_new (void);
+ECredentials * e_credentials_new_strv (const gchar * const *strv);
+ECredentials * e_credentials_new_args (const gchar *key, ...) G_GNUC_NULL_TERMINATED;
+ECredentials * e_credentials_new_clone (const ECredentials *credentials);
+void e_credentials_free ( ECredentials *credentials);
+gchar ** e_credentials_to_strv (const ECredentials *credentials);
+void e_credentials_set ( ECredentials *credentials, const gchar *key, const gchar *value);
+gchar * e_credentials_get (const ECredentials *credentials, const gchar *key);
+const gchar * e_credentials_peek ( ECredentials *credentials, const gchar *key);
+gboolean e_credentials_equal (const ECredentials *credentials1, const ECredentials *credentials2);
+gboolean e_credentials_equal_keys(const ECredentials *credentials1, const ECredentials *credentials2, const gchar *key1, ...) G_GNUC_NULL_TERMINATED;
+gboolean e_credentials_has_key (const ECredentials *credentials, const gchar *key);
+guint e_credentials_keys_size (const ECredentials *credentials);
+GSList * e_credentials_list_keys (const ECredentials *credentials);
+void e_credentials_clear ( ECredentials *credentials);
+void e_credentials_clear_peek( ECredentials *credentials);
+
+void e_credentials_util_safe_free_string (gchar *str);
+gchar * e_credentials_util_prompt_flags_to_string (guint prompt_flags); /* bit-or of ECredentialsPromptFlags */
+guint e_credentials_util_string_to_prompt_flags (const gchar *prompt_flags_string); /* bit-or of ECredentialsPromptFlags */
+
+G_END_DECLS
+
+#endif /* E_CREDENTIALS_H */
diff --git a/libedataserver/e-data-server-util.c b/libedataserver/e-data-server-util.c
index af7deac..6085b2d 100644
--- a/libedataserver/e-data-server-util.c
+++ b/libedataserver/e-data-server-util.c
@@ -910,3 +910,87 @@ e_data_server_util_get_dbus_call_timeout (void)
{
return default_dbus_timeout;
}
+
+G_LOCK_DEFINE_STATIC (ptr_tracker);
+static GHashTable *ptr_tracker = NULL;
+
+static void
+dump_left_ptrs_cb (gpointer ptr, gpointer info, gpointer user_data)
+{
+ g_print (" %p %s%s%s", ptr, info ? "(" : "", info ? (const gchar *) info : "", info ? ")" : "");
+}
+
+static void
+dump_tracked_ptrs (gboolean is_at_exit)
+{
+ G_LOCK (ptr_tracker);
+
+ if (ptr_tracker) {
+ g_print ("\n----------------------------------------------------------\n");
+ if (g_hash_table_size (ptr_tracker) == 0) {
+ g_print (" All tracked pointers were properly removed\n");
+ } else {
+ g_print (" Left %d tracked pointers:\n", g_hash_table_size (ptr_tracker));
+ g_hash_table_foreach (ptr_tracker, dump_left_ptrs_cb, NULL);
+ }
+ g_print ("----------------------------------------------------------\n");
+ } else if (!is_at_exit) {
+ g_print ("\n----------------------------------------------------------\n");
+ g_print (" Did not track any pointers yet\n");
+ g_print ("----------------------------------------------------------\n");
+ }
+
+ G_UNLOCK (ptr_tracker);
+}
+
+static void
+dump_left_at_exit_cb (void)
+{
+ dump_tracked_ptrs (TRUE);
+
+ G_LOCK (ptr_tracker);
+ if (ptr_tracker) {
+ g_hash_table_destroy (ptr_tracker);
+ ptr_tracker = NULL;
+ }
+ G_UNLOCK (ptr_tracker);
+}
+
+void
+e_pointer_tracker_track_with_info (gpointer ptr, const gchar *info)
+{
+ g_return_if_fail (ptr != NULL);
+
+ G_LOCK (ptr_tracker);
+ if (!ptr_tracker) {
+ ptr_tracker = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+ g_atexit (dump_left_at_exit_cb);
+ }
+
+ g_hash_table_insert (ptr_tracker, ptr, g_strdup (info));
+
+ G_UNLOCK (ptr_tracker);
+}
+
+void
+e_pointer_tracker_untrack (gpointer ptr)
+{
+ g_return_if_fail (ptr != NULL);
+
+ G_LOCK (ptr_tracker);
+
+ if (!ptr_tracker)
+ g_printerr ("Pointer tracker not initialized, thus cannot remove %p\n", ptr);
+ else if (!g_hash_table_lookup (ptr_tracker, ptr))
+ g_printerr ("Pointer %p is not tracked\n", ptr);
+ else
+ g_hash_table_remove (ptr_tracker, ptr);
+
+ G_UNLOCK (ptr_tracker);
+}
+
+void
+e_pointer_tracker_dump (void)
+{
+ dump_tracked_ptrs (FALSE);
+}
diff --git a/libedataserver/e-data-server-util.h b/libedataserver/e-data-server-util.h
index 0fa514d..0a52578 100644
--- a/libedataserver/e-data-server-util.h
+++ b/libedataserver/e-data-server-util.h
@@ -73,6 +73,11 @@ gint e_data_server_util_get_dbus_call_timeout
void e_data_server_util_set_dbus_call_timeout
(gint timeout_msec);
+#define e_pointer_tracker_track(ptr) e_pointer_tracker_track_with_info (ptr, G_STRFUNC)
+void e_pointer_tracker_track_with_info (gpointer ptr, const gchar *info);
+void e_pointer_tracker_untrack (gpointer ptr);
+void e_pointer_tracker_dump (void);
+
G_END_DECLS
#endif /* E_DATA_SERVER_UTIL_H */
diff --git a/addressbook/libegdbus/e-gdbus-marshallers.list b/libedataserver/e-gdbus-marshallers.list
similarity index 55%
rename from addressbook/libegdbus/e-gdbus-marshallers.list
rename to libedataserver/e-gdbus-marshallers.list
index 46f24d4..9bf81c4 100644
--- a/addressbook/libegdbus/e-gdbus-marshallers.list
+++ b/libedataserver/e-gdbus-marshallers.list
@@ -1,10 +1,13 @@
-BOOLEAN:OBJECT,STRING
-VOID:BOXED
-VOID:STRING
-VOID:UINT,STRING
+BOOLEAN:POINTER
BOOLEAN:OBJECT
-VOID:BOOLEAN
BOOLEAN:OBJECT,BOOLEAN
-BOOLEAN:OBJECT,STRING,STRING,STRING
BOOLEAN:OBJECT,BOXED
-BOOLEAN:OBJECT,STRING,UINT
+BOOLEAN:OBJECT,STRING
+BOOLEAN:OBJECT,UINT
+VOID:UINT,BOXED
+VOID:UINT,BOXED,STRING
+VOID:UINT,BOXED,BOXED
+VOID:UINT,STRING
+
+VOID:BOXED
+VOID:STRING
diff --git a/libedataserver/e-gdbus-templates.c b/libedataserver/e-gdbus-templates.c
new file mode 100644
index 0000000..3d8b450
--- /dev/null
+++ b/libedataserver/e-gdbus-templates.c
@@ -0,0 +1,1710 @@
+/*
+ * e-gdbus-templates.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include <stdio.h>
+
+#include "e-data-server-util.h"
+#include "e-flag.h"
+#include "e-gdbus-templates.h"
+
+gboolean
+e_gdbus_signal_emission_hook_void (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name)
+{
+ GObject *object;
+ GDBusConnection *connection;
+ const gchar *path;
+
+ if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
+ return FALSE;
+
+ object = g_value_get_object (¶m_values[0]);
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ if (connection == NULL || path == NULL)
+ return FALSE;
+
+ g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, NULL, NULL);
+
+ return TRUE;
+}
+
+gboolean
+e_gdbus_signal_emission_hook_boolean (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name)
+{
+ GObject *object;
+ GDBusConnection *connection;
+ const gchar *path;
+ GVariant *params;
+ GVariant *item;
+ GVariantBuilder *builder;
+
+ if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
+ return FALSE;
+
+ object = g_value_get_object (¶m_values[0]);
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ if (connection == NULL || path == NULL)
+ return FALSE;
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ g_assert_cmpint (n_param_values - 1, ==, 1);
+ param_values++;
+ item = g_variant_new_boolean (g_value_get_boolean (param_values));
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ params = g_variant_builder_end (builder);
+ g_variant_builder_unref (builder);
+
+ g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
+
+ return TRUE;
+}
+
+gboolean
+e_gdbus_signal_emission_hook_string (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name)
+{
+ GObject *object;
+ GDBusConnection *connection;
+ const gchar *path;
+ GVariant *params;
+ GVariant *item;
+ GVariantBuilder *builder;
+
+ if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
+ return FALSE;
+
+ object = g_value_get_object (¶m_values[0]);
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ if (connection == NULL || path == NULL)
+ return FALSE;
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ g_assert_cmpint (n_param_values - 1, ==, 1);
+ param_values++;
+ item = g_variant_new_string (g_value_get_string (param_values));
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ params = g_variant_builder_end (builder);
+ g_variant_builder_unref (builder);
+
+ g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
+
+ return TRUE;
+}
+
+gboolean
+e_gdbus_signal_emission_hook_strv (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name)
+{
+ GObject *object;
+ GDBusConnection *connection;
+ const gchar *path;
+ GVariant *params;
+ GVariant *item;
+ GVariantBuilder *builder;
+ const gchar * const *arg_strv;
+
+ if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
+ return FALSE;
+
+ object = g_value_get_object (¶m_values[0]);
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ if (connection == NULL || path == NULL)
+ return FALSE;
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ g_assert_cmpint (n_param_values - 1, ==, 1);
+ param_values++;
+ arg_strv = g_value_get_boxed (param_values);
+ item = g_variant_new_strv (arg_strv, -1);
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ params = g_variant_builder_end (builder);
+ g_variant_builder_unref (builder);
+
+ g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
+
+ return TRUE;
+}
+
+gboolean
+e_gdbus_signal_emission_hook_uint (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name)
+{
+ GObject *object;
+ GDBusConnection *connection;
+ const gchar *path;
+ GVariant *params;
+ GVariant *item;
+ GVariantBuilder *builder;
+
+ if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
+ return FALSE;
+
+ object = g_value_get_object (¶m_values[0]);
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ if (connection == NULL || path == NULL)
+ return FALSE;
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ g_assert_cmpint (n_param_values - 1, ==, 1);
+ param_values++;
+ item = g_variant_new_uint32 (g_value_get_uint (param_values));
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ params = g_variant_builder_end (builder);
+ g_variant_builder_unref (builder);
+
+ g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
+
+ return TRUE;
+}
+
+gboolean
+e_gdbus_signal_emission_hook_uint_string (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name)
+{
+ GObject *object;
+ GDBusConnection *connection;
+ const gchar *path;
+ GVariant *params;
+ GVariant *item;
+ GVariantBuilder *builder;
+
+ if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
+ return FALSE;
+
+ object = g_value_get_object (¶m_values[0]);
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ if (connection == NULL || path == NULL)
+ return FALSE;
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ g_assert_cmpint (n_param_values - 1, ==, 2);
+ param_values++;
+ item = g_variant_new_uint32 (g_value_get_uint (param_values));
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ item = g_variant_new_string (g_value_get_string (param_values));
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ params = g_variant_builder_end (builder);
+ g_variant_builder_unref (builder);
+
+ g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
+
+ return TRUE;
+}
+
+gboolean
+e_gdbus_signal_emission_hook_async_void (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name)
+{
+ GObject *object;
+ GDBusConnection *connection;
+ const gchar *path;
+ GVariant *params;
+ GVariant *item;
+ GVariantBuilder *builder;
+ GError *arg_error;
+
+ if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
+ return FALSE;
+
+ object = g_value_get_object (¶m_values[0]);
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ if (connection == NULL || path == NULL)
+ return FALSE;
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ g_assert_cmpint (n_param_values - 1, ==, 2);
+ param_values++;
+ item = g_variant_new_uint32 (g_value_get_uint (param_values));
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ arg_error = g_value_get_boxed (param_values);
+ if (arg_error) {
+ gchar *dbus_error_name = g_dbus_error_encode_gerror (arg_error);
+ item = g_variant_new_string (dbus_error_name ? dbus_error_name : "");
+ g_variant_builder_add_value (builder, item);
+ item = g_variant_new_string (arg_error->message);
+ g_variant_builder_add_value (builder, item);
+ g_free (dbus_error_name);
+ } else {
+ item = g_variant_new_string ("");
+ g_variant_builder_add_value (builder, item);
+ item = g_variant_new_string ("");
+ g_variant_builder_add_value (builder, item);
+ }
+ param_values++;
+ params = g_variant_builder_end (builder);
+ g_variant_builder_unref (builder);
+
+ g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
+
+ return TRUE;
+}
+
+gboolean
+e_gdbus_signal_emission_hook_async_boolean (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name)
+{
+ GObject *object;
+ GDBusConnection *connection;
+ const gchar *path;
+ GVariant *params;
+ GVariant *item;
+ GVariantBuilder *builder;
+ GError *arg_error;
+
+ if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
+ return FALSE;
+
+ object = g_value_get_object (¶m_values[0]);
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ if (connection == NULL || path == NULL)
+ return FALSE;
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ g_assert_cmpint (n_param_values - 1, ==, 3);
+ param_values++;
+ item = g_variant_new_uint32 (g_value_get_uint (param_values));
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ arg_error = g_value_get_boxed (param_values);
+ if (arg_error) {
+ gchar *dbus_error_name = g_dbus_error_encode_gerror (arg_error);
+ item = g_variant_new_string (dbus_error_name ? dbus_error_name : "");
+ g_variant_builder_add_value (builder, item);
+ item = g_variant_new_string (arg_error->message);
+ g_variant_builder_add_value (builder, item);
+ g_free (dbus_error_name);
+ } else {
+ item = g_variant_new_string ("");
+ g_variant_builder_add_value (builder, item);
+ item = g_variant_new_string ("");
+ g_variant_builder_add_value (builder, item);
+ }
+ param_values++;
+ item = g_variant_new_boolean (g_value_get_boolean (param_values));
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ params = g_variant_builder_end (builder);
+ g_variant_builder_unref (builder);
+
+ g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
+
+ return TRUE;
+}
+
+gboolean
+e_gdbus_signal_emission_hook_async_string (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name)
+{
+ GObject *object;
+ GDBusConnection *connection;
+ const gchar *path;
+ GVariant *params;
+ GVariant *item;
+ GVariantBuilder *builder;
+ GError *arg_error;
+
+ if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
+ return FALSE;
+
+ object = g_value_get_object (¶m_values[0]);
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ if (connection == NULL || path == NULL)
+ return FALSE;
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ g_assert_cmpint (n_param_values - 1, ==, 3);
+ param_values++;
+ item = g_variant_new_uint32 (g_value_get_uint (param_values));
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ arg_error = g_value_get_boxed (param_values);
+ if (arg_error) {
+ gchar *dbus_error_name = g_dbus_error_encode_gerror (arg_error);
+ item = g_variant_new_string (dbus_error_name ? dbus_error_name : "");
+ g_variant_builder_add_value (builder, item);
+ item = g_variant_new_string (arg_error->message);
+ g_variant_builder_add_value (builder, item);
+ g_free (dbus_error_name);
+ } else {
+ item = g_variant_new_string ("");
+ g_variant_builder_add_value (builder, item);
+ item = g_variant_new_string ("");
+ g_variant_builder_add_value (builder, item);
+ }
+ param_values++;
+ item = g_variant_new_string (g_value_get_string (param_values));
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ params = g_variant_builder_end (builder);
+ g_variant_builder_unref (builder);
+
+ g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
+
+ return TRUE;
+}
+
+gboolean
+e_gdbus_signal_emission_hook_async_strv (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name)
+{
+ GObject *object;
+ GDBusConnection *connection;
+ const gchar *path;
+ GVariant *params;
+ GVariant *item;
+ GVariantBuilder *builder;
+ const GError *arg_error;
+ const gchar * const *arg_strv;
+
+ if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
+ return FALSE;
+
+ object = g_value_get_object (¶m_values[0]);
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ if (connection == NULL || path == NULL)
+ return FALSE;
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ g_assert_cmpint (n_param_values - 1, ==, 3);
+ param_values++;
+ item = g_variant_new_uint32 (g_value_get_uint (param_values));
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ arg_error = g_value_get_boxed (param_values);
+ if (arg_error) {
+ gchar *dbus_error_name = g_dbus_error_encode_gerror (arg_error);
+ item = g_variant_new_string (dbus_error_name ? dbus_error_name : "");
+ g_variant_builder_add_value (builder, item);
+ item = g_variant_new_string (arg_error->message);
+ g_variant_builder_add_value (builder, item);
+ g_free (dbus_error_name);
+ } else {
+ item = g_variant_new_string ("");
+ g_variant_builder_add_value (builder, item);
+ item = g_variant_new_string ("");
+ g_variant_builder_add_value (builder, item);
+ }
+ param_values++;
+ arg_strv = g_value_get_boxed (param_values);
+ item = g_variant_new_strv (arg_strv, -1);
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ params = g_variant_builder_end (builder);
+ g_variant_builder_unref (builder);
+
+ g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
+
+ return TRUE;
+}
+
+gboolean
+e_gdbus_signal_emission_hook_async_uint (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name)
+{
+ GObject *object;
+ GDBusConnection *connection;
+ const gchar *path;
+ GVariant *params;
+ GVariant *item;
+ GVariantBuilder *builder;
+ GError *arg_error;
+
+ if (n_param_values < 1 || !G_VALUE_HOLDS (¶m_values[0], G_TYPE_OBJECT))
+ return FALSE;
+
+ object = g_value_get_object (¶m_values[0]);
+ path = g_object_get_data (object, "gdbus-codegen-path");
+ connection = g_object_get_data (object, "gdbus-codegen-connection");
+ if (connection == NULL || path == NULL)
+ return FALSE;
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ g_assert_cmpint (n_param_values - 1, ==, 3);
+ param_values++;
+ item = g_variant_new_uint32 (g_value_get_uint (param_values));
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ arg_error = g_value_get_boxed (param_values);
+ if (arg_error) {
+ gchar *dbus_error_name = g_dbus_error_encode_gerror (arg_error);
+ item = g_variant_new_string (dbus_error_name ? dbus_error_name : "");
+ g_variant_builder_add_value (builder, item);
+ item = g_variant_new_string (arg_error->message);
+ g_variant_builder_add_value (builder, item);
+ g_free (dbus_error_name);
+ } else {
+ item = g_variant_new_string ("");
+ g_variant_builder_add_value (builder, item);
+ item = g_variant_new_string ("");
+ g_variant_builder_add_value (builder, item);
+ }
+ param_values++;
+ item = g_variant_new_uint32 (g_value_get_uint (param_values));
+ g_variant_builder_add_value (builder, item);
+ param_values++;
+ params = g_variant_builder_end (builder);
+ g_variant_builder_unref (builder);
+
+ g_dbus_connection_emit_signal (connection, NULL, path, iface_name, signal_name, params, NULL);
+
+ return TRUE;
+}
+
+void
+e_gdbus_proxy_emit_signal (GDBusProxy *proxy, GVariant *parameters, guint signal_id, guint signal_type)
+{
+ gboolean arg_boolean = FALSE;
+ const gchar *arg_const_string = NULL;
+ const gchar **arg_const_strv = NULL;
+ guint arg_uint = 0;
+
+ g_return_if_fail (proxy != NULL);
+
+ if ((signal_type & E_GDBUS_TYPE_IS_ASYNC) != 0) {
+ /* the signal is a done signal, thus opid and error name with error message are first two parameters */
+ guint arg_opid = 0;
+ const gchar *dbus_error_name = NULL, *dbus_error_message = NULL;
+ GError *arg_error = NULL;
+
+ signal_type = signal_type & (~E_GDBUS_TYPE_IS_ASYNC);
+ switch (signal_type) {
+ case E_GDBUS_TYPE_VOID:
+ g_variant_get (parameters, "(u&s&s)", &arg_opid, &dbus_error_name, &dbus_error_message);
+ break;
+ case E_GDBUS_TYPE_BOOLEAN:
+ g_variant_get (parameters, "(u&s&sb)", &arg_opid, &dbus_error_name, &dbus_error_message, &arg_boolean);
+ break;
+ case E_GDBUS_TYPE_STRING:
+ g_variant_get (parameters, "(u&s&s&s)", &arg_opid, &dbus_error_name, &dbus_error_message, &arg_const_string);
+ break;
+ case E_GDBUS_TYPE_STRV:
+ /* array is newly allocated, but items are gvariant's */
+ g_variant_get (parameters, "(u&s&s^a&s)", &arg_opid, &dbus_error_name, &dbus_error_message, &arg_const_strv);
+ break;
+ case E_GDBUS_TYPE_UINT:
+ g_variant_get (parameters, "(u&s&su)", &arg_opid, &dbus_error_name, &dbus_error_message, &arg_uint);
+ break;
+ default:
+ g_warning ("%s: Unknown E_GDBUS_TYPE %x", G_STRFUNC, signal_type);
+ return;
+ }
+
+ if (dbus_error_name && *dbus_error_name && dbus_error_message)
+ arg_error = g_dbus_error_new_for_dbus_error (dbus_error_name, dbus_error_message);
+
+ switch (signal_type) {
+ case E_GDBUS_TYPE_VOID:
+ g_signal_emit (proxy, signal_id, 0, arg_opid, arg_error);
+ break;
+ case E_GDBUS_TYPE_BOOLEAN:
+ g_signal_emit (proxy, signal_id, 0, arg_opid, arg_error, arg_boolean);
+ break;
+ case E_GDBUS_TYPE_STRING:
+ g_signal_emit (proxy, signal_id, 0, arg_opid, arg_error, arg_const_string);
+ break;
+ case E_GDBUS_TYPE_STRV:
+ g_signal_emit (proxy, signal_id, 0, arg_opid, arg_error, arg_const_strv);
+ g_free (arg_const_strv);
+ break;
+ case E_GDBUS_TYPE_UINT:
+ g_signal_emit (proxy, signal_id, 0, arg_opid, arg_error, arg_uint);
+ break;
+ default:
+ g_warning ("%s: Unknown E_GDBUS_TYPE %x", G_STRFUNC, signal_type);
+ break;
+ }
+
+ if (arg_error)
+ g_error_free (arg_error);
+ } else {
+ switch (signal_type) {
+ case E_GDBUS_TYPE_VOID:
+ g_signal_emit (proxy, signal_id, 0);
+ break;
+ case E_GDBUS_TYPE_BOOLEAN:
+ g_variant_get (parameters, "(b)", &arg_boolean);
+ g_signal_emit (proxy, signal_id, 0, arg_boolean);
+ break;
+ case E_GDBUS_TYPE_STRING:
+ g_variant_get (parameters, "(&s)", &arg_const_string);
+ g_signal_emit (proxy, signal_id, 0, arg_const_string);
+ break;
+ case E_GDBUS_TYPE_STRV:
+ /* array is newly allocated, but items are gvariant's */
+ g_variant_get (parameters, "(^a&s)", &arg_const_strv);
+ g_signal_emit (proxy, signal_id, 0, arg_const_strv);
+ g_free (arg_const_strv);
+ break;
+ case E_GDBUS_TYPE_UINT:
+ g_variant_get (parameters, "(u)", &arg_uint);
+ g_signal_emit (proxy, signal_id, 0, arg_uint);
+ break;
+ case E_GDBUS_TYPE_UINT | E_GDBUS_TYPE_STRING:
+ g_variant_get (parameters, "(u&s)", &arg_uint, &arg_const_string);
+ g_signal_emit (proxy, signal_id, 0, arg_uint, arg_const_string);
+ break;
+ default:
+ g_warning ("%s: Unknown E_GDBUS_TYPE %x", G_STRFUNC, signal_type);
+ break;
+ }
+ }
+}
+
+void
+e_gdbus_stub_handle_method_call (GObject *stub_object, GDBusMethodInvocation *invocation, GVariant *parameters, const gchar *method_name, guint method_id, guint method_type)
+{
+ gboolean handled = FALSE;
+ gboolean arg_boolean = FALSE;
+ const gchar *arg_const_string = NULL;
+ const gchar ** arg_const_strv = NULL;
+ guint arg_uint = 0;
+
+ g_return_if_fail (stub_object != NULL);
+ g_return_if_fail (method_name != NULL);
+
+ switch (method_type & (~E_GDBUS_TYPE_IS_ASYNC)) {
+ case E_GDBUS_TYPE_VOID:
+ g_signal_emit (stub_object, method_id, 0, invocation, &handled);
+ break;
+ case E_GDBUS_TYPE_BOOLEAN:
+ g_variant_get (parameters, "(b)", &arg_boolean);
+ g_signal_emit (stub_object, method_id, 0, invocation, arg_boolean, &handled);
+ break;
+ case E_GDBUS_TYPE_STRING:
+ g_variant_get (parameters, "(&s)", &arg_const_string);
+ g_signal_emit (stub_object, method_id, 0, invocation, arg_const_string, &handled);
+ break;
+ case E_GDBUS_TYPE_STRV:
+ /* array is newly allocated, but items are gvariant's */
+ g_variant_get (parameters, "(^a&s)", &arg_const_strv);
+ g_signal_emit (stub_object, method_id, 0, invocation, arg_const_strv, &handled);
+ g_free (arg_const_strv);
+ break;
+ case E_GDBUS_TYPE_UINT:
+ g_variant_get (parameters, "(u)", &arg_uint);
+ g_signal_emit (stub_object, method_id, 0, invocation, arg_uint, &handled);
+ break;
+ default:
+ g_warning ("%s: Unknown E_GDBUS_TYPE %x", G_STRFUNC, method_type);
+ break;
+ }
+
+ if (!handled)
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "Method `%s' is not implemented", method_name);
+}
+
+G_DEFINE_INTERFACE (EGdbusAsyncOpKeeper, e_gdbus_async_op_keeper, G_TYPE_OBJECT)
+
+static void
+e_gdbus_async_op_keeper_default_init (EGdbusAsyncOpKeeperInterface *iface)
+{
+}
+
+/* Created hash table of pending async operations. This can be freed
+ with g_hash_table_destroy() in dispose. Interface asks for this
+ ponter by call of e_gdbus_async_op_keeper_create_pending_ops().
+*/
+GHashTable *
+e_gdbus_async_op_keeper_create_pending_ops (EGdbusAsyncOpKeeper *object)
+{
+ g_return_val_if_fail (object != NULL, NULL);
+ g_return_val_if_fail (E_IS_GDBUS_ASYNC_OP_KEEPER (object), NULL);
+
+ return g_hash_table_new (g_direct_hash, g_direct_equal);
+}
+
+/* Returns hash table of pending async operations previously created
+ by e_gdbus_async_op_keeper_create_pending_ops().
+*/
+GHashTable *
+e_gdbus_async_op_keeper_get_pending_ops (EGdbusAsyncOpKeeper *object)
+{
+ EGdbusAsyncOpKeeperInterface *iface;
+
+ g_return_val_if_fail (E_IS_GDBUS_ASYNC_OP_KEEPER (object), 0);
+
+ iface = E_GDBUS_ASYNC_OP_KEEPER_GET_IFACE (object);
+ g_return_val_if_fail (iface->get_pending_ops != NULL, 0);
+
+ return iface->get_pending_ops (object);
+}
+
+/* synchronously cancels one operation - sends a request from client to the server */
+gboolean
+e_gdbus_async_op_keeper_cancel_op_sync (EGdbusAsyncOpKeeper *object, guint in_opid, GCancellable *cancellable, GError **error)
+{
+ EGdbusAsyncOpKeeperInterface *iface;
+
+ g_return_val_if_fail (E_IS_GDBUS_ASYNC_OP_KEEPER (object), FALSE);
+
+ iface = E_GDBUS_ASYNC_OP_KEEPER_GET_IFACE (object);
+ g_return_val_if_fail (iface->cancel_op_sync != NULL, FALSE);
+
+ return iface->cancel_op_sync (object, in_opid, cancellable, error);
+}
+
+/* Used to finish asynchronous GDBus call - this might be done in the callback
+ as soon as possible; method returns to a caller operation ID which was started */
+void
+e_gdbus_complete_async_method (gpointer object, GDBusMethodInvocation *invocation, guint opid)
+{
+ g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", opid));
+}
+
+/* Used to finish synchronous GDBus call - this might be done in the callback
+ as soon as possible */
+void
+e_gdbus_complete_sync_method_void (gpointer object, GDBusMethodInvocation *invocation, const GError *error)
+{
+ if (error)
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ else
+ g_dbus_method_invocation_return_value (invocation, NULL);
+}
+
+void
+e_gdbus_complete_sync_method_boolean (gpointer object, GDBusMethodInvocation *invocation, gboolean out_boolean, const GError *error)
+{
+ if (error)
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ else
+ g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", out_boolean));
+}
+
+void
+e_gdbus_complete_sync_method_string (gpointer object, GDBusMethodInvocation *invocation, const gchar *out_string, const GError *error)
+{
+ if (error)
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ else
+ g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", out_string));
+}
+
+void
+e_gdbus_complete_sync_method_strv (gpointer object, GDBusMethodInvocation *invocation, const gchar * const *out_strv, const GError *error)
+{
+ if (error)
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ else
+ g_dbus_method_invocation_return_value (invocation, g_variant_new ("(^as)", out_strv));
+}
+
+void
+e_gdbus_complete_sync_method_uint (gpointer object, GDBusMethodInvocation *invocation, guint out_uint, const GError *error)
+{
+ if (error)
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ else
+ g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", out_uint));
+}
+
+typedef struct _AsyncOpData
+{
+ EGdbusAsyncOpKeeper *proxy;
+ guint opid;
+
+ GCancellable *cancellable;
+ gulong cancel_id;
+
+ gpointer async_source_tag;
+ GAsyncReadyCallback async_callback;
+ gpointer async_user_data;
+
+ guint result_type; /* any of E_GDBUS_TYPE_... except of E_GDBUS_TYPE_IS_ASYNC */
+ union {
+ gboolean out_boolean;
+ gchar *out_string;
+ gchar ** out_strv;
+ guint out_uint;
+ } result;
+} AsyncOpData;
+
+
+static void
+async_op_data_free (AsyncOpData *op_data)
+{
+ GHashTable *pending_ops;
+
+ g_return_if_fail (op_data != NULL);
+
+ if (op_data->cancellable) {
+ if (op_data->cancel_id)
+ g_cancellable_disconnect (op_data->cancellable, op_data->cancel_id);
+ g_object_unref (op_data->cancellable);
+ }
+
+ pending_ops = e_gdbus_async_op_keeper_get_pending_ops (E_GDBUS_ASYNC_OP_KEEPER (op_data->proxy));
+ if (pending_ops)
+ g_hash_table_remove (pending_ops, GUINT_TO_POINTER (op_data->opid));
+ g_object_unref (op_data->proxy);
+
+ switch (op_data->result_type) {
+ case E_GDBUS_TYPE_STRING:
+ if (op_data->result.out_string)
+ g_free (op_data->result.out_string);
+ break;
+ case E_GDBUS_TYPE_STRV:
+ if (op_data->result.out_strv)
+ g_strfreev (op_data->result.out_strv);
+ break;
+ }
+
+ g_free (op_data);
+
+ g_return_if_fail (pending_ops != NULL);
+}
+
+static void
+async_op_complete (AsyncOpData *op_data, const GError *error, gboolean in_idle)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_if_fail (op_data != NULL);
+
+ simple = g_simple_async_result_new (G_OBJECT (op_data->proxy), op_data->async_callback, op_data->async_user_data, op_data->async_source_tag);
+ g_simple_async_result_set_op_res_gpointer (simple, op_data, (GDestroyNotify) async_op_data_free);
+ if (error)
+ g_simple_async_result_set_from_error (simple, error);
+
+ if (in_idle)
+ g_simple_async_result_complete_in_idle (simple);
+ else
+ g_simple_async_result_complete (simple);
+
+ g_object_unref (simple);
+}
+
+static void
+gdbus_op_cancelled_cb (GCancellable *cancellable, AsyncOpData *op_data)
+{
+ GError *call_error = NULL;
+
+ g_return_if_fail (op_data != NULL);
+
+ if (!e_gdbus_async_op_keeper_cancel_op_sync (op_data->proxy, op_data->opid, NULL, &call_error)) {
+ /* only if failed, because otherwise will receive cancelled signal from the server */
+ GError *error = NULL;
+
+ g_return_if_fail (g_cancellable_set_error_if_cancelled (cancellable, &error));
+
+ async_op_complete (op_data, error, TRUE);
+ g_error_free (error);
+ }
+
+ if (call_error) {
+ g_debug ("%s: Failed to cancel operation: %s\n", G_STRFUNC, call_error->message);
+ g_error_free (call_error);
+ }
+}
+
+static void
+gdbus_async_call_opid_ready_cb (GObject *source_proxy, GAsyncResult *result, gpointer user_data)
+{
+ GVariant *_result;
+ GError *error = NULL;
+ AsyncOpData *op_data = user_data;
+
+ _result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_proxy), result, &error);
+
+ if (_result != NULL && !error) {
+ EGdbusAsyncOpKeeper *op_keeper = E_GDBUS_ASYNC_OP_KEEPER (source_proxy);
+ GHashTable *pending_ops;
+ gboolean add_pending = TRUE;
+
+ g_return_if_fail (op_keeper != NULL);
+
+ pending_ops = e_gdbus_async_op_keeper_get_pending_ops (op_keeper);
+ g_return_if_fail (pending_ops != NULL);
+
+ g_variant_get (_result, "(u)", &op_data->opid);
+ g_variant_unref (_result);
+
+ if (op_data->cancellable && !g_cancellable_set_error_if_cancelled (op_data->cancellable, &error))
+ op_data->cancel_id = g_cancellable_connect (op_data->cancellable, G_CALLBACK (gdbus_op_cancelled_cb), op_data, NULL);
+ else
+ add_pending = op_data->cancellable == NULL;
+
+ /* add to pending ops, waiting for associated 'done' signal */
+ if (add_pending)
+ g_hash_table_insert (pending_ops, GUINT_TO_POINTER (op_data->opid), op_data);
+ } else if (_result) {
+ g_variant_unref (_result);
+ }
+
+ if (error) {
+ async_op_complete (op_data, error, FALSE);
+ g_error_free (error);
+ }
+}
+
+static gchar **
+copy_strv (const gchar * const *strv)
+{
+ GPtrArray *array;
+ gint ii;
+
+ array = g_ptr_array_sized_new (g_strv_length ((gchar **) strv) + 1);
+
+ for (ii = 0; strv[ii]; ii++) {
+ g_ptr_array_add (array, g_strdup (strv[ii]));
+ }
+
+ /* NULL-terminated */
+ g_ptr_array_add (array, NULL);
+
+ return (gchar **) g_ptr_array_free (array, FALSE);
+}
+
+static void
+gdbus_proxy_async_method_done (guint e_gdbus_type, gconstpointer out_value, EGdbusAsyncOpKeeper *object, guint arg_opid, const GError *error)
+{
+ AsyncOpData *op_data;
+ GHashTable *pending_ops;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (E_IS_GDBUS_ASYNC_OP_KEEPER (object));
+
+ pending_ops = e_gdbus_async_op_keeper_get_pending_ops (object);
+ g_return_if_fail (pending_ops != NULL);
+
+ op_data = g_hash_table_lookup (pending_ops, GUINT_TO_POINTER (arg_opid));
+ if (!op_data) {
+ g_debug ("%s: Operation %d gone before got done signal for it", G_STRFUNC, arg_opid);
+ return;
+ }
+
+ if (out_value) {
+ op_data->result_type = e_gdbus_type;
+
+ switch (e_gdbus_type) {
+ case E_GDBUS_TYPE_VOID:
+ break;
+ case E_GDBUS_TYPE_BOOLEAN:
+ op_data->result.out_boolean = * ((const gboolean *)out_value);
+ break;
+ case E_GDBUS_TYPE_STRING:
+ op_data->result.out_string = g_strdup ((const gchar *) out_value);
+ break;
+ case E_GDBUS_TYPE_STRV:
+ op_data->result.out_strv = copy_strv ((const gchar * const *) out_value);
+ break;
+ case E_GDBUS_TYPE_UINT:
+ op_data->result.out_uint = * ((const guint *) out_value);
+ break;
+ default:
+ g_warning ("%s: Unknown E_GDBUS_TYPE %x", G_STRFUNC, e_gdbus_type);
+ break;
+ }
+ }
+
+ async_op_complete (op_data, error, TRUE);
+}
+
+void
+e_gdbus_proxy_async_method_done_void (EGdbusAsyncOpKeeper *proxy, guint arg_opid, const GError *error)
+{
+ gdbus_proxy_async_method_done (E_GDBUS_TYPE_VOID, NULL, proxy, arg_opid, error);
+}
+
+void
+e_gdbus_proxy_async_method_done_boolean (EGdbusAsyncOpKeeper *proxy, guint arg_opid, const GError *error, gboolean out_boolean)
+{
+ gdbus_proxy_async_method_done (E_GDBUS_TYPE_BOOLEAN, &out_boolean, proxy, arg_opid, error);
+}
+
+/* takes ownership of the out parameter */
+void
+e_gdbus_proxy_async_method_done_string (EGdbusAsyncOpKeeper *proxy, guint arg_opid, const GError *error, const gchar *out_string)
+{
+ gdbus_proxy_async_method_done (E_GDBUS_TYPE_STRING, out_string, proxy, arg_opid, error);
+}
+
+/* takes ownership of the out parameter */
+void
+e_gdbus_proxy_async_method_done_strv (EGdbusAsyncOpKeeper *proxy, guint arg_opid, const GError *error, const gchar * const *out_strv)
+{
+ gdbus_proxy_async_method_done (E_GDBUS_TYPE_STRV, out_strv, proxy, arg_opid, error);
+}
+
+void
+e_gdbus_proxy_async_method_done_uint (EGdbusAsyncOpKeeper *proxy, guint arg_opid, const GError *error, guint out_uint)
+{
+ gdbus_proxy_async_method_done (E_GDBUS_TYPE_UINT, &out_uint, proxy, arg_opid, error);
+}
+
+/* takes ownership of _params */
+static void
+gdbus_proxy_call_with_params (GVariant *_params, const gchar *method_name, gpointer source_tag, EGdbusAsyncOpKeeper *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ AsyncOpData *op_data;
+
+ op_data = g_new0 (AsyncOpData, 1);
+ op_data->proxy = g_object_ref (proxy);
+ op_data->opid = 0;
+ op_data->async_source_tag = source_tag;
+ op_data->async_callback = callback;
+ op_data->async_user_data = user_data;
+ op_data->cancellable = cancellable;
+ if (op_data->cancellable)
+ g_object_ref (op_data->cancellable);
+
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy), method_name, _params, G_DBUS_CALL_FLAGS_NONE, e_data_server_util_get_dbus_call_timeout (), cancellable, gdbus_async_call_opid_ready_cb, op_data);
+}
+
+void
+e_gdbus_proxy_call_void (const gchar *method_name, gpointer source_tag, EGdbusAsyncOpKeeper *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ gdbus_proxy_call_with_params (NULL, method_name, source_tag, proxy, cancellable, callback, user_data);
+}
+
+void
+e_gdbus_proxy_call_boolean (const gchar *method_name, gpointer source_tag, EGdbusAsyncOpKeeper *proxy, gboolean in_boolean, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ GVariant *_params;
+
+ _params = g_variant_new ("(b)", in_boolean);
+
+ gdbus_proxy_call_with_params (_params, method_name, source_tag, proxy, cancellable, callback, user_data);
+}
+
+void
+e_gdbus_proxy_call_string (const gchar *method_name, gpointer source_tag, EGdbusAsyncOpKeeper *proxy, const gchar *in_string, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ GVariant *_params;
+
+ _params = g_variant_new ("(s)", in_string);
+
+ gdbus_proxy_call_with_params (_params, method_name, source_tag, proxy, cancellable, callback, user_data);
+}
+
+void
+e_gdbus_proxy_call_strv (const gchar *method_name, gpointer source_tag, EGdbusAsyncOpKeeper *proxy, const gchar * const *in_strv, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ GVariant *_params;
+
+ _params = g_variant_new ("(^as)", in_strv);
+
+ gdbus_proxy_call_with_params (_params, method_name, source_tag, proxy, cancellable, callback, user_data);
+}
+
+void
+e_gdbus_proxy_call_uint (const gchar *method_name, gpointer source_tag, EGdbusAsyncOpKeeper *proxy, guint in_uint, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ GVariant *_params;
+
+ _params = g_variant_new ("(u)", in_uint);
+
+ gdbus_proxy_call_with_params (_params, method_name, source_tag, proxy, cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_proxy_finish_call_void (EGdbusAsyncOpKeeper *proxy, GAsyncResult *result, GError **error, gpointer source_tag)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), source_tag), FALSE);
+
+ return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
+}
+
+gboolean
+e_gdbus_proxy_finish_call_boolean (EGdbusAsyncOpKeeper *proxy, GAsyncResult *result, gboolean *out_boolean, GError **error, gpointer source_tag)
+{
+ AsyncOpData *op_data;
+
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), source_tag), FALSE);
+ g_return_val_if_fail (out_boolean != NULL, FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+
+ op_data = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ g_return_val_if_fail (op_data != NULL, FALSE);
+ g_return_val_if_fail (op_data->result_type == E_GDBUS_TYPE_BOOLEAN, FALSE);
+
+ *out_boolean = op_data->result.out_boolean;
+
+ return TRUE;
+}
+
+/* caller takes ownership and responsibility for freeing the out parameter */
+gboolean
+e_gdbus_proxy_finish_call_string (EGdbusAsyncOpKeeper *proxy, GAsyncResult *result, gchar **out_string, GError **error, gpointer source_tag)
+{
+ AsyncOpData *op_data;
+
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), source_tag), FALSE);
+ g_return_val_if_fail (out_string != NULL, FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+
+ op_data = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ g_return_val_if_fail (op_data != NULL, FALSE);
+ g_return_val_if_fail (op_data->result_type == E_GDBUS_TYPE_STRING, FALSE);
+
+ *out_string = op_data->result.out_string;
+ op_data->result.out_string = NULL;
+
+ return TRUE;
+}
+
+/* caller takes ownership and responsibility for freeing the out parameter */
+gboolean
+e_gdbus_proxy_finish_call_strv (EGdbusAsyncOpKeeper *proxy, GAsyncResult *result, gchar ***out_strv, GError **error, gpointer source_tag)
+{
+ AsyncOpData *op_data;
+
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), source_tag), FALSE);
+ g_return_val_if_fail (out_strv != NULL, FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+
+ op_data = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ g_return_val_if_fail (op_data != NULL, FALSE);
+ g_return_val_if_fail (op_data->result_type == E_GDBUS_TYPE_STRV, FALSE);
+
+ *out_strv = op_data->result.out_strv;
+ op_data->result.out_strv = NULL;
+
+ return TRUE;
+}
+
+gboolean
+e_gdbus_proxy_finish_call_uint (EGdbusAsyncOpKeeper *proxy, GAsyncResult *result, guint *out_uint, GError **error, gpointer source_tag)
+{
+ AsyncOpData *op_data;
+
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), source_tag), FALSE);
+ g_return_val_if_fail (out_uint != NULL, FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+
+ op_data = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ g_return_val_if_fail (op_data != NULL, FALSE);
+ g_return_val_if_fail (op_data->result_type == E_GDBUS_TYPE_STRING, FALSE);
+
+ *out_uint = op_data->result.out_uint;
+
+ return TRUE;
+}
+
+typedef struct _SyncOpData
+{
+ EFlag *flag;
+ GError **error;
+
+ guint out_type; /* one of E_GDBUS_TYPE_... except of E_GDBUS_TYPE_IS_ASYNC */
+ union {
+ gboolean *out_boolean;
+ gchar **out_string;
+ gchar ***out_strv;
+ guint *out_uint;
+ } out_arg;
+
+ union {
+ EGdbusCallFinishVoid finish_void;
+ EGdbusCallFinishBoolean finish_boolean;
+ EGdbusCallFinishString finish_string;
+ EGdbusCallFinishStrv finish_strv;
+ EGdbusCallFinishUint finish_uint;
+ } finish_func;
+
+ gboolean finish_result;
+} SyncOpData;
+
+static void
+gdbus_proxy_sync_ready_cb (GObject *proxy, GAsyncResult *result, gpointer user_data)
+{
+ SyncOpData *sync_data = user_data;
+
+ g_return_if_fail (sync_data != NULL);
+ g_return_if_fail (sync_data->flag != NULL);
+
+ switch (sync_data->out_type) {
+ case E_GDBUS_TYPE_VOID:
+ g_return_if_fail (sync_data->finish_func.finish_void != NULL);
+ sync_data->finish_result = sync_data->finish_func.finish_void (G_DBUS_PROXY (proxy), result, sync_data->error);
+ break;
+ case E_GDBUS_TYPE_BOOLEAN:
+ g_return_if_fail (sync_data->finish_func.finish_boolean != NULL);
+ sync_data->finish_result = sync_data->finish_func.finish_boolean (G_DBUS_PROXY (proxy), result, sync_data->out_arg.out_boolean, sync_data->error);
+ break;
+ case E_GDBUS_TYPE_STRING:
+ g_return_if_fail (sync_data->finish_func.finish_string != NULL);
+ sync_data->finish_result = sync_data->finish_func.finish_string (G_DBUS_PROXY (proxy), result, sync_data->out_arg.out_string, sync_data->error);
+ break;
+ case E_GDBUS_TYPE_STRV:
+ g_return_if_fail (sync_data->finish_func.finish_strv != NULL);
+ sync_data->finish_result = sync_data->finish_func.finish_strv (G_DBUS_PROXY (proxy), result, sync_data->out_arg.out_strv, sync_data->error);
+ break;
+ case E_GDBUS_TYPE_UINT:
+ g_return_if_fail (sync_data->finish_func.finish_uint != NULL);
+ sync_data->finish_result = sync_data->finish_func.finish_uint (G_DBUS_PROXY (proxy), result, sync_data->out_arg.out_uint, sync_data->error);
+ break;
+ default:
+ g_warning ("%s: Unknown 'out' E_GDBUS_TYPE %x", G_STRFUNC, sync_data->out_type);
+ sync_data->finish_result = FALSE;
+ }
+
+ e_flag_set (sync_data->flag);
+}
+
+static gboolean
+gdbus_proxy_call_sync (GDBusProxy *proxy, GCancellable *cancellable, GError **error, gpointer start_func, gpointer finish_func, guint in_type, gconstpointer in_value, guint out_type, gpointer out_value)
+{
+ SyncOpData sync_data = { 0 };
+
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+
+ switch (out_type) {
+ case E_GDBUS_TYPE_VOID:
+ sync_data.finish_func.finish_void = finish_func;
+ break;
+ case E_GDBUS_TYPE_BOOLEAN:
+ sync_data.out_arg.out_boolean = out_value;
+ sync_data.finish_func.finish_boolean = finish_func;
+ break;
+ case E_GDBUS_TYPE_STRING:
+ sync_data.out_arg.out_string = out_value;
+ sync_data.finish_func.finish_string = finish_func;
+ break;
+ case E_GDBUS_TYPE_STRV:
+ sync_data.out_arg.out_strv = out_value;
+ sync_data.finish_func.finish_strv = finish_func;
+ break;
+ case E_GDBUS_TYPE_UINT:
+ sync_data.out_arg.out_uint = out_value;
+ sync_data.finish_func.finish_uint = finish_func;
+ break;
+ default:
+ g_warning ("%s: Unknown 'out' E_GDBUS_TYPE %x", G_STRFUNC, out_type);
+ return FALSE;
+ }
+
+ sync_data.flag = e_flag_new ();
+ sync_data.error = error;
+ sync_data.out_type = out_type;
+
+ switch (in_type) {
+ case E_GDBUS_TYPE_VOID: {
+ EGdbusCallStartVoid start = start_func;
+ start (proxy, cancellable, gdbus_proxy_sync_ready_cb, &sync_data);
+ } break;
+ case E_GDBUS_TYPE_BOOLEAN: {
+ EGdbusCallStartBoolean start = start_func;
+ start (proxy, * ((gboolean *) in_value), cancellable, gdbus_proxy_sync_ready_cb, &sync_data);
+ } break;
+ case E_GDBUS_TYPE_STRING: {
+ EGdbusCallStartString start = start_func;
+ start (proxy, (const gchar *) in_value, cancellable, gdbus_proxy_sync_ready_cb, &sync_data);
+ } break;
+ case E_GDBUS_TYPE_STRV: {
+ EGdbusCallStartStrv start = start_func;
+ start (proxy, (const gchar * const *) in_value, cancellable, gdbus_proxy_sync_ready_cb, &sync_data);
+ } break;
+ case E_GDBUS_TYPE_UINT: {
+ EGdbusCallStartUint start = start_func;
+ start (proxy, * ((guint *) in_value), cancellable, gdbus_proxy_sync_ready_cb, &sync_data);
+ } break;
+ default:
+ g_warning ("%s: Unknown 'in' E_GDBUS_TYPE %x", G_STRFUNC, in_type);
+ e_flag_free (sync_data.flag);
+ return FALSE;
+ }
+
+ /* check if called from the main thread */
+ if (g_main_context_is_owner (g_main_context_default ())
+ || g_main_context_default () == g_main_context_get_thread_default ()
+ || !g_main_context_get_thread_default ()) {
+ /* Might not be the best thing here, but as the async operation
+ is divided into two-steps process, invoking the method and
+ waiting for its "done" signal, then if the sync method is called
+ from the main thread, then there is probably no other option.
+ */
+ while (!e_flag_is_set (sync_data.flag)) {
+ g_usleep (250000);
+ g_main_context_iteration (NULL, FALSE);
+ }
+ } else {
+ /* is called in a dedicated thread */
+ e_flag_wait (sync_data.flag);
+ }
+ e_flag_free (sync_data.flag);
+
+ return sync_data.finish_result;
+}
+
+gboolean
+e_gdbus_proxy_call_sync_void__void (GDBusProxy *proxy, GCancellable *cancellable, GError **error, EGdbusCallStartVoid start_func, EGdbusCallFinishVoid finish_func)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+
+ return gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_VOID, NULL, E_GDBUS_TYPE_VOID, NULL);
+}
+
+gboolean
+e_gdbus_proxy_call_sync_void__boolean (GDBusProxy *proxy, gboolean *out_boolean, GCancellable *cancellable, GError **error, EGdbusCallStartVoid start_func, EGdbusCallFinishBoolean finish_func)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+ g_return_val_if_fail (out_boolean != NULL, FALSE);
+
+ return gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_VOID, NULL, E_GDBUS_TYPE_BOOLEAN, out_boolean);
+}
+
+gboolean
+e_gdbus_proxy_call_sync_void__string (GDBusProxy *proxy, gchar **out_string, GCancellable *cancellable, GError **error, EGdbusCallStartVoid start_func, EGdbusCallFinishString finish_func)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+ g_return_val_if_fail (out_string != NULL, FALSE);
+
+ return gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_VOID, NULL, E_GDBUS_TYPE_STRING, out_string);
+}
+
+gboolean
+e_gdbus_proxy_call_sync_void__strv (GDBusProxy *proxy, gchar ***out_strv, GCancellable *cancellable, GError **error, EGdbusCallStartVoid start_func, EGdbusCallFinishStrv finish_func)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+ g_return_val_if_fail (out_strv != NULL, FALSE);
+
+ return gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_VOID, NULL, E_GDBUS_TYPE_STRV, out_strv);
+}
+
+gboolean
+e_gdbus_proxy_call_sync_void__uint (GDBusProxy *proxy, guint *out_uint, GCancellable *cancellable, GError **error, EGdbusCallStartVoid start_func, EGdbusCallFinishUint finish_func)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+ g_return_val_if_fail (out_uint != NULL, FALSE);
+
+ return gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_VOID, NULL, E_GDBUS_TYPE_UINT, out_uint);
+}
+
+gboolean
+e_gdbus_proxy_call_sync_boolean__void (GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GError **error, EGdbusCallStartBoolean start_func, EGdbusCallFinishVoid finish_func)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+
+ return gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_BOOLEAN, &in_boolean, E_GDBUS_TYPE_VOID, NULL);
+}
+
+gboolean
+e_gdbus_proxy_call_sync_string__void (GDBusProxy *proxy, const gchar *in_string, GCancellable *cancellable, GError **error, EGdbusCallStartString start_func, EGdbusCallFinishVoid finish_func)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+ g_return_val_if_fail (in_string != NULL, FALSE);
+
+ return gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_STRING, in_string, E_GDBUS_TYPE_VOID, NULL);
+}
+
+gboolean
+e_gdbus_proxy_call_sync_strv__void (GDBusProxy *proxy, const gchar * const *in_strv, GCancellable *cancellable, GError **error, EGdbusCallStartStrv start_func, EGdbusCallFinishVoid finish_func)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+ g_return_val_if_fail (in_strv != NULL, FALSE);
+
+ return gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_STRV, in_strv, E_GDBUS_TYPE_VOID, NULL);
+}
+
+gboolean
+e_gdbus_proxy_call_sync_uint__void (GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GError **error, EGdbusCallStartUint start_func, EGdbusCallFinishVoid finish_func)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+
+ return gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_UINT, &in_uint, E_GDBUS_TYPE_VOID, NULL);
+}
+
+gboolean
+e_gdbus_proxy_call_sync_string__string (GDBusProxy *proxy, const gchar *in_string, gchar **out_string, GCancellable *cancellable, GError **error, EGdbusCallStartString start_func, EGdbusCallFinishString finish_func)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+ g_return_val_if_fail (in_string != NULL, FALSE);
+ g_return_val_if_fail (out_string != NULL, FALSE);
+
+ return gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_STRING, in_string, E_GDBUS_TYPE_STRING, out_string);
+}
+
+gboolean
+e_gdbus_proxy_call_sync_string__strv (GDBusProxy *proxy, const gchar *in_string, gchar ***out_strv, GCancellable *cancellable, GError **error, EGdbusCallStartString start_func, EGdbusCallFinishStrv finish_func)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+ g_return_val_if_fail (in_string != NULL, FALSE);
+ g_return_val_if_fail (out_strv != NULL, FALSE);
+
+ return gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_STRING, in_string, E_GDBUS_TYPE_STRV, out_strv);
+}
+
+gboolean
+e_gdbus_proxy_call_sync_strv__string (GDBusProxy *proxy, const gchar * const *in_strv, gchar **out_string, GCancellable *cancellable, GError **error, EGdbusCallStartStrv start_func, EGdbusCallFinishString finish_func)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+ g_return_val_if_fail (in_strv != NULL, FALSE);
+ g_return_val_if_fail (out_string != NULL, FALSE);
+
+ return gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_STRV, in_strv, E_GDBUS_TYPE_STRING, out_string);
+}
+
+gboolean
+e_gdbus_proxy_call_sync_strv__strv (GDBusProxy *proxy, const gchar * const *in_strv, gchar ***out_strv, GCancellable *cancellable, GError **error, EGdbusCallStartStrv start_func, EGdbusCallFinishStrv finish_func)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (start_func != NULL, FALSE);
+ g_return_val_if_fail (finish_func != NULL, FALSE);
+ g_return_val_if_fail (in_strv != NULL, FALSE);
+ g_return_val_if_fail (out_strv != NULL, FALSE);
+
+ return gdbus_proxy_call_sync (proxy, cancellable, error, start_func, finish_func, E_GDBUS_TYPE_STRV, in_strv, E_GDBUS_TYPE_STRV, out_strv);
+}
+
+static void
+proxy_method_call (const gchar *method_name, guint param_type, gconstpointer param_value, GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ GVariant *params = NULL;
+ GVariant *item;
+ GVariantBuilder *builder = NULL;
+
+ g_return_if_fail (method_name != NULL);
+ g_return_if_fail (proxy != NULL);
+ g_return_if_fail (G_IS_DBUS_PROXY (proxy));
+ if (param_type != E_GDBUS_TYPE_VOID)
+ g_return_if_fail (param_value != NULL);
+
+ switch (param_type) {
+ case E_GDBUS_TYPE_VOID:
+ break;
+ case E_GDBUS_TYPE_BOOLEAN:
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ item = g_variant_new_boolean (* ((const gboolean *) param_value));
+ g_variant_builder_add_value (builder, item);
+ break;
+ case E_GDBUS_TYPE_STRING:
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ item = g_variant_new_string ((const gchar *) param_value);
+ g_variant_builder_add_value (builder, item);
+ break;
+ case E_GDBUS_TYPE_STRV:
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ item = g_variant_new_strv ((const gchar * const *) param_value, -1);
+ g_variant_builder_add_value (builder, item);
+ break;
+ case E_GDBUS_TYPE_UINT:
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ item = g_variant_new_uint32 (* ((const guint *) param_value));
+ g_variant_builder_add_value (builder, item);
+ break;
+ default:
+ g_warning ("%s: Unknown 'param' E_GDBUS_TYPE %x", G_STRFUNC, param_type);
+ return;
+ }
+
+ if (builder != NULL) {
+ params = g_variant_builder_end (builder);
+ g_variant_builder_unref (builder);
+ }
+
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy), method_name, params, G_DBUS_CALL_FLAGS_NONE, e_data_server_util_get_dbus_call_timeout (), cancellable, callback, user_data);
+}
+
+void
+e_gdbus_proxy_method_call_void (const gchar *method_name, GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ proxy_method_call (method_name, E_GDBUS_TYPE_VOID, NULL, proxy, cancellable, callback, user_data);
+}
+
+void
+e_gdbus_proxy_method_call_boolean (const gchar *method_name, GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ proxy_method_call (method_name, E_GDBUS_TYPE_BOOLEAN, &in_boolean, proxy, cancellable, callback, user_data);
+}
+
+void
+e_gdbus_proxy_method_call_string (const gchar *method_name, GDBusProxy *proxy, const gchar *in_string, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ proxy_method_call (method_name, E_GDBUS_TYPE_STRING, in_string, proxy, cancellable, callback, user_data);
+}
+
+void
+e_gdbus_proxy_method_call_strv (const gchar *method_name, GDBusProxy *proxy, const gchar * const *in_strv, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ proxy_method_call (method_name, E_GDBUS_TYPE_STRV, in_strv, proxy, cancellable, callback, user_data);
+}
+
+void
+e_gdbus_proxy_method_call_uint (const gchar *method_name, GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ proxy_method_call (method_name, E_GDBUS_TYPE_VOID, &in_uint, proxy, cancellable, callback, user_data);
+}
+
+static gboolean
+process_result (const gchar *caller_func_name, guint out_type, gpointer out_value, GVariant *_result)
+{
+ if (out_type != E_GDBUS_TYPE_VOID)
+ g_return_val_if_fail (out_value != NULL, FALSE);
+
+ if (_result == NULL)
+ return FALSE;
+
+ switch (out_type) {
+ case E_GDBUS_TYPE_VOID:
+ break;
+ case E_GDBUS_TYPE_BOOLEAN:
+ g_variant_get (_result, "(b)", (gboolean *) out_value);
+ break;
+ case E_GDBUS_TYPE_STRING:
+ g_variant_get (_result, "(s)", (gchar **) out_value);
+ break;
+ case E_GDBUS_TYPE_STRV:
+ g_variant_get (_result, "(^as)", (gchar ***) out_value);
+ break;
+ case E_GDBUS_TYPE_UINT:
+ g_variant_get (_result, "(u)", (guint *) out_value);
+ break;
+ default:
+ g_warning ("%s: Unknown 'out' E_GDBUS_TYPE %x", caller_func_name ? caller_func_name : G_STRFUNC, out_type);
+ break;
+ }
+
+ g_variant_unref (_result);
+
+ return TRUE;
+}
+
+static gboolean
+proxy_method_call_finish (guint out_type, gpointer out_param, GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), FALSE);
+ if (out_type != E_GDBUS_TYPE_VOID)
+ g_return_val_if_fail (out_param != NULL, FALSE);
+
+ return process_result (G_STRFUNC, out_type, out_param, g_dbus_proxy_call_finish (proxy, result, error));
+}
+
+gboolean
+e_gdbus_proxy_method_call_finish_void (GDBusProxy *proxy, GAsyncResult *result, GError **error)
+{
+ return proxy_method_call_finish (E_GDBUS_TYPE_VOID, NULL, proxy, result, error);
+}
+
+gboolean
+e_gdbus_proxy_method_call_finish_boolean (GDBusProxy *proxy, GAsyncResult *result, gboolean *out_boolean, GError **error)
+{
+ return proxy_method_call_finish (E_GDBUS_TYPE_BOOLEAN, out_boolean, proxy, result, error);
+}
+
+gboolean
+e_gdbus_proxy_method_call_finish_string (GDBusProxy *proxy, GAsyncResult *result, gchar **out_string, GError **error)
+{
+ return proxy_method_call_finish (E_GDBUS_TYPE_STRING, out_string, proxy, result, error);
+}
+
+gboolean
+e_gdbus_proxy_method_call_finish_strv (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_strv, GError **error)
+{
+ return proxy_method_call_finish (E_GDBUS_TYPE_STRV, out_strv, proxy, result, error);
+}
+
+gboolean
+e_gdbus_proxy_method_call_finish_uint (GDBusProxy *proxy, GAsyncResult *result, guint *out_uint, GError **error)
+{
+ return proxy_method_call_finish (E_GDBUS_TYPE_UINT, out_uint, proxy, result, error);
+}
+
+static gboolean
+proxy_method_call_sync (const gchar *method_name, guint in_type, gconstpointer in_value, guint out_type, gpointer out_value, GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ GVariant *params = NULL;
+ GVariant *item;
+ GVariantBuilder *builder = NULL;
+
+ g_return_val_if_fail (method_name != NULL, FALSE);
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), FALSE);
+ if (in_type != E_GDBUS_TYPE_VOID)
+ g_return_val_if_fail (in_value != NULL, FALSE);
+ if (out_type != E_GDBUS_TYPE_VOID)
+ g_return_val_if_fail (out_value != NULL, FALSE);
+
+ switch (in_type) {
+ case E_GDBUS_TYPE_VOID:
+ break;
+ case E_GDBUS_TYPE_BOOLEAN:
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ item = g_variant_new_boolean (* ((const gboolean *) in_value));
+ g_variant_builder_add_value (builder, item);
+ break;
+ case E_GDBUS_TYPE_STRING:
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ item = g_variant_new_string ((const gchar *) in_value);
+ g_variant_builder_add_value (builder, item);
+ break;
+ case E_GDBUS_TYPE_STRV:
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ item = g_variant_new_strv ((const gchar * const *) in_value, -1);
+ g_variant_builder_add_value (builder, item);
+ break;
+ case E_GDBUS_TYPE_UINT:
+ builder = g_variant_builder_new (G_VARIANT_TYPE_TUPLE);
+ item = g_variant_new_uint32 (* ((const guint *) in_value));
+ g_variant_builder_add_value (builder, item);
+ break;
+ default:
+ g_warning ("%s: Unknown 'in' E_GDBUS_TYPE %x", G_STRFUNC, in_type);
+ return FALSE;
+ }
+
+ if (builder != NULL) {
+ params = g_variant_builder_end (builder);
+ g_variant_builder_unref (builder);
+ }
+
+ return process_result (G_STRFUNC, out_type, out_value, g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), method_name, params, G_DBUS_CALL_FLAGS_NONE, e_data_server_util_get_dbus_call_timeout (), cancellable, error));
+}
+
+gboolean
+e_gdbus_proxy_method_call_sync_void__void (const gchar *method_name, GDBusProxy *proxy, GCancellable *cancellable, GError **error)
+{
+ return proxy_method_call_sync (method_name, E_GDBUS_TYPE_VOID, NULL, E_GDBUS_TYPE_VOID, NULL, proxy, cancellable, error);
+}
+
+gboolean
+e_gdbus_proxy_method_call_sync_boolean__void (const gchar *method_name, GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GError **error)
+{
+ return proxy_method_call_sync (method_name, E_GDBUS_TYPE_BOOLEAN, &in_boolean, E_GDBUS_TYPE_VOID, NULL, proxy, cancellable, error);
+}
+
+gboolean
+e_gdbus_proxy_method_call_sync_string__void (const gchar *method_name, GDBusProxy *proxy, const gchar *in_string, GCancellable *cancellable, GError **error)
+{
+ return proxy_method_call_sync (method_name, E_GDBUS_TYPE_STRING, in_string, E_GDBUS_TYPE_VOID, NULL, proxy, cancellable, error);
+}
+
+gboolean
+e_gdbus_proxy_method_call_sync_strv__void (const gchar *method_name, GDBusProxy *proxy, const gchar * const *in_strv, GCancellable *cancellable, GError **error)
+{
+ return proxy_method_call_sync (method_name, E_GDBUS_TYPE_STRV, in_strv, E_GDBUS_TYPE_VOID, NULL, proxy, cancellable, error);
+}
+
+gboolean
+e_gdbus_proxy_method_call_sync_uint__void (const gchar *method_name, GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GError **error)
+{
+ return proxy_method_call_sync (method_name, E_GDBUS_TYPE_UINT, &in_uint, E_GDBUS_TYPE_VOID, NULL, proxy, cancellable, error);
+}
+
+gboolean
+e_gdbus_proxy_method_call_sync_string__string (const gchar *method_name, GDBusProxy *proxy, const gchar *in_string, gchar **out_string, GCancellable *cancellable, GError **error)
+{
+ return proxy_method_call_sync (method_name, E_GDBUS_TYPE_STRING, in_string, E_GDBUS_TYPE_STRING, out_string, proxy, cancellable, error);
+}
+
+gboolean
+e_gdbus_proxy_method_call_sync_strv__string (const gchar *method_name, GDBusProxy *proxy, const gchar * const *in_strv, gchar **out_string, GCancellable *cancellable, GError **error)
+{
+ return proxy_method_call_sync (method_name, E_GDBUS_TYPE_STRV, in_strv, E_GDBUS_TYPE_STRING, out_string, proxy, cancellable, error);
+}
+
+/* free returned pointer with g_strfreev() */
+gchar **
+e_gdbus_templates_encode_error (const GError *in_error)
+{
+ gchar **strv;
+
+ strv = g_new0 (gchar *, 3);
+
+ if (!in_error) {
+ strv[0] = g_strdup ("");
+ strv[1] = g_strdup ("");
+ } else {
+ gchar *dbus_error_name = g_dbus_error_encode_gerror (in_error);
+
+ strv[0] = e_util_utf8_make_valid (dbus_error_name ? dbus_error_name : "");
+ strv[1] = e_util_utf8_make_valid (in_error->message);
+
+ g_free (dbus_error_name);
+ }
+
+ return strv;
+}
+
+/* free *out_error with g_error_free(), if not NULL */
+gboolean
+e_gdbus_templates_decode_error (const gchar * const *in_strv, GError **out_error)
+{
+ const gchar *error_name, *error_message;
+
+ g_return_val_if_fail (out_error != NULL, FALSE);
+
+ *out_error = NULL;
+
+ g_return_val_if_fail (in_strv != NULL, FALSE);
+ g_return_val_if_fail (in_strv[0] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[1] != NULL, FALSE);
+ g_return_val_if_fail (in_strv[2] == NULL, FALSE);
+
+ error_name = in_strv[0];
+ error_message = in_strv[1];
+
+ if (error_name && *error_name && error_message)
+ *out_error = g_dbus_error_new_for_dbus_error (error_name, error_message);
+
+ return TRUE;
+}
diff --git a/libedataserver/e-gdbus-templates.h b/libedataserver/e-gdbus-templates.h
new file mode 100644
index 0000000..ce32798
--- /dev/null
+++ b/libedataserver/e-gdbus-templates.h
@@ -0,0 +1,750 @@
+/*
+ * e-gdbus-templates.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_GDBUS_TEMPLATES_H
+#define E_GDBUS_TEMPLATES_H
+
+#include <gio/gio.h>
+#include <libedataserver/e-gdbus-marshallers.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_GDBUS_ASYNC_OP_KEEPER (e_gdbus_async_op_keeper_get_type ())
+#define E_GDBUS_ASYNC_OP_KEEPER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_GDBUS_ASYNC_OP_KEEPER, EGdbusAsyncOpKeeper))
+#define E_IS_GDBUS_ASYNC_OP_KEEPER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_GDBUS_ASYNC_OP_KEEPER))
+#define E_GDBUS_ASYNC_OP_KEEPER_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE((o), E_TYPE_GDBUS_ASYNC_OP_KEEPER, EGdbusAsyncOpKeeperInterface))
+
+typedef struct _EGdbusAsyncOpKeeper EGdbusAsyncOpKeeper; /* Dummy typedef */
+typedef struct _EGdbusAsyncOpKeeperInterface EGdbusAsyncOpKeeperInterface;
+
+struct _EGdbusAsyncOpKeeperInterface
+{
+ GTypeInterface parent_iface;
+
+ GHashTable * (* get_pending_ops) (EGdbusAsyncOpKeeper *object);
+ gboolean (* cancel_op_sync) (EGdbusAsyncOpKeeper *object, guint in_opid, GCancellable *cancellable, GError **error);
+};
+
+GType e_gdbus_async_op_keeper_get_type (void) G_GNUC_CONST;
+
+GHashTable * e_gdbus_async_op_keeper_create_pending_ops (EGdbusAsyncOpKeeper *object);
+GHashTable * e_gdbus_async_op_keeper_get_pending_ops (EGdbusAsyncOpKeeper *object);
+gboolean e_gdbus_async_op_keeper_cancel_op_sync (EGdbusAsyncOpKeeper *object, guint in_opid, GCancellable *cancellable, GError **error);
+
+enum {
+ E_GDBUS_TYPE_IS_ASYNC = 1 << 0, /* if set, then OPID and GError precedes to actual parameter */
+ E_GDBUS_TYPE_VOID = 1 << 1,
+ E_GDBUS_TYPE_BOOLEAN = 1 << 2,
+ E_GDBUS_TYPE_STRING = 1 << 3,
+ E_GDBUS_TYPE_STRV = 1 << 4,
+ E_GDBUS_TYPE_UINT = 1 << 5
+};
+
+/* _where is a target component name, like ' ## _where ## ' or 'cal'
+ _mname is method name, like 'open'
+ _mtype is method type, like 'method_in'
+ _param_name is parameter name, like 'only_if_exists'
+ _param_type is parameter type, as string, like "s"
+ all except _param_type are identificators, not strings
+*/
+#define E_DECLARE_GDBUS_ARG(_where, _mname, _mtype, _param_name, _param_type) \
+ static const GDBusArgInfo e_gdbus_ ## _where ## _ ## _mtype ## _mname ## _param_name = \
+ { \
+ -1, \
+ (gchar *) # _param_name, \
+ (gchar *) _param_type, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARE_GDBUS_NOTIFY_SIGNAL_0(_where, _sname) \
+ static const GDBusSignalInfo e_gdbus_ ## _where ## _signal_ ## _sname = \
+ { \
+ -1, \
+ (gchar *) # _sname, \
+ (GDBusArgInfo **) NULL, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARE_GDBUS_NOTIFY_SIGNAL_1(_where, _sname, _p1_name, _p1_type) \
+ E_DECLARE_GDBUS_ARG (_where, _sname, signal, _p1_name, _p1_type) \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _signal_arg_pointers_ ## _sname[] = \
+ { \
+ &e_gdbus_ ## _where ## _signal ## _sname ## _p1_name, \
+ NULL \
+ }; \
+ \
+ static const GDBusSignalInfo e_gdbus_ ## _where ## _signal_ ## _sname = \
+ { \
+ -1, \
+ (gchar *) # _sname, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _signal_arg_pointers_ ## _sname, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARE_GDBUS_NOTIFY_SIGNAL_2(_where, _sname, _p1_name, _p1_type, _p2_name, _p2_type) \
+ E_DECLARE_GDBUS_ARG (_where, _sname, signal, _p1_name, _p1_type) \
+ E_DECLARE_GDBUS_ARG (_where, _sname, signal, _p2_name, _p2_type) \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _signal_arg_pointers_ ## _sname[] = \
+ { \
+ &e_gdbus_ ## _where ## _signal ## _sname ## _p1_name, \
+ &e_gdbus_ ## _where ## _signal ## _sname ## _p2_name, \
+ NULL \
+ }; \
+ \
+ static const GDBusSignalInfo e_gdbus_ ## _where ## _signal_ ## _sname = \
+ { \
+ -1, \
+ (gchar *) # _sname, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _signal_arg_pointers_ ## _sname, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARE_GDBUS_ASYNC_DONE_SIGNAL_0(_where, _sname) \
+ E_DECLARE_GDBUS_ARG (_where, _sname, signal, opid, "u") \
+ E_DECLARE_GDBUS_ARG (_where, _sname, signal, dbus_error_name, "s") \
+ E_DECLARE_GDBUS_ARG (_where, _sname, signal, dbus_error_message, "s") \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _signal_arg_pointers_ ## _sname[] = \
+ { \
+ &e_gdbus_ ## _where ## _signal ## _sname ## opid, \
+ &e_gdbus_ ## _where ## _signal ## _sname ## dbus_error_name, \
+ &e_gdbus_ ## _where ## _signal ## _sname ## dbus_error_message, \
+ NULL \
+ }; \
+ \
+ static const GDBusSignalInfo e_gdbus_ ## _where ## _signal_ ## _sname = \
+ { \
+ -1, \
+ (gchar *) # _sname, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _signal_arg_pointers_ ## _sname, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARE_GDBUS_ASYNC_DONE_SIGNAL_1(_where, _sname, _p1_name, _p1_type) \
+ E_DECLARE_GDBUS_ARG (_where, _sname, signal, opid, "u") \
+ E_DECLARE_GDBUS_ARG (_where, _sname, signal, dbus_error_name, "s") \
+ E_DECLARE_GDBUS_ARG (_where, _sname, signal, dbus_error_message, "s") \
+ E_DECLARE_GDBUS_ARG (_where, _sname, signal, _p1_name, _p1_type) \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _signal_arg_pointers_ ## _sname[] = \
+ { \
+ &e_gdbus_ ## _where ## _signal ## _sname ## opid, \
+ &e_gdbus_ ## _where ## _signal ## _sname ## dbus_error_name, \
+ &e_gdbus_ ## _where ## _signal ## _sname ## dbus_error_message, \
+ &e_gdbus_ ## _where ## _signal ## _sname ## _p1_name, \
+ NULL \
+ }; \
+ \
+ static const GDBusSignalInfo e_gdbus_ ## _where ## _signal_ ## _sname = \
+ { \
+ -1, \
+ (gchar *) # _sname, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _signal_arg_pointers_ ## _sname, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARE_GDBUS_SYNC_METHOD_0(_where, _mname) \
+ static const GDBusMethodInfo e_gdbus_ ## _where ## _method_ ## _mname = \
+ { \
+ -1, \
+ (gchar *) # _mname, \
+ (GDBusArgInfo **) NULL, \
+ (GDBusArgInfo **) NULL, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARE_GDBUS_SYNC_METHOD_1(_where, _mname, _p1_name, _p1_type) \
+ E_DECLARE_GDBUS_ARG (_where, _mname, method_in, _p1_name, _p1_type) \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _method_in_arg_pointers_ ## _mname[] = \
+ { \
+ &e_gdbus_ ## _where ## _method_in ## _mname ## _p1_name, \
+ NULL \
+ }; \
+ \
+ static const GDBusMethodInfo e_gdbus_ ## _where ## _method_ ## _mname = \
+ { \
+ -1, \
+ (gchar *) # _mname, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _method_in_arg_pointers_ ## _mname, \
+ (GDBusArgInfo **) NULL, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARE_GDBUS_SYNC_METHOD_0_WITH_RETURN(_where, _mname, _r1_name, _r1_type) \
+ E_DECLARE_GDBUS_ARG (_where, _mname, method_out, _r1_name, _r1_type) \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _method_out_arg_pointers_ ## _mname[] = \
+ { \
+ &e_gdbus_ ## _where ## _method_out ## _mname ## _r1_name, \
+ NULL \
+ }; \
+ \
+ static const GDBusMethodInfo e_gdbus_ ## _where ## _method_ ## _mname = \
+ { \
+ -1, \
+ (gchar *) # _mname, \
+ (GDBusArgInfo **) NULL, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _method_out_arg_pointers_ ## _mname, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARE_GDBUS_SYNC_METHOD_1_WITH_RETURN(_where, _mname, _p1_name, _p1_type, _r1_name, _r1_type)\
+ E_DECLARE_GDBUS_ARG (_where, _mname, method_in, _p1_name, _p1_type) \
+ E_DECLARE_GDBUS_ARG (_where, _mname, method_out, _r1_name, _r1_type) \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _method_in_arg_pointers_ ## _mname[] = \
+ { \
+ &e_gdbus_ ## _where ## _method_in ## _mname ## _p1_name, \
+ NULL \
+ }; \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _method_out_arg_pointers_ ## _mname[] = \
+ { \
+ &e_gdbus_ ## _where ## _method_out ## _mname ## _r1_name, \
+ NULL \
+ }; \
+ \
+ static const GDBusMethodInfo e_gdbus_ ## _where ## _method_ ## _mname = \
+ { \
+ -1, \
+ (gchar *) # _mname, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _method_in_arg_pointers_ ## _mname, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _method_out_arg_pointers_ ## _mname, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARE_GDBUS_ASYNC_METHOD_0(_where, _mname) \
+ E_DECLARE_GDBUS_ASYNC_DONE_SIGNAL_0 (_where, _mname ## _done) \
+ E_DECLARE_GDBUS_ARG (_where, _mname, method_out, opid, "u") \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _method_out_arg_pointers_ ## _mname[] = \
+ { \
+ &e_gdbus_ ## _where ## _method_out ## _mname ## opid, \
+ NULL \
+ }; \
+ \
+ static const GDBusMethodInfo e_gdbus_ ## _where ## _method_ ## _mname = \
+ { \
+ -1, \
+ (gchar *) # _mname, \
+ (GDBusArgInfo **) NULL, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _method_out_arg_pointers_ ## _mname, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARE_GDBUS_ASYNC_METHOD_1(_where, _mname, _p1_name, _p1_type) \
+ E_DECLARE_GDBUS_ASYNC_DONE_SIGNAL_0 (_where, _mname ## _done) \
+ E_DECLARE_GDBUS_ARG (_where, _mname, method_in, _p1_name, _p1_type) \
+ E_DECLARE_GDBUS_ARG (_where, _mname, method_out, opid, "u") \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _method_in_arg_pointers_ ## _mname[] = \
+ { \
+ &e_gdbus_ ## _where ## _method_in ## _mname ## _p1_name, \
+ NULL \
+ }; \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _method_out_arg_pointers_ ## _mname[] = \
+ { \
+ &e_gdbus_ ## _where ## _method_out ## _mname ## opid, \
+ NULL \
+ }; \
+ \
+ static const GDBusMethodInfo e_gdbus_ ## _where ## _method_ ## _mname = \
+ { \
+ -1, \
+ (gchar *) # _mname, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _method_in_arg_pointers_ ## _mname, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _method_out_arg_pointers_ ## _mname, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARE_GDBUS_ASYNC_METHOD_0_WITH_RETURN(_where, _mname, _r1_name, _r1_type) \
+ E_DECLARE_GDBUS_ASYNC_DONE_SIGNAL_1 (_where, _mname ## _done, _r1_name, _r1_type) \
+ E_DECLARE_GDBUS_ARG (_where, _mname, method_out, opid, "u") \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _method_out_arg_pointers_ ## _mname[] = \
+ { \
+ &e_gdbus_ ## _where ## _method_out ## _mname ## opid, \
+ NULL \
+ }; \
+ \
+ static const GDBusMethodInfo e_gdbus_ ## _where ## _method_ ## _mname = \
+ { \
+ -1, \
+ (gchar *) # _mname, \
+ (GDBusArgInfo **) NULL, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _method_out_arg_pointers_ ## _mname, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN(_where, _mname, _p1_name, _p1_type, _r1_name, _r1_type)\
+ E_DECLARE_GDBUS_ASYNC_DONE_SIGNAL_1 (_where, _mname ## _done, _r1_name, _r1_type) \
+ E_DECLARE_GDBUS_ARG (_where, _mname, method_in, _p1_name, _p1_type) \
+ E_DECLARE_GDBUS_ARG (_where, _mname, method_out, opid, "u") \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _method_in_arg_pointers_ ## _mname[] = \
+ { \
+ &e_gdbus_ ## _where ## _method_in ## _mname ## _p1_name, \
+ NULL \
+ }; \
+ \
+ static const GDBusArgInfo * const e_gdbus_ ## _where ## _method_out_arg_pointers_ ## _mname[] = \
+ { \
+ &e_gdbus_ ## _where ## _method_out ## _mname ## opid, \
+ NULL \
+ }; \
+ \
+ static const GDBusMethodInfo e_gdbus_ ## _where ## _method_ ## _mname = \
+ { \
+ -1, \
+ (gchar *) # _mname, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _method_in_arg_pointers_ ## _mname, \
+ (GDBusArgInfo **) &e_gdbus_ ## _where ## _method_out_arg_pointers_ ## _mname, \
+ (GDBusAnnotationInfo **) NULL, \
+ };
+
+#define E_DECLARED_GDBUS_SIGNAL_INFO_NAME(_where, _sname) e_gdbus_ ## _where ## _signal_ ## _sname
+#define E_DECLARED_GDBUS_METHOD_INFO_NAME(_where, _mname) e_gdbus_ ## _where ## _method_ ## _mname
+
+/* this requires signal_emission_hook_cb_ ## _sig_name hook defined,
+ which can be created with one of E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_... macros */
+#define E_INIT_GDBUS_SIGNAL_VOID(_iface_struct, _dbus_sig_name_str, _sig_name_var, _sig_id) \
+ signals[_sig_id] = g_signal_new (# _sig_name_var, \
+ G_TYPE_FROM_INTERFACE (iface), \
+ G_SIGNAL_RUN_LAST, \
+ G_STRUCT_OFFSET (_iface_struct, _sig_name_var), \
+ NULL, \
+ NULL, \
+ g_cclosure_marshal_VOID__VOID, \
+ G_TYPE_NONE, \
+ 0); \
+ \
+ g_signal_add_emission_hook (signals[_sig_id], 0, signal_emission_hook_cb_ ## _sig_name_var, (gpointer) _dbus_sig_name_str, NULL);\
+ g_hash_table_insert (_signal_name_to_id, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (_sig_id)); \
+ g_hash_table_insert (_signal_name_to_type, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (E_GDBUS_TYPE_VOID));
+
+#define E_INIT_GDBUS_SIGNAL_TMPL_TYPED(_mtype, _gtype, _iface_struct, _dbus_sig_name_str, _sig_name_var, _sig_id) \
+ signals[_sig_id] = g_signal_new (# _sig_name_var, \
+ G_TYPE_FROM_INTERFACE (iface), \
+ G_SIGNAL_RUN_LAST, \
+ G_STRUCT_OFFSET (_iface_struct, _sig_name_var), \
+ NULL, \
+ NULL, \
+ g_cclosure_marshal_VOID__ ## _mtype, \
+ G_TYPE_NONE, \
+ 1, \
+ G_TYPE_ ## _gtype); \
+ \
+ g_signal_add_emission_hook (signals[_sig_id], 0, signal_emission_hook_cb_ ## _sig_name_var, (gpointer) _dbus_sig_name_str, NULL);\
+ g_hash_table_insert (_signal_name_to_id, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (_sig_id)); \
+ g_hash_table_insert (_signal_name_to_type, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (E_GDBUS_TYPE_ ## _gtype));
+
+#define E_INIT_GDBUS_SIGNAL_BOOLEAN(_iface_struct, _dbus_sig_name_str, _sig_name_var, _sig_id) \
+ E_INIT_GDBUS_SIGNAL_TMPL_TYPED (BOOLEAN, BOOLEAN, _iface_struct, _dbus_sig_name_str, _sig_name_var, _sig_id)
+
+#define E_INIT_GDBUS_SIGNAL_STRING(_iface_struct, _dbus_sig_name_str, _sig_name_var, _sig_id) \
+ E_INIT_GDBUS_SIGNAL_TMPL_TYPED (STRING, STRING, _iface_struct, _dbus_sig_name_str, _sig_name_var, _sig_id)
+
+#define E_INIT_GDBUS_SIGNAL_STRV(_iface_struct, _dbus_sig_name_str, _sig_name_var, _sig_id) \
+ E_INIT_GDBUS_SIGNAL_TMPL_TYPED (BOXED, STRV, _iface_struct, _dbus_sig_name_str, _sig_name_var, _sig_id)
+
+#define E_INIT_GDBUS_SIGNAL_UINT(_iface_struct, _dbus_sig_name_str, _sig_name_var, _sig_id) \
+ E_INIT_GDBUS_SIGNAL_TMPL_TYPED (UINT, UINT, _iface_struct, _dbus_sig_name_str, _sig_name_var, _sig_id)
+
+#define E_INIT_GDBUS_SIGNAL_UINT_STRING(_iface_struct, _dbus_sig_name_str, _sig_name_var, _sig_id) \
+ signals[_sig_id] = g_signal_new (# _sig_name_var, \
+ G_TYPE_FROM_INTERFACE (iface), \
+ G_SIGNAL_RUN_LAST, \
+ G_STRUCT_OFFSET (_iface_struct, _sig_name_var), \
+ NULL, \
+ NULL, \
+ e_gdbus_marshallers_VOID__UINT_STRING, \
+ G_TYPE_NONE, \
+ 2, \
+ G_TYPE_UINT, G_TYPE_STRING); \
+ \
+ g_signal_add_emission_hook (signals[_sig_id], 0, signal_emission_hook_cb_ ## _sig_name_var, (gpointer) _dbus_sig_name_str, NULL);\
+ g_hash_table_insert (_signal_name_to_id, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (_sig_id)); \
+ g_hash_table_insert (_signal_name_to_type, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (E_GDBUS_TYPE_UINT | E_GDBUS_TYPE_STRING));
+
+#define E_INIT_GDBUS_METHOD_DONE_VOID(_iface_struct, _sig_name_var, _done_sig_id) \
+ signals[_done_sig_id] = g_signal_new (# _sig_name_var "_done", \
+ G_TYPE_FROM_INTERFACE (iface), \
+ G_SIGNAL_RUN_LAST, \
+ G_STRUCT_OFFSET (_iface_struct, _sig_name_var ## _done), \
+ NULL, \
+ NULL, \
+ e_gdbus_marshallers_VOID__UINT_BOXED, \
+ G_TYPE_NONE, \
+ 2, \
+ G_TYPE_UINT, G_TYPE_ERROR); \
+ g_signal_add_emission_hook (signals[_done_sig_id], 0, \
+ signal_emission_hook_cb_ ## _sig_name_var ## _done, (gpointer) # _sig_name_var "_done", NULL); \
+ g_hash_table_insert (_signal_name_to_id, (gpointer) # _sig_name_var "_done", GUINT_TO_POINTER (_done_sig_id)); \
+ g_hash_table_insert (_signal_name_to_type, (gpointer) # _sig_name_var "_done", GUINT_TO_POINTER (E_GDBUS_TYPE_IS_ASYNC | E_GDBUS_TYPE_VOID));
+
+#define E_INIT_GDBUS_METHOD_DONE_ASYNC_TMPL_TYPED(_mtype, _gtype, _iface_struct, _sig_name_var, _done_sig_id) \
+ signals[_done_sig_id] = g_signal_new (# _sig_name_var "_done", \
+ G_TYPE_FROM_INTERFACE (iface), \
+ G_SIGNAL_RUN_LAST, \
+ G_STRUCT_OFFSET (_iface_struct, _sig_name_var ## _done), \
+ NULL, \
+ NULL, \
+ e_gdbus_marshallers_VOID__UINT_BOXED_ ## _mtype, \
+ G_TYPE_NONE, \
+ 3, \
+ G_TYPE_UINT, G_TYPE_ERROR, G_TYPE_ ## _gtype); \
+ g_signal_add_emission_hook (signals[_done_sig_id], 0, \
+ signal_emission_hook_cb_ ## _sig_name_var ## _done, (gpointer) # _sig_name_var "_done", NULL); \
+ g_hash_table_insert (_signal_name_to_id, (gpointer) # _sig_name_var "_done", GUINT_TO_POINTER (_done_sig_id)); \
+ g_hash_table_insert (_signal_name_to_type, (gpointer) # _sig_name_var "_done", GUINT_TO_POINTER (E_GDBUS_TYPE_IS_ASYNC | E_GDBUS_TYPE_ ## _gtype));
+
+#define E_INIT_GDBUS_METHOD_DONE_BOOLEAN(_iface_struct, _sig_name_var, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_ASYNC_TMPL_TYPED (BOOLEAN, BOOLEAN, _iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_INIT_GDBUS_METHOD_DONE_STRING(_iface_struct, _sig_name_var, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_ASYNC_TMPL_TYPED (STRING, STRING, _iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_INIT_GDBUS_METHOD_DONE_STRV(_iface_struct, _sig_name_var, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_ASYNC_TMPL_TYPED (BOXED, STRV, _iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_INIT_GDBUS_METHOD_DONE_UINT(_iface_struct, _sig_name_var, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_ASYNC_TMPL_TYPED (UINT, UINT, _iface_struct, _sig_name_var, _done_sig_id)
+
+/* do not use this directly, there is missing _method_name_to_type insertion */
+#define E_INIT_GDBUS_METHOD_CALL_TMPL_VOID(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ signals[_method_sig_id] = g_signal_new ("handle-" # _sig_name_var, \
+ G_TYPE_FROM_INTERFACE (iface), \
+ G_SIGNAL_RUN_LAST, \
+ G_STRUCT_OFFSET (_iface_struct, handle_ ## _sig_name_var), \
+ NULL, NULL, \
+ e_gdbus_marshallers_BOOLEAN__OBJECT, \
+ G_TYPE_BOOLEAN, \
+ 1, \
+ G_TYPE_DBUS_METHOD_INVOCATION); \
+ g_hash_table_insert (_method_name_to_id, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (_method_sig_id));
+
+/* do not use this directly, there is missing _method_name_to_type insertion */
+#define E_INIT_GDBUS_METHOD_CALL_TMPL_TYPED(_mtype, _gtype, _iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ signals[_method_sig_id] = g_signal_new ("handle-" # _sig_name_var, \
+ G_TYPE_FROM_INTERFACE (iface), \
+ G_SIGNAL_RUN_LAST, \
+ G_STRUCT_OFFSET (_iface_struct, handle_ ## _sig_name_var), \
+ NULL, NULL, \
+ e_gdbus_marshallers_BOOLEAN__OBJECT_ ## _mtype, \
+ G_TYPE_BOOLEAN, \
+ 2, \
+ G_TYPE_DBUS_METHOD_INVOCATION, \
+ G_TYPE_ ## _gtype); \
+ g_hash_table_insert (_method_name_to_id, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (_method_sig_id)); \
+
+#define E_INIT_GDBUS_METHOD_CALL_ASYNC_TMPL_TYPED(_mtype, _gtype, _iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_TMPL_TYPED (_mtype, _gtype, _iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ g_hash_table_insert (_method_name_to_type, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (E_GDBUS_TYPE_ ## _gtype | E_GDBUS_TYPE_IS_ASYNC));
+
+#define E_INIT_GDBUS_METHOD_VOID(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_TMPL_VOID(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ g_hash_table_insert (_method_name_to_type, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (E_GDBUS_TYPE_VOID));
+
+#define E_INIT_GDBUS_METHOD_BOOLEAN(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_TMPL_TYPED (BOOLEAN, BOOLEAN, _iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id)\
+ g_hash_table_insert (_method_name_to_type, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (E_GDBUS_TYPE_BOOLEAN));
+
+#define E_INIT_GDBUS_METHOD_STRING(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_TMPL_TYPED (STRING, STRING, _iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ g_hash_table_insert (_method_name_to_type, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (E_GDBUS_TYPE_STRING));
+
+#define E_INIT_GDBUS_METHOD_STRV(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_TMPL_TYPED (BOXED, STRV, _iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ g_hash_table_insert (_method_name_to_type, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (E_GDBUS_TYPE_STRV));
+
+#define E_INIT_GDBUS_METHOD_UINT(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_TMPL_TYPED (UINT, UINT, _iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ g_hash_table_insert (_method_name_to_type, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (E_GDBUS_TYPE_UINT));
+
+#define E_INIT_GDBUS_METHOD_CALL_VOID(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_TMPL_VOID(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ g_hash_table_insert (_method_name_to_type, (gpointer) _dbus_sig_name_str, GUINT_TO_POINTER (E_GDBUS_TYPE_VOID | E_GDBUS_TYPE_IS_ASYNC));
+
+#define E_INIT_GDBUS_METHOD_CALL_BOOLEAN(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_ASYNC_TMPL_TYPED (BOOLEAN, BOOLEAN, _iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id)
+
+#define E_INIT_GDBUS_METHOD_CALL_STRING(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_ASYNC_TMPL_TYPED (STRING, STRING, _iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id)
+
+#define E_INIT_GDBUS_METHOD_CALL_STRV(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_ASYNC_TMPL_TYPED (BOXED, STRV, _iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id)
+
+#define E_INIT_GDBUS_METHOD_CALL_UINT(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_ASYNC_TMPL_TYPED (UINT, UINT, _iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id)
+
+#define E_INIT_GDBUS_METHOD_ASYNC_VOID__VOID(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_VOID (_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_VOID (_iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_INIT_GDBUS_METHOD_ASYNC_VOID__STRING(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_VOID (_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_STRING (_iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_INIT_GDBUS_METHOD_ASYNC_VOID__STRV(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_VOID (_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_STRV (_iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_INIT_GDBUS_METHOD_ASYNC_BOOLEAN__VOID(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_BOOLEAN (_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_VOID (_iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_INIT_GDBUS_METHOD_ASYNC_UINT__VOID(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_UINT (_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_VOID (_iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_INIT_GDBUS_METHOD_ASYNC_STRING__VOID(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_STRING (_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_VOID (_iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_INIT_GDBUS_METHOD_ASYNC_STRV__VOID(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_STRV (_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_VOID (_iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id, _done_sig_id)\
+ E_INIT_GDBUS_METHOD_CALL_STRING (_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_STRING (_iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_INIT_GDBUS_METHOD_ASYNC_STRING__STRV(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_STRING (_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_STRV (_iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_INIT_GDBUS_METHOD_ASYNC_STRV__STRING(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_STRV (_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_STRING (_iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_INIT_GDBUS_METHOD_ASYNC_STRV__STRV(_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id, _done_sig_id) \
+ E_INIT_GDBUS_METHOD_CALL_STRV (_iface_struct, _dbus_sig_name_str, _sig_name_var, _method_sig_id) \
+ E_INIT_GDBUS_METHOD_DONE_STRV (_iface_struct, _sig_name_var, _done_sig_id)
+
+#define E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_VOID(_iface_name, _sig_name) \
+ static gboolean \
+ signal_emission_hook_cb_ ## _sig_name (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer user_data) \
+ { \
+ return e_gdbus_signal_emission_hook_void (ihint, n_param_values, param_values, user_data, _iface_name); \
+ }
+
+#define E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_BOOLEAN(_iface_name, _sig_name) \
+ static gboolean \
+ signal_emission_hook_cb_ ## _sig_name (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer user_data) \
+ { \
+ return e_gdbus_signal_emission_hook_boolean (ihint, n_param_values, param_values, user_data, _iface_name); \
+ }
+
+#define E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRING(_iface_name, _sig_name) \
+ static gboolean \
+ signal_emission_hook_cb_ ## _sig_name (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer user_data) \
+ { \
+ return e_gdbus_signal_emission_hook_string (ihint, n_param_values, param_values, user_data, _iface_name); \
+ }
+
+#define E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_STRV(_iface_name, _sig_name) \
+ static gboolean \
+ signal_emission_hook_cb_ ## _sig_name (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer user_data) \
+ { \
+ return e_gdbus_signal_emission_hook_strv (ihint, n_param_values, param_values, user_data, _iface_name); \
+ }
+
+#define E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_UINT(_iface_name, _sig_name) \
+ static gboolean \
+ signal_emission_hook_cb_ ## _sig_name (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer user_data) \
+ { \
+ return e_gdbus_signal_emission_hook_uint (ihint, n_param_values, param_values, user_data, _iface_name); \
+ }
+
+#define E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_UINT_STRING(_iface_name, _sig_name) \
+ static gboolean \
+ signal_emission_hook_cb_ ## _sig_name (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer user_data) \
+ { \
+ return e_gdbus_signal_emission_hook_uint_string (ihint, n_param_values, param_values, user_data, _iface_name); \
+ }
+
+#define E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_ASYNC_VOID(_iface_name, _sig_name) \
+ static gboolean \
+ signal_emission_hook_cb_ ## _sig_name (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer user_data) \
+ { \
+ return e_gdbus_signal_emission_hook_async_void (ihint, n_param_values, param_values, user_data, _iface_name); \
+ }
+
+#define E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_ASYNC_BOOLEAN(_iface_name, _sig_name) \
+ static gboolean \
+ signal_emission_hook_cb_ ## _sig_name (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer user_data) \
+ { \
+ return e_gdbus_signal_emission_hook_async_boolean (ihint, n_param_values, param_values, user_data, _iface_name); \
+ }
+
+#define E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_ASYNC_STRING(_iface_name, _sig_name) \
+ static gboolean \
+ signal_emission_hook_cb_ ## _sig_name (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer user_data) \
+ { \
+ return e_gdbus_signal_emission_hook_async_string (ihint, n_param_values, param_values, user_data, _iface_name); \
+ }
+
+#define E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_ASYNC_STRV(_iface_name, _sig_name) \
+ static gboolean \
+ signal_emission_hook_cb_ ## _sig_name (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer user_data) \
+ { \
+ return e_gdbus_signal_emission_hook_async_strv (ihint, n_param_values, param_values, user_data, _iface_name); \
+ }
+
+#define E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_ASYNC_UINT(_iface_name, _sig_name) \
+ static gboolean \
+ signal_emission_hook_cb_ ## _sig_name (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer user_data) \
+ { \
+ return e_gdbus_signal_emission_hook_async_uint (ihint, n_param_values, param_values, user_data, _iface_name); \
+ }
+
+#define E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID(_iface_name, _sig_name) \
+ E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_ASYNC_VOID (_iface_name, _sig_name ## _done)
+
+#define E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_BOOLEAN(_iface_name, _sig_name) \
+ E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_ASYNC_BOOLEAN (_iface_name, _sig_name ## _done)
+
+#define E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING(_iface_name, _sig_name) \
+ E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_ASYNC_STRING (_iface_name, _sig_name ## _done)
+
+#define E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRV(_iface_name, _sig_name) \
+ E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_ASYNC_STRV (_iface_name, _sig_name ## _done)
+
+#define E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_UINT(_iface_name, _sig_name) \
+ E_DECLARE_GDBUS_SIGNAL_EMISSION_HOOK_ASYNC_UINT (_iface_name, _sig_name ## _done)
+
+#define E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID(_sig_name) \
+ g_signal_connect (proxy, # _sig_name "_done", G_CALLBACK (e_gdbus_proxy_async_method_done_void), NULL);
+
+#define E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_BOOLEAN(_sig_name) \
+ g_signal_connect (proxy, # _sig_name "_done", G_CALLBACK (e_gdbus_proxy_async_method_done_boolean), NULL);
+
+#define E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING(_sig_name) \
+ g_signal_connect (proxy, # _sig_name "_done", G_CALLBACK (e_gdbus_proxy_async_method_done_string), NULL);
+
+#define E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRV(_sig_name) \
+ g_signal_connect (proxy, # _sig_name "_done", G_CALLBACK (e_gdbus_proxy_async_method_done_strv), NULL);
+
+#define E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_UINT(_sig_name) \
+ g_signal_connect (proxy, # _sig_name "_done", G_CALLBACK (e_gdbus_proxy_async_method_done_uint), NULL);
+
+void e_gdbus_proxy_emit_signal (GDBusProxy *proxy, GVariant *parameters, guint signal_id, guint signal_type);
+void e_gdbus_stub_handle_method_call (GObject *stub_object, GDBusMethodInvocation *invocation, GVariant *parameters, const gchar *method_name, guint method_id, guint method_type);
+
+gboolean e_gdbus_signal_emission_hook_void (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name);
+gboolean e_gdbus_signal_emission_hook_boolean (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name);
+gboolean e_gdbus_signal_emission_hook_string (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name);
+gboolean e_gdbus_signal_emission_hook_strv (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name);
+gboolean e_gdbus_signal_emission_hook_uint (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name);
+gboolean e_gdbus_signal_emission_hook_uint_string (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name);
+
+gboolean e_gdbus_signal_emission_hook_async_void (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name);
+gboolean e_gdbus_signal_emission_hook_async_boolean (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name);
+gboolean e_gdbus_signal_emission_hook_async_string (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name);
+gboolean e_gdbus_signal_emission_hook_async_strv (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name);
+gboolean e_gdbus_signal_emission_hook_async_uint (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, const gchar *signal_name, const gchar *iface_name);
+
+/* GDBus calls method completion functions; after the 'async' method is expected associated done signal */
+void e_gdbus_complete_async_method (gpointer object, GDBusMethodInvocation *invocation, guint opid);
+void e_gdbus_complete_sync_method_void (gpointer object, GDBusMethodInvocation *invocation, const GError *error);
+void e_gdbus_complete_sync_method_boolean (gpointer object, GDBusMethodInvocation *invocation, gboolean out_boolean, const GError *error);
+void e_gdbus_complete_sync_method_string (gpointer object, GDBusMethodInvocation *invocation, const gchar *out_string, const GError *error);
+void e_gdbus_complete_sync_method_strv (gpointer object, GDBusMethodInvocation *invocation, const gchar * const *out_strv, const GError *error);
+void e_gdbus_complete_sync_method_uint (gpointer object, GDBusMethodInvocation *invocation, guint out_uint, const GError *error);
+
+/* callbacks on done signal handlers in the client proxy, which implements EGdbusAsyncOpKeeper interface;
+ functions take ownership of out parameters and are responsible for their freeing */
+void e_gdbus_proxy_async_method_done_void (EGdbusAsyncOpKeeper *proxy, guint arg_opid, const GError *error);
+void e_gdbus_proxy_async_method_done_boolean (EGdbusAsyncOpKeeper *proxy, guint arg_opid, const GError *error, gboolean out_boolean);
+void e_gdbus_proxy_async_method_done_string (EGdbusAsyncOpKeeper *proxy, guint arg_opid, const GError *error, const gchar *out_string);
+void e_gdbus_proxy_async_method_done_strv (EGdbusAsyncOpKeeper *proxy, guint arg_opid, const GError *error, const gchar * const *out_strv);
+void e_gdbus_proxy_async_method_done_uint (EGdbusAsyncOpKeeper *proxy, guint arg_opid, const GError *error, guint out_uint);
+
+void e_gdbus_proxy_call_void (const gchar *method_name, gpointer source_tag, EGdbusAsyncOpKeeper *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+void e_gdbus_proxy_call_boolean (const gchar *method_name, gpointer source_tag, EGdbusAsyncOpKeeper *proxy, gboolean in_boolean, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+void e_gdbus_proxy_call_string (const gchar *method_name, gpointer source_tag, EGdbusAsyncOpKeeper *proxy, const gchar *in_string, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+void e_gdbus_proxy_call_strv (const gchar *method_name, gpointer source_tag, EGdbusAsyncOpKeeper *proxy, const gchar * const *in_strv, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+void e_gdbus_proxy_call_uint (const gchar *method_name, gpointer source_tag, EGdbusAsyncOpKeeper *proxy, guint in_uint, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+
+gboolean e_gdbus_proxy_finish_call_void (EGdbusAsyncOpKeeper *proxy, GAsyncResult *result, GError **error, gpointer source_tag);
+gboolean e_gdbus_proxy_finish_call_boolean (EGdbusAsyncOpKeeper *proxy, GAsyncResult *result, gboolean *out_boolean, GError **error, gpointer source_tag);
+gboolean e_gdbus_proxy_finish_call_string (EGdbusAsyncOpKeeper *proxy, GAsyncResult *result, gchar **out_string, GError **error, gpointer source_tag);
+gboolean e_gdbus_proxy_finish_call_strv (EGdbusAsyncOpKeeper *proxy, GAsyncResult *result, gchar ***out_strv, GError **error, gpointer source_tag);
+gboolean e_gdbus_proxy_finish_call_uint (EGdbusAsyncOpKeeper *proxy, GAsyncResult *result, guint *out_uint, GError **error, gpointer source_tag);
+
+typedef void (* EGdbusCallStartVoid) (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+typedef void (* EGdbusCallStartBoolean) (GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+typedef void (* EGdbusCallStartString) (GDBusProxy *proxy, const gchar *in_string, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+typedef void (* EGdbusCallStartStrv) (GDBusProxy *proxy, const gchar * const *in_strv, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+typedef void (* EGdbusCallStartUint) (GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+
+typedef gboolean (* EGdbusCallFinishVoid) (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+typedef gboolean (* EGdbusCallFinishBoolean) (GDBusProxy *proxy, GAsyncResult *result, gboolean *out_boolean, GError **error);
+typedef gboolean (* EGdbusCallFinishString) (GDBusProxy *proxy, GAsyncResult *result, gchar **out_string, GError **error);
+typedef gboolean (* EGdbusCallFinishStrv) (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_strv, GError **error);
+typedef gboolean (* EGdbusCallFinishUint) (GDBusProxy *proxy, GAsyncResult *result, guint *out_uint, GError **error);
+
+/* this is for methods which are dividied into invocation and done signal */
+gboolean e_gdbus_proxy_call_sync_void__void (GDBusProxy *proxy, GCancellable *cancellable, GError **error, EGdbusCallStartVoid start_func, EGdbusCallFinishVoid finish_func);
+gboolean e_gdbus_proxy_call_sync_void__boolean (GDBusProxy *proxy, gboolean *out_boolean, GCancellable *cancellable, GError **error, EGdbusCallStartVoid start_func, EGdbusCallFinishBoolean finish_func);
+gboolean e_gdbus_proxy_call_sync_void__string (GDBusProxy *proxy, gchar **out_string, GCancellable *cancellable, GError **error, EGdbusCallStartVoid start_func, EGdbusCallFinishString finish_func);
+gboolean e_gdbus_proxy_call_sync_void__strv (GDBusProxy *proxy, gchar ***out_strv, GCancellable *cancellable, GError **error, EGdbusCallStartVoid start_func, EGdbusCallFinishStrv finish_func);
+gboolean e_gdbus_proxy_call_sync_void__uint (GDBusProxy *proxy, guint *out_uint, GCancellable *cancellable, GError **error, EGdbusCallStartVoid start_func, EGdbusCallFinishUint finish_func);
+gboolean e_gdbus_proxy_call_sync_boolean__void (GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GError **error, EGdbusCallStartBoolean start_func, EGdbusCallFinishVoid finish_func);
+gboolean e_gdbus_proxy_call_sync_string__void (GDBusProxy *proxy, const gchar *in_string, GCancellable *cancellable, GError **error, EGdbusCallStartString start_func, EGdbusCallFinishVoid finish_func);
+gboolean e_gdbus_proxy_call_sync_strv__void (GDBusProxy *proxy, const gchar * const *in_strv, GCancellable *cancellable, GError **error, EGdbusCallStartStrv start_func, EGdbusCallFinishVoid finish_func);
+gboolean e_gdbus_proxy_call_sync_uint__void (GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GError **error, EGdbusCallStartUint start_func, EGdbusCallFinishVoid finish_func);
+gboolean e_gdbus_proxy_call_sync_string__string (GDBusProxy *proxy, const gchar *in_string, gchar **out_string, GCancellable *cancellable, GError **error, EGdbusCallStartString start_func, EGdbusCallFinishString finish_func);
+gboolean e_gdbus_proxy_call_sync_string__strv (GDBusProxy *proxy, const gchar *in_string, gchar ***out_strv, GCancellable *cancellable, GError **error, EGdbusCallStartString start_func, EGdbusCallFinishStrv finish_func);
+gboolean e_gdbus_proxy_call_sync_strv__string (GDBusProxy *proxy, const gchar * const *in_strv, gchar **out_string, GCancellable *cancellable, GError **error, EGdbusCallStartStrv start_func, EGdbusCallFinishString finish_func);
+gboolean e_gdbus_proxy_call_sync_strv__strv (GDBusProxy *proxy, const gchar * const *in_strv, gchar ***out_strv, GCancellable *cancellable, GError **error, EGdbusCallStartStrv start_func, EGdbusCallFinishStrv finish_func);
+
+/* this is for "synchronous" methods, those without done signal */
+void e_gdbus_proxy_method_call_void (const gchar *method_name, GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+void e_gdbus_proxy_method_call_boolean (const gchar *method_name, GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+void e_gdbus_proxy_method_call_string (const gchar *method_name, GDBusProxy *proxy, const gchar *in_string, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+void e_gdbus_proxy_method_call_strv (const gchar *method_name, GDBusProxy *proxy, const gchar * const *in_strv, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+void e_gdbus_proxy_method_call_uint (const gchar *method_name, GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+
+gboolean e_gdbus_proxy_method_call_finish_void (GDBusProxy *proxy, GAsyncResult *result, GError **error);
+gboolean e_gdbus_proxy_method_call_finish_boolean (GDBusProxy *proxy, GAsyncResult *result, gboolean *out_boolean, GError **error);
+gboolean e_gdbus_proxy_method_call_finish_string (GDBusProxy *proxy, GAsyncResult *result, gchar **out_string, GError **error);
+gboolean e_gdbus_proxy_method_call_finish_strv (GDBusProxy *proxy, GAsyncResult *result, gchar ***out_strv, GError **error);
+gboolean e_gdbus_proxy_method_call_finish_uint (GDBusProxy *proxy, GAsyncResult *result, guint *out_uint, GError **error);
+
+gboolean e_gdbus_proxy_method_call_sync_void__void (const gchar *method_name, GDBusProxy *proxy, GCancellable *cancellable, GError **error);
+gboolean e_gdbus_proxy_method_call_sync_boolean__void (const gchar *method_name, GDBusProxy *proxy, gboolean in_boolean, GCancellable *cancellable, GError **error);
+gboolean e_gdbus_proxy_method_call_sync_string__void (const gchar *method_name, GDBusProxy *proxy, const gchar *in_string, GCancellable *cancellable, GError **error);
+gboolean e_gdbus_proxy_method_call_sync_strv__void (const gchar *method_name, GDBusProxy *proxy, const gchar * const *in_strv, GCancellable *cancellable, GError **error);
+gboolean e_gdbus_proxy_method_call_sync_uint__void (const gchar *method_name, GDBusProxy *proxy, guint in_uint, GCancellable *cancellable, GError **error);
+gboolean e_gdbus_proxy_method_call_sync_string__string (const gchar *method_name, GDBusProxy *proxy, const gchar *in_string, gchar **out_string, GCancellable *cancellable, GError **error);
+gboolean e_gdbus_proxy_method_call_sync_strv__string (const gchar *method_name, GDBusProxy *proxy, const gchar * const *in_strv, gchar **out_string, GCancellable *cancellable, GError **error);
+
+gchar ** e_gdbus_templates_encode_error (const GError *in_error);
+gboolean e_gdbus_templates_decode_error (const gchar * const *in_strv, GError **out_error);
+
+G_END_DECLS
+
+#endif /* E_GDBUS_TEMPLATES_H */
diff --git a/libedataserver/e-operation-pool.c b/libedataserver/e-operation-pool.c
new file mode 100644
index 0000000..edef4d6
--- /dev/null
+++ b/libedataserver/e-operation-pool.c
@@ -0,0 +1,136 @@
+/*
+ * e-operation-pool.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/>
+ *
+ *
+ * Copyright (C) 2011 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <glib.h>
+
+#include "e-operation-pool.h"
+
+struct _EOperationPool {
+ GThreadPool *pool;
+
+ GMutex *ops_lock;
+ GHashTable *ops;
+ guint32 last_opid;
+};
+
+EOperationPool *
+e_operation_pool_new (guint max_threads, GFunc thread_func, gpointer user_data)
+{
+ EOperationPool *pool;
+ GThreadPool *thread_pool;
+ GError *error = NULL;
+
+ g_return_val_if_fail (thread_func != NULL, NULL);
+
+ thread_pool = g_thread_pool_new (thread_func, user_data, max_threads, FALSE, &error);
+ if (error) {
+ g_warning ("%s: Failed to create thread pool: %s", G_STRFUNC, error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ pool = g_new0 (EOperationPool, 1);
+ pool->pool = thread_pool;
+ pool->ops_lock = g_mutex_new ();
+ pool->ops = g_hash_table_new (g_direct_hash, g_direct_equal);
+ pool->last_opid = 0;
+
+ /* Kill threads which don't do anything for 10 seconds */
+ g_thread_pool_set_max_idle_time (10 * 1000);
+
+ return pool;
+}
+
+void
+e_operation_pool_free (EOperationPool *pool)
+{
+ g_return_if_fail (pool != NULL);
+
+ g_thread_pool_free (pool->pool, FALSE, FALSE);
+ g_mutex_free (pool->ops_lock);
+ g_hash_table_destroy (pool->ops);
+ g_free (pool);
+}
+
+/* Reserves new operation ID, which is returned. This operation ID may
+ be released by e_operation_pool_release_opid() when the operation
+ is finished.
+*/
+guint32
+e_operation_pool_reserve_opid (EOperationPool *pool)
+{
+ guint32 opid;
+
+ g_return_val_if_fail (pool != NULL, 0);
+ g_return_val_if_fail (pool->ops != NULL, 0);
+ g_return_val_if_fail (pool->ops_lock != NULL, 0);
+
+ g_mutex_lock (pool->ops_lock);
+
+ pool->last_opid++;
+ if (!pool->last_opid)
+ pool->last_opid = 1;
+
+ while (pool->last_opid && g_hash_table_lookup (pool->ops, GUINT_TO_POINTER (pool->last_opid)))
+ pool->last_opid++;
+
+ opid = pool->last_opid;
+ if (opid)
+ g_hash_table_insert (pool->ops, GUINT_TO_POINTER (opid), GUINT_TO_POINTER (1));
+
+ g_mutex_unlock (pool->ops_lock);
+
+ g_return_val_if_fail (opid != 0, 0);
+
+ return opid;
+}
+
+/* Releases operation ID previously reserved by e_operation_pool_reserve_opid(). */
+void
+e_operation_pool_release_opid (EOperationPool *pool, guint32 opid)
+{
+ g_return_if_fail (pool != NULL);
+ g_return_if_fail (pool->ops != NULL);
+ g_return_if_fail (pool->ops_lock != NULL);
+
+ g_mutex_lock (pool->ops_lock);
+ g_hash_table_remove (pool->ops, GUINT_TO_POINTER (opid));
+ g_mutex_unlock (pool->ops_lock);
+}
+
+/* Pushes operation to be processed. 'opdata' is passed to the function
+ provided in e_operation_pool_new().
+*/
+void
+e_operation_pool_push (EOperationPool *pool, gpointer opdata)
+{
+ GError *error = NULL;
+
+ g_return_if_fail (pool != NULL);
+ g_return_if_fail (pool->pool != NULL);
+
+ g_thread_pool_push (pool->pool, opdata, &error);
+
+ if (error) {
+ g_warning ("%s: Failed to push to thread pool: %s", G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+}
diff --git a/libedataserver/e-operation-pool.h b/libedataserver/e-operation-pool.h
new file mode 100644
index 0000000..f3f481c
--- /dev/null
+++ b/libedataserver/e-operation-pool.h
@@ -0,0 +1,36 @@
+/*
+ * e-operation-pool.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/>
+ *
+ *
+ * Copyright (C) 2011 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_OPERATION_POOL_H
+#define E_OPERATION_POOL_H
+
+#include <glib.h>
+#include <gio/gio.h>
+
+typedef struct _EOperationPool EOperationPool;
+
+EOperationPool *e_operation_pool_new (guint max_threads, GFunc thread_func, gpointer user_data);
+void e_operation_pool_free (EOperationPool *pool);
+guint32 e_operation_pool_reserve_opid (EOperationPool *pool);
+void e_operation_pool_release_opid (EOperationPool *pool, guint32 opid);
+void e_operation_pool_push (EOperationPool *pool, gpointer data);
+
+#endif /* E_OPERATION_POOL_H */
diff --git a/libedataserverui/Makefile.am b/libedataserverui/Makefile.am
index af00b8a..478b790 100644
--- a/libedataserverui/Makefile.am
+++ b/libedataserverui/Makefile.am
@@ -7,11 +7,14 @@ CPPFLAGS = \
-I$(top_srcdir) \
-I$(top_srcdir)/addressbook \
-I$(top_builddir)/addressbook \
+ -I$(top_srcdir)/calendar \
+ -I$(top_builddir)/calendar \
-DG_LOG_DOMAIN=\"e-data-server-ui\" \
-DE_DATA_SERVER_UI_UIDIR=\""$(uidir)"\" \
$(E_DATA_SERVER_UI_CFLAGS) \
$(GNOME_KEYRING_CFLAGS) \
- $(CAMEL_CFLAGS)
+ $(CAMEL_CFLAGS) \
+ $(SOUP_CFLAGS)
lib_LTLIBRARIES = libedataserverui-3.0.la
@@ -23,6 +26,7 @@ libedataserveruiinclude_HEADERS = \
e-category-editor.h \
e-destination-store.h \
e-book-auth-util.h \
+ e-client-utils.h \
e-contact-store.h \
e-name-selector.h \
e-name-selector-dialog.h \
@@ -53,6 +57,7 @@ libedataserverui_3_0_la_SOURCES = \
e-category-editor.c \
e-destination-store.c \
e-book-auth-util.c \
+ e-client-utils.c \
e-contact-store.c \
e-name-selector.c \
e-name-selector-dialog.c \
@@ -70,11 +75,13 @@ libedataserverui_3_0_la_CPPFLAGS = $(CPPFLAGS)
libedataserverui_3_0_la_LIBADD = \
$(top_builddir)/addressbook/libebook/libebook-1.2.la \
+ $(top_builddir)/calendar/libecal/libecal-1.2.la \
$(top_builddir)/libedataserver/libedataserver-1.2.la \
$(top_builddir)/camel/libcamel-1.2.la \
$(E_DATA_SERVER_UI_LIBS) \
$(GNOME_KEYRING_LIBS) \
- $(CAMEL_LIBS)
+ $(CAMEL_LIBS) \
+ $(SOUP_LIBS)
libedataserverui_3_0_la_LDFLAGS = \
-version-info $(LIBEDATASERVERUI_CURRENT):$(LIBEDATASERVERUI_REVISION):$(LIBEDATASERVERUI_AGE) $(NO_UNDEFINED)
diff --git a/libedataserverui/e-client-utils.c b/libedataserverui/e-client-utils.c
new file mode 100644
index 0000000..032ee5e
--- /dev/null
+++ b/libedataserverui/e-client-utils.c
@@ -0,0 +1,773 @@
+/*
+ * e-client-utils.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include <libsoup/soup.h>
+
+#include <libedataserver/e-client.h>
+#include "libedataserver/e-client-private.h"
+#include <libebook/e-book-client.h>
+#include <libecal/e-cal-client.h>
+
+#include "e-passwords.h"
+#include "e-client-utils.h"
+
+/**
+ * e_client_utils_new:
+ *
+ * Proxy function for e_book_client_utils_new() and e_cal_client_utils_new().
+ **/
+EClient *
+e_client_utils_new (ESource *source, EClientSourceType source_type, GError **error)
+{
+ EClient *res = NULL;
+
+ g_return_val_if_fail (source != NULL, NULL);
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ switch (source_type) {
+ case E_CLIENT_SOURCE_TYPE_CONTACTS:
+ res = E_CLIENT (e_book_client_new (source, error));
+ break;
+ case E_CLIENT_SOURCE_TYPE_EVENTS:
+ res = E_CLIENT (e_cal_client_new (source, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, error));
+ break;
+ case E_CLIENT_SOURCE_TYPE_MEMOS:
+ res = E_CLIENT (e_cal_client_new (source, E_CAL_CLIENT_SOURCE_TYPE_MEMOS, error));
+ break;
+ case E_CLIENT_SOURCE_TYPE_TASKS:
+ res = E_CLIENT (e_cal_client_new (source, E_CAL_CLIENT_SOURCE_TYPE_TASKS, error));
+ break;
+ default:
+ g_return_val_if_reached (NULL);
+ break;
+ }
+
+ return res;
+}
+
+/**
+ * e_client_utils_new_from_uri:
+ *
+ * Proxy function for e_book_client_utils_new_from_uri() and e_cal_client_utils_new_from_uri().
+ **/
+EClient *
+e_client_utils_new_from_uri (const gchar *uri, EClientSourceType source_type, GError **error)
+{
+ EClient *res = NULL;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ switch (source_type) {
+ case E_CLIENT_SOURCE_TYPE_CONTACTS:
+ res = E_CLIENT (e_book_client_new_from_uri (uri, error));
+ break;
+ case E_CLIENT_SOURCE_TYPE_EVENTS:
+ res = E_CLIENT (e_cal_client_new_from_uri (uri, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, error));
+ break;
+ case E_CLIENT_SOURCE_TYPE_MEMOS:
+ res = E_CLIENT (e_cal_client_new_from_uri (uri, E_CAL_CLIENT_SOURCE_TYPE_MEMOS, error));
+ break;
+ case E_CLIENT_SOURCE_TYPE_TASKS:
+ res = E_CLIENT (e_cal_client_new_from_uri (uri, E_CAL_CLIENT_SOURCE_TYPE_TASKS, error));
+ break;
+ default:
+ g_return_val_if_reached (NULL);
+ break;
+ }
+
+ return res;
+}
+
+/**
+ * e_client_utils_new_system:
+ *
+ * Proxy function for e_book_client_utils_new_system() and e_cal_client_utils_new_system().
+ **/
+EClient *
+e_client_utils_new_system (EClientSourceType source_type, GError **error)
+{
+ EClient *res = NULL;
+
+ switch (source_type) {
+ case E_CLIENT_SOURCE_TYPE_CONTACTS:
+ res = E_CLIENT (e_book_client_new_system (error));
+ break;
+ case E_CLIENT_SOURCE_TYPE_EVENTS:
+ res = E_CLIENT (e_cal_client_new_system (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, error));
+ break;
+ case E_CLIENT_SOURCE_TYPE_MEMOS:
+ res = E_CLIENT (e_cal_client_new_system (E_CAL_CLIENT_SOURCE_TYPE_MEMOS, error));
+ break;
+ case E_CLIENT_SOURCE_TYPE_TASKS:
+ res = E_CLIENT (e_cal_client_new_system (E_CAL_CLIENT_SOURCE_TYPE_TASKS, error));
+ break;
+ default:
+ g_return_val_if_reached (NULL);
+ break;
+ }
+
+ return res;
+}
+
+/**
+ * e_client_utils_new_default:
+ *
+ * Proxy function for e_book_client_utils_new_default() and e_cal_client_utils_new_default().
+ **/
+EClient *
+e_client_utils_new_default (EClientSourceType source_type, GError **error)
+{
+ EClient *res = NULL;
+
+ switch (source_type) {
+ case E_CLIENT_SOURCE_TYPE_CONTACTS:
+ res = E_CLIENT (e_book_client_new_default (error));
+ break;
+ case E_CLIENT_SOURCE_TYPE_EVENTS:
+ res = E_CLIENT (e_cal_client_new_default (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, error));
+ break;
+ case E_CLIENT_SOURCE_TYPE_MEMOS:
+ res = E_CLIENT (e_cal_client_new_default (E_CAL_CLIENT_SOURCE_TYPE_MEMOS, error));
+ break;
+ case E_CLIENT_SOURCE_TYPE_TASKS:
+ res = E_CLIENT (e_cal_client_new_default (E_CAL_CLIENT_SOURCE_TYPE_TASKS, error));
+ break;
+ default:
+ g_return_val_if_reached (NULL);
+ break;
+ }
+
+ return res;
+}
+
+/**
+ * e_client_utils_set_default:
+ *
+ * Proxy function for e_book_client_utils_set_default() and e_book_client_utils_set_default().
+ **/
+gboolean
+e_client_utils_set_default (EClient *client, EClientSourceType source_type, GError **error)
+{
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+
+ switch (source_type) {
+ case E_CLIENT_SOURCE_TYPE_CONTACTS:
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+ res = e_book_client_set_default (E_BOOK_CLIENT (client), error);
+ break;
+ case E_CLIENT_SOURCE_TYPE_EVENTS:
+ case E_CLIENT_SOURCE_TYPE_MEMOS:
+ case E_CLIENT_SOURCE_TYPE_TASKS:
+ g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+ res = e_cal_client_set_default (E_CAL_CLIENT (client), error);
+ break;
+ default:
+ g_return_val_if_reached (FALSE);
+ break;
+ }
+
+ return res;
+}
+
+/**
+ * e_client_utils_set_default_source:
+ *
+ * Proxy function for e_book_client_utils_set_default_source() and e_cal_client_utils_set_default_source().
+ **/
+gboolean
+e_client_utils_set_default_source (ESource *source, EClientSourceType source_type, GError **error)
+{
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (source != NULL, FALSE);
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+ switch (source_type) {
+ case E_CLIENT_SOURCE_TYPE_CONTACTS:
+ res = e_book_client_set_default_source (source, error);
+ break;
+ case E_CLIENT_SOURCE_TYPE_EVENTS:
+ res = e_cal_client_set_default_source (source, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, error);
+ break;
+ case E_CLIENT_SOURCE_TYPE_MEMOS:
+ res = e_cal_client_set_default_source (source, E_CAL_CLIENT_SOURCE_TYPE_MEMOS, error);
+ break;
+ case E_CLIENT_SOURCE_TYPE_TASKS:
+ res = e_cal_client_set_default_source (source, E_CAL_CLIENT_SOURCE_TYPE_TASKS, error);
+ break;
+ default:
+ g_return_val_if_reached (FALSE);
+ break;
+ }
+
+ return res;
+}
+
+/**
+ * e_client_utils_get_sources:
+ *
+ * Proxy function for e_book_client_utils_get_sources() and e_cal_client_utils_get_sources().
+ **/
+gboolean
+e_client_utils_get_sources (ESourceList **sources, EClientSourceType source_type, GError **error)
+{
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (sources != NULL, FALSE);
+
+ switch (source_type) {
+ case E_CLIENT_SOURCE_TYPE_CONTACTS:
+ res = e_book_client_get_sources (sources, error);
+ break;
+ case E_CLIENT_SOURCE_TYPE_EVENTS:
+ res = e_cal_client_get_sources (sources, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, error);
+ break;
+ case E_CLIENT_SOURCE_TYPE_MEMOS:
+ res = e_cal_client_get_sources (sources, E_CAL_CLIENT_SOURCE_TYPE_MEMOS, error);
+ break;
+ case E_CLIENT_SOURCE_TYPE_TASKS:
+ res = e_cal_client_get_sources (sources, E_CAL_CLIENT_SOURCE_TYPE_TASKS, error);
+ break;
+ default:
+ g_return_val_if_reached (FALSE);
+ break;
+ }
+
+ return res;
+}
+
+typedef struct _EClientUtilsAsyncOpData
+{
+ EClientUtilsAuthenticateHandler auth_handler;
+ gpointer auth_handler_user_data;
+ GAsyncReadyCallback async_cb;
+ gpointer async_cb_user_data;
+ GCancellable *cancellable;
+ EClient *client;
+ ECredentials *used_credentials;
+ gboolean open_finished;
+ GError *opened_cb_error;
+} EClientUtilsAsyncOpData;
+
+static void
+free_client_utils_async_op_data (EClientUtilsAsyncOpData *async_data)
+{
+ g_return_if_fail (async_data != NULL);
+ g_return_if_fail (async_data->cancellable != NULL);
+ g_return_if_fail (async_data->client != NULL);
+
+ g_signal_handlers_disconnect_matched (async_data->cancellable, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, async_data);
+ g_signal_handlers_disconnect_matched (async_data->client, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, async_data);
+
+ if (async_data->used_credentials)
+ e_credentials_free (async_data->used_credentials);
+ if (async_data->opened_cb_error)
+ g_error_free (async_data->opened_cb_error);
+ g_object_unref (async_data->cancellable);
+ g_object_unref (async_data->client);
+ g_free (async_data);
+}
+
+static gboolean
+complete_async_op_in_idle_cb (gpointer user_data)
+{
+ GSimpleAsyncResult *simple = user_data;
+ gint run_main_depth;
+
+ g_return_val_if_fail (simple != NULL, FALSE);
+
+ run_main_depth = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (simple), "run-main-depth"));
+ if (run_main_depth < 1)
+ run_main_depth = 1;
+
+ /* do not receive in higher level than was initially run */
+ if (g_main_depth () > run_main_depth) {
+ return TRUE;
+ }
+
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ return FALSE;
+}
+
+#define return_async_error_if_fail(expr, async_cb, async_cb_user_data, source_tag) G_STMT_START { \
+ if (G_LIKELY ((expr))) { } else { \
+ GError *error; \
+ \
+ error = g_error_new (E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG, \
+ "%s: assertion '%s' failed", G_STRFUNC, #expr); \
+ \
+ return_async_error (error, async_cb, async_cb_user_data, source_tag); \
+ g_error_free (error); \
+ return; \
+ } \
+ } G_STMT_END
+
+static void
+return_async_error (const GError *error, GAsyncReadyCallback async_cb, gpointer async_cb_user_data, gpointer source_tag)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_if_fail (error != NULL);
+ g_return_if_fail (source_tag != NULL);
+
+ simple = g_simple_async_result_new (NULL, async_cb, async_cb_user_data, source_tag);
+ g_simple_async_result_set_from_error (simple, error);
+
+ g_object_set_data (G_OBJECT (simple), "run-main-depth", GINT_TO_POINTER (g_main_depth ()));
+ g_idle_add (complete_async_op_in_idle_cb, simple);
+}
+
+static void
+client_utils_open_new_done (EClientUtilsAsyncOpData *async_data)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_if_fail (async_data != NULL);
+ g_return_if_fail (async_data->client != NULL);
+
+ /* keep the initial auth_handler connected directly, thus it will be able
+ to answer any later authentication requests, for reconnection, for example
+ */
+ if (async_data->auth_handler)
+ g_signal_connect (async_data->client, "authenticate", G_CALLBACK (async_data->auth_handler), async_data->auth_handler_user_data);
+
+ simple = g_simple_async_result_new (NULL, async_data->async_cb, async_data->async_cb_user_data, e_client_utils_open_new);
+ g_simple_async_result_set_op_res_gpointer (simple, g_object_ref (async_data->client), g_object_unref);
+
+ g_object_set_data (G_OBJECT (simple), "run-main-depth", GINT_TO_POINTER (g_main_depth ()));
+ g_idle_add (complete_async_op_in_idle_cb, simple);
+
+ free_client_utils_async_op_data (async_data);
+}
+
+static void
+client_utils_open_new_cancelled_cb (GCancellable *cancellable, EClientUtilsAsyncOpData *async_data)
+{
+ GError *error = NULL;
+
+ g_return_if_fail (cancellable != NULL);
+ g_return_if_fail (async_data != NULL);
+ g_return_if_fail (async_data->cancellable == cancellable);
+ g_return_if_fail (g_cancellable_set_error_if_cancelled (cancellable, &error));
+
+ return_async_error (error, async_data->async_cb, async_data->async_cb_user_data, e_client_utils_open_new);
+ free_client_utils_async_op_data (async_data);
+ g_error_free (error);
+}
+
+static void
+finish_or_retry_open (EClientUtilsAsyncOpData *async_data, const GError *error)
+{
+ g_return_if_fail (async_data != NULL);
+
+ if (async_data->auth_handler && error && g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_FAILED)) {
+ if (async_data->used_credentials) {
+ const gchar *auth_domain, *prompt_key;
+
+ auth_domain = e_credentials_peek (async_data->used_credentials, E_CREDENTIALS_KEY_AUTH_DOMAIN);
+ prompt_key = e_credentials_peek (async_data->used_credentials, E_CREDENTIALS_KEY_PROMPT_KEY);
+
+ /* make sure the old password is forgotten when authentication failed */
+ if (auth_domain && prompt_key)
+ e_passwords_forget_password (auth_domain, prompt_key);
+
+ e_credentials_set (async_data->used_credentials, E_CREDENTIALS_KEY_PROMPT_REASON, error->message);
+ }
+
+ e_client_process_authentication (async_data->client, async_data->used_credentials);
+ } else if (error) {
+ return_async_error (error, async_data->async_cb, async_data->async_cb_user_data, e_client_utils_open_new);
+ free_client_utils_async_op_data (async_data);
+ } else {
+ client_utils_open_new_done (async_data);
+ }
+}
+
+static void
+client_utils_opened_cb (EClient *client, const GError *error, EClientUtilsAsyncOpData *async_data)
+{
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (async_data != NULL);
+ g_return_if_fail (client == async_data->client);
+
+ if (!async_data->open_finished) {
+ /* there can happen that the "opened" signal is received
+ before the e_client_open() is finished, thus keep detailed
+ error for later use, if any */
+ if (error)
+ async_data->opened_cb_error = g_error_copy (error);
+ } else {
+ finish_or_retry_open (async_data, error);
+ }
+}
+
+static void
+client_utils_open_new_async_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ EClientUtilsAsyncOpData *async_data = user_data;
+ GError *error = NULL;
+
+ g_return_if_fail (source_object != NULL);
+ g_return_if_fail (result != NULL);
+ g_return_if_fail (async_data != NULL);
+ g_return_if_fail (async_data->async_cb != NULL);
+ g_return_if_fail (async_data->client == E_CLIENT (source_object));
+
+ async_data->open_finished = TRUE;
+
+ if (!e_client_open_finish (E_CLIENT (source_object), result, &error)
+ || g_cancellable_set_error_if_cancelled (async_data->cancellable, &error)) {
+ finish_or_retry_open (async_data, error);
+ g_error_free (error);
+ return;
+ }
+
+ if (async_data->opened_cb_error) {
+ finish_or_retry_open (async_data, async_data->opened_cb_error);
+ return;
+ }
+
+ if (e_client_is_opened (async_data->client)) {
+ client_utils_open_new_done (async_data);
+ return;
+ }
+
+ /* wait for 'opened' signal, which is received in client_utils_opened_cb */
+ g_signal_connect (async_data->cancellable, "cancelled", G_CALLBACK (client_utils_open_new_cancelled_cb), async_data);
+}
+
+static gboolean
+client_utils_open_new_auth_cb (EClient *client, ECredentials *credentials, gpointer user_data)
+{
+ EClientUtilsAsyncOpData *async_data = user_data;
+ gboolean handled;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (async_data != NULL, FALSE);
+ g_return_val_if_fail (async_data->auth_handler != NULL, FALSE);
+
+ if (async_data->used_credentials) {
+ const gchar *reason = e_credentials_peek (async_data->used_credentials, E_CREDENTIALS_KEY_PROMPT_REASON);
+
+ if (reason) {
+ e_credentials_set (credentials, E_CREDENTIALS_KEY_PROMPT_TEXT, NULL);
+ e_credentials_set (credentials, E_CREDENTIALS_KEY_PROMPT_REASON, reason);
+ }
+ }
+
+ handled = async_data->auth_handler (client, credentials, async_data->auth_handler_user_data);
+
+ if (handled && credentials) {
+ if (async_data->used_credentials) {
+ gchar *prompt_flags_str;
+ guint prompt_flags = 0;
+
+ e_credentials_free (async_data->used_credentials);
+
+ prompt_flags_str = e_credentials_get (credentials, E_CREDENTIALS_KEY_PROMPT_FLAGS);
+ if (prompt_flags_str) {
+ prompt_flags = e_credentials_util_string_to_prompt_flags (prompt_flags_str);
+ g_free (prompt_flags_str);
+ } else {
+ prompt_flags = E_CREDENTIALS_PROMPT_FLAG_REMEMBER_FOREVER
+ | E_CREDENTIALS_PROMPT_FLAG_SECRET
+ | E_CREDENTIALS_PROMPT_FLAG_ONLINE;
+ }
+
+ prompt_flags |= E_CREDENTIALS_PROMPT_FLAG_REPROMPT;
+
+ prompt_flags_str = e_credentials_util_prompt_flags_to_string (prompt_flags);
+ e_credentials_set (credentials, E_CREDENTIALS_KEY_PROMPT_FLAGS, prompt_flags_str);
+ g_free (prompt_flags_str);
+ }
+
+ async_data->used_credentials = e_credentials_new_clone (credentials);
+ }
+
+ return handled;
+}
+
+/**
+ * e_client_utils_open_new:
+ * @source: an #ESource to be opened
+ * @source_type: an #EClientSourceType of the @source
+ * @only_if_exists: if %TRUE, fail if this client doesn't already exist, otherwise create it first
+ * @auth_handler: authentication handler, to be used; the e_client_utils_authenticate_handler() is usually sufficient
+ * @auth_handler_user_data: user data for @auth_handler function
+ * @cancellable: a #GCancellable; can be %NULL
+ * @async_cb: callback to call when a result is ready
+ * @async_cb_user_data: user data for the @async_cb
+ *
+ * Begins asynchronous opening of a new #EClient corresponding
+ * to the @source of type @source_type. The resulting #EClient
+ * is fully opened and authenticated client, ready to be used.
+ * This call is finished by e_client_utils_open_new_finish()
+ * from the @async_cb.
+ *
+ * Note: the @auth_handler, and its @auth_handler_user_data,
+ * should be valid through whole live of returned #EClient.
+ *
+ * Since: 3.2
+ **/
+void
+e_client_utils_open_new (ESource *source, EClientSourceType source_type, gboolean only_if_exists,
+ EClientUtilsAuthenticateHandler auth_handler, gpointer auth_handler_user_data,
+ GCancellable *cancellable, GAsyncReadyCallback async_cb, gpointer async_cb_user_data)
+{
+ EClient *client;
+ GError *error = NULL;
+ EClientUtilsAsyncOpData *async_data;
+
+ g_return_if_fail (async_cb != NULL);
+ return_async_error_if_fail (source != NULL, async_cb, async_cb_user_data, e_client_utils_open_new);
+ return_async_error_if_fail (E_IS_SOURCE (source), async_cb, async_cb_user_data, e_client_utils_open_new);
+
+ client = e_client_utils_new (source, source_type, &error);
+ if (!client) {
+ return_async_error (error, async_cb, async_cb_user_data, e_client_utils_open_new);
+ g_error_free (error);
+ return;
+ }
+
+ async_data = g_new0 (EClientUtilsAsyncOpData, 1);
+ async_data->auth_handler = auth_handler;
+ async_data->auth_handler_user_data = auth_handler_user_data;
+ async_data->async_cb = async_cb;
+ async_data->async_cb_user_data = async_cb_user_data;
+ async_data->client = client;
+ async_data->open_finished = FALSE;
+ if (cancellable)
+ async_data->cancellable = g_object_ref (cancellable);
+ else
+ async_data->cancellable = g_cancellable_new ();
+
+ if (auth_handler)
+ g_signal_connect (client, "authenticate", G_CALLBACK (client_utils_open_new_auth_cb), async_data);
+
+
+ /* wait till backend notifies about its opened state */
+ g_signal_connect (client, "opened", G_CALLBACK (client_utils_opened_cb), async_data);
+
+ e_client_open (client, only_if_exists, async_data->cancellable, client_utils_open_new_async_cb, async_data);
+}
+
+/**
+ * e_client_utils_open_new_finish:
+ * @result: a #GAsyncResult
+ * @client: (out): Return value for an #EClient.
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_client_utils_open_new() and
+ * sets @client to a fully opened and authenticated #EClient.
+ * This @client, if not NULL, should be freed with g_object_unref().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_utils_open_new_finish (GAsyncResult *result, EClient **client, GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (result != NULL, FALSE);
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, e_client_utils_open_new), FALSE);
+
+ *client = NULL;
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ *client = g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
+
+ return *client != NULL;
+}
+
+/* This function is suitable as a handler for EClient::authenticate signal.
+ It takes care of all the password prompt and such and returns TRUE if
+ credentials (password) were provided. Thus just connect it to that signal
+ and it'll take care of everything else.
+*/
+gboolean
+e_client_utils_authenticate_handler (EClient *client, ECredentials *credentials, gpointer unused_user_data)
+{
+ ESource *source;
+ gboolean is_book, is_cal, res, remember_password = FALSE;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (credentials != NULL, FALSE);
+
+ is_book = E_IS_BOOK_CLIENT (client);
+ is_cal = !is_book && E_IS_CAL_CLIENT (client);
+ g_return_val_if_fail (is_book || is_cal, FALSE);
+
+ source = e_client_get_source (client);
+ g_return_val_if_fail (source != NULL, FALSE);
+
+ if (!e_credentials_has_key (credentials, E_CREDENTIALS_KEY_USERNAME)) {
+ e_credentials_set (credentials, E_CREDENTIALS_KEY_USERNAME, e_source_get_property (source, "username"));
+
+ /* no username set on the source - deny authentication request until
+ username will be also enterable with e-passwords */
+ if (!e_credentials_has_key (credentials, E_CREDENTIALS_KEY_USERNAME))
+ return FALSE;
+ }
+
+ if (!e_credentials_has_key (credentials, E_CREDENTIALS_KEY_AUTH_DOMAIN))
+ e_credentials_set (credentials, E_CREDENTIALS_KEY_AUTH_DOMAIN, is_book ? E_CREDENTIALS_AUTH_DOMAIN_ADDRESSBOOK : E_CREDENTIALS_AUTH_DOMAIN_CALENDAR);
+
+ if (!e_credentials_has_key (credentials, E_CREDENTIALS_KEY_PROMPT_TEXT)) {
+ gchar *prompt, *reason;
+ gchar *username_markup, *source_name_markup;
+
+ reason = e_credentials_get (credentials, E_CREDENTIALS_KEY_PROMPT_REASON);
+ username_markup = g_markup_printf_escaped ("<b>%s</b>", e_credentials_peek (credentials, E_CREDENTIALS_KEY_USERNAME));
+ source_name_markup = g_markup_printf_escaped ("<b>%s</b>", e_source_peek_name (source));
+
+
+ if (reason && *reason)
+ prompt = g_strdup_printf (_("Enter password for %s (user %s)\nReason: %s"), source_name_markup, username_markup, reason);
+ else
+ prompt = g_strdup_printf (_("Enter password for %s (user %s)"), source_name_markup, username_markup);
+
+ e_credentials_set (credentials, E_CREDENTIALS_KEY_PROMPT_TEXT, prompt);
+
+ g_free (username_markup);
+ g_free (source_name_markup);
+ g_free (reason);
+ g_free (prompt);
+ }
+
+ if (!e_credentials_has_key (credentials, E_CREDENTIALS_KEY_PROMPT_KEY)) {
+ SoupURI *suri;
+ gchar *uri_str;
+
+ suri = soup_uri_new (e_client_get_uri (client));
+ g_return_val_if_fail (suri != NULL, FALSE);
+
+ soup_uri_set_user (suri, e_credentials_peek (credentials, E_CREDENTIALS_KEY_USERNAME));
+ soup_uri_set_password (suri, NULL);
+ soup_uri_set_fragment (suri, NULL);
+
+ uri_str = soup_uri_to_string (suri, FALSE);
+
+ e_credentials_set (credentials, E_CREDENTIALS_KEY_PROMPT_KEY, uri_str);
+
+ g_free (uri_str);
+ soup_uri_free (suri);
+ }
+
+ remember_password = g_strcmp0 (e_source_get_property (source, "remember_password"), "true") == 0;
+
+ res = e_credentials_authenticate_helper (credentials, NULL, &remember_password);
+
+ if (res)
+ e_source_set_property (source, "remember_password", remember_password ? "true" : NULL);
+
+ e_credentials_clear_peek (credentials);
+
+ return res;
+}
+
+/* Asks for a password based on the provided credentials information.
+ Credentials should have set following keys:
+ E_CREDENTIALS_KEY_USERNAME
+ E_CREDENTIALS_KEY_AUTH_DOMAIN
+ E_CREDENTIALS_KEY_PROMPT_TEXT
+ E_CREDENTIALS_KEY_PROMPT_KEY
+ all other keys are optional. If also E_CREDENTIALS_KEY_PASSWORD key is provided,
+ then it implies a reprompt.
+
+ When this returns TRUE, then the structure contains E_CREDENTIALS_KEY_PASSWORD set
+ as entered by a user.
+*/
+gboolean
+e_credentials_authenticate_helper (ECredentials *credentials, GtkWindow *parent, gboolean *remember_password)
+{
+ gboolean res, fake_remember_password = FALSE;
+ guint prompt_flags;
+ gchar *password = NULL;
+ const gchar *title, *auth_domain, *prompt_key;
+
+ g_return_val_if_fail (credentials != NULL, FALSE);
+ g_return_val_if_fail (e_credentials_has_key (credentials, E_CREDENTIALS_KEY_USERNAME), FALSE);
+ g_return_val_if_fail (e_credentials_has_key (credentials, E_CREDENTIALS_KEY_AUTH_DOMAIN), FALSE);
+ g_return_val_if_fail (e_credentials_has_key (credentials, E_CREDENTIALS_KEY_PROMPT_TEXT), FALSE);
+ g_return_val_if_fail (e_credentials_has_key (credentials, E_CREDENTIALS_KEY_PROMPT_KEY), FALSE);
+
+ if (e_credentials_has_key (credentials, E_CREDENTIALS_KEY_PROMPT_FLAGS)) {
+ prompt_flags = e_credentials_util_string_to_prompt_flags (e_credentials_peek (credentials, E_CREDENTIALS_KEY_PROMPT_FLAGS));
+ } else {
+ prompt_flags = E_CREDENTIALS_PROMPT_FLAG_REMEMBER_FOREVER
+ | E_CREDENTIALS_PROMPT_FLAG_SECRET
+ | E_CREDENTIALS_PROMPT_FLAG_ONLINE;
+ }
+
+ if (!remember_password) {
+ prompt_flags |= E_CREDENTIALS_PROMPT_FLAG_DISABLE_REMEMBER;
+ remember_password = &fake_remember_password;
+ }
+
+ if (e_credentials_has_key (credentials, E_CREDENTIALS_KEY_PASSWORD))
+ prompt_flags |= E_CREDENTIALS_PROMPT_FLAG_REPROMPT;
+
+ if (e_credentials_has_key (credentials, E_CREDENTIALS_KEY_PROMPT_TITLE))
+ title = e_credentials_peek (credentials, E_CREDENTIALS_KEY_PROMPT_TITLE);
+ else if (prompt_flags & E_CREDENTIALS_PROMPT_FLAG_PASSPHRASE)
+ title = _("Enter Passphrase");
+ else
+ title = _("Enter Password");
+
+ auth_domain = e_credentials_peek (credentials, E_CREDENTIALS_KEY_AUTH_DOMAIN);
+ prompt_key = e_credentials_peek (credentials, E_CREDENTIALS_KEY_PROMPT_KEY);
+
+ if (!(prompt_flags & E_CREDENTIALS_PROMPT_FLAG_REPROMPT))
+ password = e_passwords_get_password (auth_domain, prompt_key);
+
+ if (!password)
+ password = e_passwords_ask_password (title, auth_domain, prompt_key,
+ e_credentials_peek (credentials, E_CREDENTIALS_KEY_PROMPT_TEXT),
+ prompt_flags, remember_password, parent);
+
+ res = password != NULL;
+
+ if (res)
+ e_credentials_set (credentials, E_CREDENTIALS_KEY_PASSWORD, password);
+
+ e_credentials_util_safe_free_string (password);
+ e_credentials_clear_peek (credentials);
+
+ return res;
+}
diff --git a/libedataserverui/e-client-utils.h b/libedataserverui/e-client-utils.h
new file mode 100644
index 0000000..b6a189f
--- /dev/null
+++ b/libedataserverui/e-client-utils.h
@@ -0,0 +1,61 @@
+/*
+ * e-client-utils.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/>
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_CLIENT_UTILS_H
+#define E_CLIENT_UTILS_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include <libedataserver/e-client.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ E_CLIENT_SOURCE_TYPE_CONTACTS,
+ E_CLIENT_SOURCE_TYPE_EVENTS,
+ E_CLIENT_SOURCE_TYPE_MEMOS,
+ E_CLIENT_SOURCE_TYPE_TASKS,
+ E_CLIENT_SOURCE_TYPE_LAST
+} EClientSourceType;
+
+typedef gboolean (* EClientUtilsAuthenticateHandler) (EClient *client, ECredentials *credentials, gpointer user_data);
+
+EClient * e_client_utils_new (ESource *source, EClientSourceType source_type, GError **error);
+EClient * e_client_utils_new_from_uri (const gchar *uri, EClientSourceType source_type, GError **error);
+EClient * e_client_utils_new_system (EClientSourceType source_type, GError **error);
+EClient * e_client_utils_new_default (EClientSourceType source_type, GError **error);
+
+gboolean e_client_utils_set_default (EClient *client, EClientSourceType source_type, GError **error);
+gboolean e_client_utils_set_default_source (ESource *source, EClientSourceType source_type, GError **error);
+gboolean e_client_utils_get_sources (ESourceList **sources, EClientSourceType source_type, GError **error);
+
+void e_client_utils_open_new (ESource *source, EClientSourceType source_type, gboolean only_if_exists,
+ EClientUtilsAuthenticateHandler auth_handler, gpointer auth_handler_user_data,
+ GCancellable *cancellable, GAsyncReadyCallback async_cb, gpointer async_cb_user_data);
+gboolean e_client_utils_open_new_finish (GAsyncResult *result, EClient **client, GError **error);
+
+gboolean e_client_utils_authenticate_handler (EClient *client, ECredentials *credentials, gpointer unused_user_data);
+gboolean e_credentials_authenticate_helper (ECredentials *credentials, GtkWindow *parent, gboolean *remember_password);
+
+G_END_DECLS
+
+#endif /* E_CLIENT_UTILS_H */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index e1e39a0..e96df5b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -8,8 +8,11 @@ addressbook/backends/ldap/e-book-backend-ldap.c
addressbook/backends/vcf/e-book-backend-vcf.c
addressbook/backends/webdav/e-book-backend-webdav.c
addressbook/libebook/e-book.c
+addressbook/libebook/e-book-client.c
+addressbook/libebook/e-book-client-view.c
addressbook/libebook/e-contact.c
addressbook/libebook/e-destination.c
+addressbook/libedata-book/e-book-backend.c
addressbook/libedata-book/e-data-book-factory.c
addressbook/libedata-book/e-data-book.c
calendar/backends/caldav/e-cal-backend-caldav.c
@@ -19,12 +22,15 @@ calendar/backends/groupwise/e-cal-backend-groupwise-utils.c
calendar/backends/groupwise/e-cal-backend-groupwise.c
calendar/backends/http/e-cal-backend-http.c
calendar/backends/weather/e-cal-backend-weather.c
+calendar/libecal/e-cal-client.c
+calendar/libecal/e-cal-client-view.c
calendar/libecal/e-cal-component.c
calendar/libecal/e-cal-recur.c
calendar/libecal/e-cal-util.c
calendar/libecal/e-cal.c
calendar/libedata-cal/e-cal-backend-sexp.c
calendar/libedata-cal/e-cal-backend-util.c
+calendar/libedata-cal/e-cal-backend.c
calendar/libedata-cal/e-data-cal.c
calendar/libedata-cal/e-data-cal-factory.c
camel/camel-address.c
@@ -184,11 +190,13 @@ camel/providers/sendmail/camel-sendmail-transport.c
camel/providers/smtp/camel-smtp-provider.c
camel/providers/smtp/camel-smtp-transport.c
libedataserver/e-categories.c
+libedataserver/e-client.c
libedataserver/e-time-utils.c
libedataserverui/e-book-auth-util.c
libedataserverui/e-categories-dialog.c
libedataserverui/e-category-completion.c
libedataserverui/e-cell-renderer-color.c
+libedataserverui/e-client-utils.c
libedataserverui/e-name-selector-dialog.c
libedataserverui/e-name-selector-entry.c
libedataserverui/e-name-selector-list.c
diff --git a/tests/libebook/Makefile.am b/tests/libebook/Makefile.am
index 90a1e60..ac23d45 100644
--- a/tests/libebook/Makefile.am
+++ b/tests/libebook/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = vcard
+SUBDIRS = vcard client
noinst_LTLIBRARIES = libebook-test-utils.la
libebook_test_utils_la_SOURCES = ebook-test-utils.c ebook-test-utils.h
diff --git a/tests/libebook/client/Makefile.am b/tests/libebook/client/Makefile.am
new file mode 100644
index 0000000..9f1b832
--- /dev/null
+++ b/tests/libebook/client/Makefile.am
@@ -0,0 +1,98 @@
+noinst_LTLIBRARIES = libclient-test-utils.la
+
+libclient_test_utils_la_SOURCES = client-test-utils.c client-test-utils.h
+
+libclient_test_utils_la_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ -I$(top_srcdir)/addressbook \
+ -I$(top_builddir)/addressbook \
+ -DSRCDIR=\""$(srcdir)"\" \
+ $(EVOLUTION_ADDRESSBOOK_CFLAGS) \
+ $(NULL)
+
+libclient_test_utils_la_LIBADD = \
+ $(top_builddir)/addressbook/libebook/libebook-1.2.la \
+ $(EVOLUTION_ADDRESSBOOK_LIBS) \
+ $(NULL)
+
+# Should be kept ordered approximately from least to most difficult/complex
+TESTS = \
+ test-client-remove \
+ test-client-examine \
+ test-client-refresh \
+ test-client-add-contact \
+ test-client-get-contact \
+ test-client-get-view \
+ test-client-modify-contact \
+ test-client-remove-contact \
+ test-client-remove-contact-by-uid \
+ test-client-remove-contacts \
+ test-client-stress-factory--serial \
+ test-client-stress-factory--fifo \
+ test-client-stress-factory--single-book \
+ $(NULL)
+
+noinst_PROGRAMS = \
+ $(TESTS) \
+ test-client \
+ test-client-async \
+ test-client-nonexistent-id \
+ test-client-search \
+ test-client-self \
+ test-client-stress-views \
+ $(NULL)
+
+TEST_CPPFLAGS = \
+ $(libclient_test_utils_la_CPPFLAGS) \
+ $(EVOLUTION_ADDRESSBOOK_CPPFLAGS) \
+ $(NULL)
+
+TEST_LIBS = \
+ $(libclient_test_utils_la_LIBS) \
+ libclient-test-utils.la \
+ $(top_builddir)/addressbook/libebook/libebook-1.2.la \
+ $(EVOLUTION_ADDRESSBOOK_LIBS) \
+ $(NULL)
+
+test_client_LDADD=$(TEST_LIBS)
+test_client_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_async_LDADD=$(TEST_LIBS)
+test_client_async_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_add_contact_LDADD=$(TEST_LIBS)
+test_client_add_contact_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_examine_LDADD=$(TEST_LIBS)
+test_client_examine_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_get_contact_LDADD=$(TEST_LIBS)
+test_client_get_contact_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_get_view_LDADD=$(TEST_LIBS)
+test_client_get_view_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_modify_contact_LDADD=$(TEST_LIBS)
+test_client_modify_contact_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_refresh_LDADD=$(TEST_LIBS)
+test_client_refresh_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_remove_LDADD=$(TEST_LIBS)
+test_client_remove_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_remove_contact_LDADD=$(TEST_LIBS)
+test_client_remove_contact_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_remove_contact_by_uid_LDADD=$(TEST_LIBS)
+test_client_remove_contact_by_uid_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_remove_contacts_LDADD=$(TEST_LIBS)
+test_client_remove_contacts_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_stress_factory__fifo_LDADD=$(TEST_LIBS)
+test_client_stress_factory__fifo_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_stress_factory__serial_LDADD=$(TEST_LIBS)
+test_client_stress_factory__serial_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_stress_factory__single_book_LDADD=$(TEST_LIBS)
+test_client_stress_factory__single_book_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_nonexistent_id_LDADD=$(TEST_LIBS)
+test_client_nonexistent_id_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_search_LDADD=$(TEST_LIBS)
+test_client_search_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_self_LDADD=$(TEST_LIBS)
+test_client_self_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_stress_views_LDADD=$(TEST_LIBS)
+test_client_stress_views_CPPFLAGS=$(TEST_CPPFLAGS)
+
+-include $(top_srcdir)/git.mk
diff --git a/tests/libebook/client/client-test-utils.c b/tests/libebook/client/client-test-utils.c
new file mode 100644
index 0000000..13acd6a
--- /dev/null
+++ b/tests/libebook/client/client-test-utils.c
@@ -0,0 +1,433 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdio.h>
+
+#include "client-test-utils.h"
+
+void
+report_error (const gchar *operation, GError **error)
+{
+ g_return_if_fail (operation != NULL);
+
+ g_printerr ("Failed to %s: %s\n", operation, (error && *error) ? (*error)->message : "Unknown error");
+
+ g_clear_error (error);
+}
+
+void
+print_email (EContact *contact)
+{
+ const gchar *file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS);
+ const gchar *name_or_org = e_contact_get_const (contact, E_CONTACT_NAME_OR_ORG);
+ GList *emails, *e;
+
+ g_print (" Contact: %s\n", file_as);
+ g_print (" Name or org: %s\n", name_or_org);
+ g_print (" Email addresses:\n");
+ emails = e_contact_get (contact, E_CONTACT_EMAIL);
+ for (e = emails; e; e = e->next) {
+ g_print ("\t%s\n", (gchar *)e->data);
+ }
+ g_list_foreach (emails, (GFunc)g_free, NULL);
+ g_list_free (emails);
+
+ g_print ("\n");
+}
+
+EBookClient *
+open_system_book (gboolean only_if_exists)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+
+ main_initialize ();
+
+ book_client = e_book_client_new_system (&error);
+ if (error) {
+ report_error ("create system addressbook", &error);
+ return NULL;
+ }
+
+ if (!e_client_open_sync (E_CLIENT (book_client), only_if_exists, NULL, &error)) {
+ g_object_unref (book_client);
+ report_error ("open client sync", &error);
+ return NULL;
+ }
+
+ return book_client;
+}
+
+void
+main_initialize (void)
+{
+ static gboolean initialized = FALSE;
+
+ if (initialized)
+ return;
+
+ g_type_init ();
+ g_thread_init (NULL);
+
+ initialized = TRUE;
+}
+
+struct IdleData {
+ GThreadFunc func;
+ gpointer data;
+ gboolean run_in_thread; /* FALSE to run in idle callback */
+};
+
+static gboolean
+idle_cb (gpointer data)
+{
+ struct IdleData *idle = data;
+
+ g_return_val_if_fail (idle != NULL, FALSE);
+ g_return_val_if_fail (idle->func != NULL, FALSE);
+
+ if (idle->run_in_thread) {
+ GError *error = NULL;
+
+ g_thread_create (idle->func, idle->data, FALSE, &error);
+
+ if (error) {
+ report_error ("create thread", &error);
+ stop_main_loop (1);
+ }
+ } else {
+ idle->func (idle->data);
+ }
+
+ g_free (idle);
+
+ return FALSE;
+}
+
+static GMainLoop *loop = NULL;
+static gint main_stop_result = 0;
+
+static void
+do_start (GThreadFunc func, gpointer data)
+{
+ main_initialize ();
+
+ g_return_if_fail (loop == NULL);
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ if (func)
+ func (data);
+
+ g_main_loop_run (loop);
+
+ g_main_loop_unref (loop);
+ loop = NULL;
+}
+
+/* Starts new main-loop, but just before that calls 'func'.
+ Main-loop is kept running, and this function blocks,
+ until call of stop_main_loop().
+*/
+void
+start_main_loop (GThreadFunc func, gpointer data)
+{
+ g_return_if_fail (loop == NULL);
+
+ do_start (func, data);
+}
+
+/* Starts new main-loop and then invokes func in a new thread.
+ Main-loop is kept running, and this function blocks,
+ until call of stop_main_loop().
+*/
+void
+start_in_thread_with_main_loop (GThreadFunc func, gpointer data)
+{
+ struct IdleData *idle;
+
+ g_return_if_fail (func != NULL);
+ g_return_if_fail (loop == NULL);
+
+ main_initialize ();
+
+ idle = g_new0 (struct IdleData, 1);
+ idle->func = func;
+ idle->data = data;
+ idle->run_in_thread = TRUE;
+
+ g_idle_add (idle_cb, idle);
+
+ do_start (NULL, NULL);
+}
+
+/* Starts new main-loop and then invokes func in an idle callback.
+ Main-loop is kept running, and this function blocks,
+ until call of stop_main_loop().
+*/
+void
+start_in_idle_with_main_loop (GThreadFunc func, gpointer data)
+{
+ struct IdleData *idle;
+
+ g_return_if_fail (func != NULL);
+ g_return_if_fail (loop == NULL);
+
+ main_initialize ();
+
+ idle = g_new0 (struct IdleData, 1);
+ idle->func = func;
+ idle->data = data;
+ idle->run_in_thread = FALSE;
+
+ g_idle_add (idle_cb, idle);
+
+ do_start (NULL, NULL);
+}
+
+/* Stops main-loop previously run by start_main_loop,
+ start_in_thread_with_main_loop or start_in_idle_with_main_loop.
+*/
+void
+stop_main_loop (gint stop_result)
+{
+ g_return_if_fail (loop != NULL);
+
+ main_stop_result = stop_result;
+ g_main_loop_quit (loop);
+}
+
+/* returns value used in stop_main_loop() */
+gint
+get_main_loop_stop_result (void)
+{
+ return main_stop_result;
+}
+
+void
+foreach_configured_source (void (*func) (ESource *source))
+{
+ gpointer foreach_async_data;
+ ESource *source = NULL;
+
+ g_return_if_fail (func != NULL);
+
+ main_initialize ();
+
+ foreach_async_data = foreach_configured_source_async_start (&source);
+ if (!foreach_async_data)
+ return;
+
+ do {
+ func (source);
+ } while (foreach_configured_source_async_next (&foreach_async_data, &source));
+}
+
+struct ForeachConfiguredData
+{
+ ESourceList *source_list;
+ GSList *current_group;
+ GSList *current_source;
+};
+
+gpointer
+foreach_configured_source_async_start (ESource **source)
+{
+ struct ForeachConfiguredData *async_data;
+ ESourceList *source_list = NULL;
+ GError *error = NULL;
+
+ g_return_val_if_fail (source != NULL, NULL);
+
+ main_initialize ();
+
+ if (!e_book_client_get_sources (&source_list, &error)) {
+ report_error ("get addressbooks", &error);
+ return NULL;
+ }
+
+ g_return_val_if_fail (source_list != NULL, NULL);
+
+ async_data = g_new0 (struct ForeachConfiguredData, 1);
+ async_data->source_list = source_list;
+ async_data->current_group = e_source_list_peek_groups (source_list);
+ if (!async_data->current_group) {
+ gpointer ad = async_data;
+
+ foreach_configured_source_async_next (&ad, source);
+ return ad;
+ }
+
+ async_data->current_source = e_source_group_peek_sources (async_data->current_group->data);
+ if (!async_data->current_source) {
+ gpointer ad = async_data;
+
+ if (foreach_configured_source_async_next (&ad, source))
+ return ad;
+
+ return NULL;
+ }
+
+ *source = async_data->current_source->data;
+
+ return async_data;
+}
+
+gboolean
+foreach_configured_source_async_next (gpointer *foreach_async_data, ESource **source)
+{
+ struct ForeachConfiguredData *async_data;
+
+ g_return_val_if_fail (foreach_async_data != NULL, FALSE);
+ g_return_val_if_fail (source != NULL, FALSE);
+
+ async_data = *foreach_async_data;
+ g_return_val_if_fail (async_data != NULL, FALSE);
+ g_return_val_if_fail (async_data->source_list != NULL, FALSE);
+ g_return_val_if_fail (async_data->current_group != NULL, FALSE);
+
+ if (async_data->current_source)
+ async_data->current_source = async_data->current_source->next;
+ if (async_data->current_source) {
+ *source = async_data->current_source->data;
+ return TRUE;
+ }
+
+ do {
+ async_data->current_group = async_data->current_group->next;
+ if (async_data->current_group)
+ async_data->current_source = e_source_group_peek_sources (async_data->current_group->data);
+ } while (async_data->current_group && !async_data->current_source);
+
+ if (async_data->current_source) {
+ *source = async_data->current_source->data;
+ return TRUE;
+ }
+
+ g_object_unref (async_data->source_list);
+ g_free (async_data);
+
+ *foreach_async_data = NULL;
+
+ return FALSE;
+}
+
+EBookClient *
+new_temp_client (gchar **uri)
+{
+ EBookClient *book_client;
+ ESource *source;
+ gchar *abs_uri, *filename;
+ gint handle;
+ GError *error = NULL;
+
+ filename = g_build_filename (g_get_tmp_dir (), "e-book-client-test-XXXXXX/", NULL);
+ handle = g_mkstemp (filename);
+
+ if (handle != -1)
+ close (handle);
+
+ g_return_val_if_fail (g_mkdir_with_parents (filename, 0700) == 0, NULL);
+
+ abs_uri = g_strconcat ("local://", filename, NULL);
+ g_free (filename);
+
+ source = e_source_new_with_absolute_uri ("Test book", abs_uri);
+ if (uri)
+ *uri = abs_uri;
+ else
+ g_free (abs_uri);
+
+ g_return_val_if_fail (source != NULL, NULL);
+
+ book_client = e_book_client_new (source, &error);
+ g_object_unref (source);
+
+ if (error)
+ report_error ("new temp client", &error);
+
+ return book_client;
+}
+
+gchar *
+new_vcard_from_test_case (const gchar *case_name)
+{
+ gchar *filename;
+ gchar *case_filename;
+ GFile* file;
+ GError *error = NULL;
+ gchar *vcard;
+
+ case_filename = g_strdup_printf ("%s.vcf", case_name);
+ filename = g_build_filename (SRCDIR, "..", "data", "vcards", case_filename, NULL);
+ file = g_file_new_for_path (filename);
+ if (!g_file_load_contents (file, NULL, &vcard, NULL, NULL, &error)) {
+ g_warning ("failed to read test contact file '%s': %s",
+ filename, error->message);
+ exit (1);
+ }
+
+ g_free (case_filename);
+ g_free (filename);
+ g_object_unref (file);
+
+ return vcard;
+}
+
+static gboolean
+contacts_are_equal_shallow (EContact *a, EContact *b)
+{
+ const gchar *uid_a, *uid_b;
+
+ /* Avoid warnings if one or more are NULL, to make this function
+ * "NULL-friendly" */
+ if (!a && !b)
+ return TRUE;
+
+ if (!E_IS_CONTACT (a) || !E_IS_CONTACT (b))
+ return FALSE;
+
+ uid_a = e_contact_get_const (a, E_CONTACT_UID);
+ uid_b = e_contact_get_const (b, E_CONTACT_UID);
+
+ return g_strcmp0 (uid_a, uid_b) == 0;
+}
+
+gboolean
+add_contact_from_test_case_verify (EBookClient *book_client, const gchar *case_name, EContact **contact)
+{
+ gchar *vcard;
+ EContact *contact_orig;
+ EContact *contact_final;
+ gchar *uid;
+ GError *error = NULL;
+
+ vcard = new_vcard_from_test_case (case_name);
+ contact_orig = e_contact_new_from_vcard (vcard);
+ g_free (vcard);
+ if (!e_book_client_add_contact_sync (book_client, contact_orig, &uid, NULL, &error)) {
+ report_error ("add contact sync", &error);
+ g_object_unref (contact_orig);
+ return FALSE;
+ }
+
+ e_contact_set (contact_orig, E_CONTACT_UID, uid);
+
+ if (!e_book_client_get_contact_sync (book_client, uid, &contact_final, NULL, &error)) {
+ report_error ("get contact sync", &error);
+ g_object_unref (contact_orig);
+ g_free (uid);
+ return FALSE;
+ }
+
+ /* verify the contact was added "successfully" (not thorough) */
+ g_assert (contacts_are_equal_shallow (contact_orig, contact_final));
+
+ if (contact)
+ *contact = contact_final;
+ else
+ g_object_unref (contact_final);
+ g_object_unref (contact_orig);
+ g_free (uid);
+
+ return TRUE;
+}
diff --git a/tests/libebook/client/client-test-utils.h b/tests/libebook/client/client-test-utils.h
new file mode 100644
index 0000000..5d33d95
--- /dev/null
+++ b/tests/libebook/client/client-test-utils.h
@@ -0,0 +1,27 @@
+#ifndef CLIENT_TEST_UTILS_H
+#define CLIENT_TEST_UTILS_H
+
+#include <glib.h>
+#include <libebook/e-book-client.h>
+#include <libebook/e-contact.h>
+
+void report_error (const gchar *operation, GError **error);
+void print_email (EContact *contact);
+EBookClient *open_system_book (gboolean only_if_exists);
+
+void main_initialize (void);
+void start_main_loop (GThreadFunc func, gpointer data);
+void start_in_thread_with_main_loop (GThreadFunc func, gpointer data);
+void start_in_idle_with_main_loop (GThreadFunc func, gpointer data);
+void stop_main_loop (gint stop_result);
+gint get_main_loop_stop_result (void);
+
+void foreach_configured_source (void (*func) (ESource *source));
+gpointer foreach_configured_source_async_start (ESource **source);
+gboolean foreach_configured_source_async_next (gpointer *foreach_async_data, ESource **source);
+
+EBookClient *new_temp_client (gchar **uri);
+gboolean add_contact_from_test_case_verify (EBookClient *book_client, const gchar *case_name, EContact **contact);
+gchar *new_vcard_from_test_case (const gchar *case_name);
+
+#endif /* CLIENT_TEST_UTILS_H */
diff --git a/tests/libebook/client/test-client-add-contact.c b/tests/libebook/client/test-client-add-contact.c
new file mode 100644
index 0000000..24b3de1
--- /dev/null
+++ b/tests/libebook/client/test-client-add-contact.c
@@ -0,0 +1,95 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libebook/e-book-client.h>
+
+#include "client-test-utils.h"
+
+static void
+add_contact_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ GError *error = NULL;
+ gchar *uid;
+
+ if (!e_book_client_add_contact_finish (E_BOOK_CLIENT (source_object), result, &uid, &error)) {
+ report_error ("add contact finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ printf ("Contact added as '%s'\n", uid);
+ g_free (uid);
+ stop_main_loop (0);
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+ EContact *contact;
+ gchar *vcard;
+
+ main_initialize ();
+
+ /*
+ * Setup
+ */
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ /*
+ * Sync version
+ */
+ if (!add_contact_from_test_case_verify (book_client, "simple-1", &contact)) {
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (contact);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ /*
+ * Async version
+ */
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ vcard = new_vcard_from_test_case ("simple-1");
+ contact = e_contact_new_from_vcard (vcard);
+ g_free (vcard);
+
+ e_book_client_add_contact (book_client, contact, NULL, add_contact_cb, NULL);
+ g_object_unref (contact);
+
+ start_main_loop (NULL, NULL);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libebook/client/test-client-async.c b/tests/libebook/client/test-client-async.c
new file mode 100644
index 0000000..e3cc419
--- /dev/null
+++ b/tests/libebook/client/test-client-async.c
@@ -0,0 +1,121 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libebook/e-book-client.h>
+#include <libebook/e-book-query.h>
+
+#include "client-test-utils.h"
+
+static void
+print_all_emails_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ EBookClient *book_client;
+ GSList *contacts = NULL, *c;
+ GError *error = NULL;
+
+ book_client = E_BOOK_CLIENT (source_object);
+ g_return_if_fail (book_client != NULL);
+
+ if (!e_book_client_get_contacts_finish (book_client, result, &contacts, &error)) {
+ report_error ("get contacts finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ for (c = contacts; c; c = c->next) {
+ EContact *contact = E_CONTACT (c->data);
+
+ print_email (contact);
+ }
+
+ g_slist_foreach (contacts, (GFunc) g_object_unref, NULL);
+ g_slist_free (contacts);
+
+ stop_main_loop (0);
+}
+
+static void
+print_all_emails (EBookClient *book_client)
+{
+ EBookQuery *query;
+ gchar *sexp;
+
+ query = e_book_query_field_exists (E_CONTACT_FULL_NAME);
+ sexp = e_book_query_to_string (query);
+ e_book_query_unref (query);
+
+ e_book_client_get_contacts (book_client, sexp, NULL, print_all_emails_cb, NULL);
+
+ g_free (sexp);
+}
+
+static void
+print_email_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ EBookClient *book_client;
+ EContact *contact = NULL;
+ GError *error = NULL;
+
+ book_client = E_BOOK_CLIENT (source_object);
+ g_return_if_fail (book_client != NULL);
+
+ if (!e_book_client_get_contact_finish (book_client, result, &contact, &error)) {
+ report_error ("get contact finish", &error);
+ } else {
+ print_email (contact);
+ g_object_unref (contact);
+ }
+
+ printf ("printing all contacts\n");
+ print_all_emails (book_client);
+}
+
+static void
+print_one_email (EBookClient *book_client)
+{
+ e_book_client_get_contact (book_client, "pas-id-0002023", NULL, print_email_cb, NULL);
+}
+
+static void
+client_loaded_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+
+ book_client = E_BOOK_CLIENT (source_object);
+ g_return_if_fail (book_client != NULL);
+
+ if (!e_client_open_finish (E_CLIENT (book_client), result, &error)) {
+ report_error ("client open finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ printf ("printing one contact\n");
+ print_one_email (book_client);
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+
+ main_initialize ();
+
+ book_client = e_book_client_new_system (&error);
+ if (error) {
+ report_error ("create system addressbook", &error);
+ return 1;
+ }
+
+ printf ("loading addressbook\n");
+
+ e_client_open (E_CLIENT (book_client), FALSE, NULL, client_loaded_cb, NULL);
+
+ start_main_loop (NULL, NULL);
+
+ g_object_unref (book_client);
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libebook/client/test-client-examine.c b/tests/libebook/client/test-client-examine.c
new file mode 100644
index 0000000..687c74a
--- /dev/null
+++ b/tests/libebook/client/test-client-examine.c
@@ -0,0 +1,399 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <string.h>
+#include <libebook/e-book-client.h>
+#include <libedataserver/e-source-group.h>
+
+#include "client-test-utils.h"
+
+static gint running_async = 0;
+
+static GSList *
+get_known_prop_names (void)
+{
+ GSList *prop_names = NULL;
+
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENED);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENING);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_ONLINE);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_READONLY);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CACHE_DIR);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CAPABILITIES);
+ prop_names = g_slist_append (prop_names, (gpointer) BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS);
+ prop_names = g_slist_append (prop_names, (gpointer) BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS);
+ prop_names = g_slist_append (prop_names, (gpointer) BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS);
+
+ return prop_names;
+}
+
+typedef struct _ExtraValues {
+ gpointer async_data;
+
+ GSList *todo_prop_names;
+ GHashTable *retrieved_props;
+} ExtraValues;
+
+static void
+extra_values_free (ExtraValues *evals)
+{
+ if (!evals)
+ return;
+
+ g_slist_free (evals->todo_prop_names);
+ g_hash_table_destroy (evals->retrieved_props);
+ g_free (evals);
+}
+
+static void
+print_each_property (gpointer prop_name, gpointer prop_value, gpointer user_data)
+{
+ g_return_if_fail (prop_name != NULL);
+
+ if (prop_value == NULL) {
+ g_print ("\t %s: NULL\n", (const gchar *) prop_name);
+ return;
+ }
+
+ g_print ("\t %s: ", (const gchar *) prop_name);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES) ||
+ g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS) ||
+ g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS) ||
+ g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS)) {
+ GSList *values = e_client_util_parse_comma_strings (prop_value), *v;
+
+
+ for (v = values; v; v = v->next) {
+ if (v != values)
+ g_print (", ");
+
+ g_print ("'%s'", (const gchar *) v->data);
+ }
+
+ e_client_util_free_string_slist (values);
+ } else {
+ g_print ("'%s'", (const gchar *) prop_value);
+ }
+
+ g_print ("\n");
+}
+
+static void
+print_values (const ExtraValues *evals, EClient *client)
+{
+ const GSList *values;
+
+ g_return_if_fail (evals != NULL);
+
+ g_print ("\treadonly:%s\n", e_client_is_readonly (client) ? "yes" : "no");
+ g_print ("\tonline:%s\n", e_client_is_online (client) ? "yes" : "no");
+ g_print ("\topened:%s\n", e_client_is_opened (client) ? "yes" : "no");
+ g_print ("\tcapabilities: ");
+ values = e_client_get_capabilities (client);
+ if (!values) {
+ g_print ("NULL");
+ } else {
+ while (values) {
+ const gchar *cap = values->data;
+
+ g_print ("'%s'", cap);
+ if (!e_client_check_capability (client, cap))
+ g_print (" (not found in EClient)");
+
+ values = values->next;
+
+ if (values)
+ g_print (", ");
+ }
+ }
+ g_print ("\n");
+
+ g_print ("\tbackend properties:\n");
+ g_hash_table_foreach (evals->retrieved_props, print_each_property, NULL);
+}
+
+static void
+identify_source (ESource *source)
+{
+ const gchar *name, *uri;
+ gchar *abs_uri = NULL;
+
+ g_return_if_fail (source != NULL);
+
+ name = e_source_peek_name (source);
+ if (!name)
+ name = "Unknown name";
+
+ uri = e_source_peek_absolute_uri (source);
+ if (!uri) {
+ abs_uri = e_source_build_absolute_uri (source);
+ uri = abs_uri;
+ }
+ if (!uri)
+ uri = e_source_peek_relative_uri (source);
+ if (!uri)
+ uri = "Unknown uri";
+
+ g_print ("\n Checking source '%s' (%s)\n", name, uri);
+
+ g_free (abs_uri);
+}
+
+static void
+identify_client (EBookClient *book_client)
+{
+ g_return_if_fail (book_client != NULL);
+ g_return_if_fail (E_IS_BOOK_CLIENT (book_client));
+
+ identify_source (e_client_get_source (E_CLIENT (book_client)));
+}
+
+static void client_opened_async (GObject *source_object, GAsyncResult *result, gpointer async_data);
+
+static void
+continue_next_source (gpointer async_data)
+{
+ ESource *source = NULL;
+ EBookClient *book_client;
+ GError *error = NULL;
+
+ g_return_if_fail (async_data != NULL);
+
+ while (async_data && foreach_configured_source_async_next (&async_data, &source)) {
+ book_client = e_book_client_new (source, &error);
+ if (!book_client) {
+ identify_source (source);
+ report_error ("book client new", &error);
+ continue;
+ }
+
+ e_client_open (E_CLIENT (book_client), TRUE, NULL, client_opened_async, async_data);
+ break;
+ }
+
+ if (!async_data) {
+ running_async--;
+ if (!running_async)
+ stop_main_loop (0);
+ }
+}
+
+static void
+client_got_backend_property_async (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ExtraValues *evals = user_data;
+ gchar *prop_value = NULL;
+ GError *error = NULL;
+ EBookClient *book_client;
+
+ g_return_if_fail (source_object != NULL);
+ g_return_if_fail (E_IS_BOOK_CLIENT (source_object));
+ g_return_if_fail (evals != NULL);
+
+ book_client = E_BOOK_CLIENT (source_object);
+
+ if (!e_client_get_backend_property_finish (E_CLIENT (book_client), result, &prop_value, &error)) {
+ identify_client (book_client);
+ report_error ("get backend property finish", &error);
+ }
+
+ g_hash_table_insert (evals->retrieved_props, evals->todo_prop_names->data, prop_value);
+ evals->todo_prop_names = g_slist_remove (evals->todo_prop_names, evals->todo_prop_names->data);
+
+ if (!evals->todo_prop_names) {
+ /* to cache them, as it can be fetched with idle as well */
+ e_client_get_capabilities (E_CLIENT (source_object));
+
+ identify_client (book_client);
+ print_values (evals, E_CLIENT (source_object));
+
+ g_object_unref (source_object);
+
+ continue_next_source (evals->async_data);
+ extra_values_free (evals);
+ } else {
+ e_client_get_backend_property (E_CLIENT (book_client), evals->todo_prop_names->data, NULL, client_got_backend_property_async, evals);
+ }
+}
+
+static void
+client_set_backend_property_async (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ExtraValues *evals = user_data;
+ GError *error = NULL;
+ EBookClient *book_client;
+
+ g_return_if_fail (source_object != NULL);
+ g_return_if_fail (E_IS_BOOK_CLIENT (source_object));
+ g_return_if_fail (evals != NULL);
+
+ book_client = E_BOOK_CLIENT (source_object);
+
+ if (!e_client_set_backend_property_finish (E_CLIENT (book_client), result, &error)) {
+ /* it may fail on the set_backend_property */
+ g_clear_error (&error);
+ } else {
+ identify_client (book_client);
+ g_printerr (" Might fail on set_backend_property, but reported success\n");
+ }
+
+ e_client_get_backend_property (E_CLIENT (book_client), evals->todo_prop_names->data, NULL, client_got_backend_property_async, evals);
+}
+
+static void
+client_opened_async (GObject *source_object, GAsyncResult *result, gpointer async_data)
+{
+ ExtraValues *evals;
+ GError *error = NULL;
+ EBookClient *book_client;
+
+ g_return_if_fail (source_object != NULL);
+ g_return_if_fail (E_IS_BOOK_CLIENT (source_object));
+ g_return_if_fail (async_data != NULL);
+
+ book_client = E_BOOK_CLIENT (source_object);
+
+ if (!e_client_open_finish (E_CLIENT (source_object), result, &error)) {
+ identify_client (book_client);
+ report_error ("client open finish", &error);
+ g_object_unref (source_object);
+ continue_next_source (async_data);
+ return;
+ }
+
+ evals = g_new0 (ExtraValues, 1);
+ evals->async_data = async_data;
+ evals->todo_prop_names = get_known_prop_names ();
+ evals->retrieved_props = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+
+ e_client_set_backend_property (E_CLIENT (book_client), "*unknown*property*", "*value*", NULL, client_set_backend_property_async, evals);
+}
+
+static void
+check_source_sync (ESource *source)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+ GSList *properties, *p;
+ ExtraValues evals = { 0 };
+
+ g_return_if_fail (source != NULL);
+
+ identify_source (source);
+
+ book_client = e_book_client_new (source, &error);
+ if (!book_client) {
+ report_error ("book client new", &error);
+ return;
+ }
+
+ if (!e_client_open_sync (E_CLIENT (book_client), TRUE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return;
+ }
+
+ if (!e_client_set_backend_property_sync (E_CLIENT (book_client), "*unknown*property*", "*value*", NULL, &error)) {
+ g_clear_error (&error);
+ } else {
+ identify_client (book_client);
+ g_printerr (" Might fail on set_backend_property, but reported success\n");
+ }
+
+ evals.retrieved_props = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+
+ properties = get_known_prop_names ();
+ for (p = properties; p != NULL; p = p->next) {
+ gchar *prop_value = NULL;
+
+ if (!e_client_get_backend_property_sync (E_CLIENT (book_client), p->data, &prop_value, NULL, &error)) {
+ identify_client (book_client);
+ report_error ("get backend property sync", &error);
+ } else {
+ g_hash_table_insert (evals.retrieved_props, p->data, prop_value);
+ }
+ }
+ g_slist_free (properties);
+
+ print_values (&evals, E_CLIENT (book_client));
+
+ g_hash_table_destroy (evals.retrieved_props);
+ g_object_unref (book_client);
+}
+
+static gboolean
+foreach_async (void)
+{
+ gpointer async_data;
+ ESource *source = NULL;
+ EBookClient *book_client;
+ GError *error = NULL;
+
+ async_data = foreach_configured_source_async_start (&source);
+ if (!async_data) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ running_async++;
+
+ while (book_client = e_book_client_new (source, &error), !book_client) {
+ identify_source (source);
+ report_error ("book client new", &error);
+
+ if (!foreach_configured_source_async_next (&async_data, &source)) {
+ running_async--;
+ if (!running_async)
+ stop_main_loop (0);
+ return FALSE;
+ }
+
+ identify_source (source);
+ }
+
+ e_client_open (E_CLIENT (book_client), TRUE, NULL, client_opened_async, async_data);
+
+ return TRUE;
+}
+
+static gboolean
+in_main_thread_idle_cb (gpointer unused)
+{
+ g_print ("* run in main thread with mainloop running\n");
+ foreach_configured_source (check_source_sync);
+ g_print ("---------------------------------------------------------\n\n");
+
+ g_print ("* run in main thread async\n");
+
+ if (!foreach_async ())
+ return FALSE;
+
+ return FALSE;
+}
+
+static gpointer
+worker_thread (gpointer unused)
+{
+ g_print ("* run in dedicated thread with mainloop running\n");
+ foreach_configured_source (check_source_sync);
+ g_print ("---------------------------------------------------------\n\n");
+
+ g_idle_add (in_main_thread_idle_cb, NULL);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ main_initialize ();
+
+ g_print ("* run in main thread without mainloop\n");
+ foreach_configured_source (check_source_sync);
+ g_print ("---------------------------------------------------------\n\n");
+
+ start_in_thread_with_main_loop (worker_thread, NULL);
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libebook/client/test-client-get-contact.c b/tests/libebook/client/test-client-get-contact.c
new file mode 100644
index 0000000..7a8e0b7
--- /dev/null
+++ b/tests/libebook/client/test-client-get-contact.c
@@ -0,0 +1,70 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libebook/e-book-client.h>
+
+#include "client-test-utils.h"
+
+static void
+contact_ready_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ EContact *contact;
+ GError *error = NULL;
+
+ if (!e_book_client_get_contact_finish (E_BOOK_CLIENT (source_object), result, &contact, &error)) {
+ report_error ("get contact finish", &error);
+ stop_main_loop (1);
+ } else {
+ g_object_unref (contact);
+ stop_main_loop (0);
+ }
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client;
+ EContact *contact_final;
+ GError *error = NULL;
+
+ main_initialize ();
+
+ /*
+ * Setup
+ */
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ /*
+ * Sync version
+ */
+ if (!add_contact_from_test_case_verify (book_client, "simple-1", &contact_final)) {
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ /*
+ * Async version
+ */
+ e_book_client_get_contact (book_client, e_contact_get_const (contact_final, E_CONTACT_UID), NULL, contact_ready_cb, NULL);
+
+ g_object_unref (contact_final);
+
+ start_main_loop (NULL, NULL);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libebook/client/test-client-get-view.c b/tests/libebook/client/test-client-get-view.c
new file mode 100644
index 0000000..de7829f
--- /dev/null
+++ b/tests/libebook/client/test-client-get-view.c
@@ -0,0 +1,180 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libebook/e-book-client.h>
+#include <libebook/e-book-query.h>
+
+#include "client-test-utils.h"
+
+static void
+objects_added (EBookClientView *view, const GSList *contacts)
+{
+ const GSList *l;
+
+ for (l = contacts; l; l = l->next) {
+ print_email (l->data);
+ }
+}
+
+static void
+objects_removed (EBookClientView *view, const GSList *ids)
+{
+ const GSList *l;
+
+ for (l = ids; l; l = l->next) {
+ printf (" Removed contact: %s\n", (gchar *) l->data);
+ }
+}
+
+static void
+complete (EBookClientView *view, const GError *error)
+{
+ e_book_client_view_stop (view, NULL);
+ g_object_unref (view);
+
+ stop_main_loop (0);
+}
+
+static void
+setup_and_start_view (EBookClientView *view)
+{
+ GError *error = NULL;
+
+ g_signal_connect (view, "objects-added", G_CALLBACK (objects_added), NULL);
+ g_signal_connect (view, "objects-removed", G_CALLBACK (objects_removed), NULL);
+ g_signal_connect (view, "complete", G_CALLBACK (complete), NULL);
+
+ e_book_client_view_set_fields_of_interest (view, NULL, &error);
+ if (error)
+ report_error ("set fields of interest", &error);
+
+ e_book_client_view_start (view, &error);
+ if (error)
+ report_error ("start view", &error);
+}
+
+static void
+get_view_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ EBookClientView *view;
+ GError *error = NULL;
+
+ if (!e_book_client_get_view_finish (E_BOOK_CLIENT (source_object), result, &view, &error)) {
+ report_error ("get view finish", &error);
+ stop_main_loop (1);
+
+ return;
+ }
+
+ setup_and_start_view (view);
+}
+
+static gboolean
+setup_book (EBookClient **book_client)
+{
+ GError *error = NULL;
+
+ g_return_val_if_fail (book_client != NULL, FALSE);
+
+ *book_client = new_temp_client (NULL);
+ g_return_val_if_fail (*book_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (*book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (*book_client);
+ return FALSE;
+ }
+
+ if (!add_contact_from_test_case_verify (*book_client, "simple-1", NULL) ||
+ !add_contact_from_test_case_verify (*book_client, "simple-2", NULL) ||
+ !add_contact_from_test_case_verify (*book_client, "name-only", NULL)) {
+ g_object_unref (*book_client);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gpointer
+call_get_view (gpointer user_data)
+{
+ EBookQuery *query;
+ EBookClient *book_client = user_data;
+ gchar *sexp;
+
+ g_return_val_if_fail (book_client != NULL, NULL);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (book_client), NULL);
+
+ query = e_book_query_any_field_contains ("");
+ sexp = e_book_query_to_string (query);
+ e_book_query_unref (query);
+
+ e_book_client_get_view (book_client, sexp, NULL, get_view_cb, NULL);
+
+ g_free (sexp);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client;
+ EBookQuery *query;
+ EBookClientView *view;
+ gchar *sexp;
+ GError *error = NULL;
+
+ main_initialize ();
+
+ /*
+ * Sync version
+ */
+ if (!setup_book (&book_client))
+ return 1;
+
+ query = e_book_query_any_field_contains ("");
+ sexp = e_book_query_to_string (query);
+ e_book_query_unref (query);
+ if (!e_book_client_get_view_sync (book_client, sexp, &view, NULL, &error)) {
+ report_error ("get book view sync", &error);
+ g_free (sexp);
+ g_object_unref (book_client);
+
+ return 1;
+ }
+
+ g_free (sexp);
+
+ setup_and_start_view (view);
+
+ start_main_loop (NULL, NULL);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ /*
+ * Async version
+ */
+ if (!setup_book (&book_client))
+ return 1;
+
+ start_in_idle_with_main_loop (call_get_view, book_client);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libebook/client/test-client-modify-contact.c b/tests/libebook/client/test-client-modify-contact.c
new file mode 100644
index 0000000..309e370
--- /dev/null
+++ b/tests/libebook/client/test-client-modify-contact.c
@@ -0,0 +1,159 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libebook/e-book-client.h>
+
+#include "client-test-utils.h"
+
+#define EMAIL_ADD "foo bar com"
+
+static void
+verify_premodify_and_prepare_contact (EContact *contact)
+{
+ EVCardAttribute *attr;
+
+ /* ensure there is no email address to begin with, then add one */
+ g_assert (!e_vcard_get_attribute (E_VCARD (contact), EVC_EMAIL));
+ attr = e_vcard_attribute_new (NULL, EVC_EMAIL);
+ e_vcard_add_attribute_with_value (E_VCARD (contact), attr, EMAIL_ADD);
+}
+
+static void
+verify_modify (EContact *contact)
+{
+ EVCardAttribute *attr;
+ gchar *email_value;
+
+ g_assert ((attr = e_vcard_get_attribute (E_VCARD (contact), EVC_EMAIL)));
+ g_assert (e_vcard_attribute_is_single_valued (attr));
+ email_value = e_vcard_attribute_get_value (attr);
+ g_assert (!g_strcmp0 (email_value, EMAIL_ADD));
+ g_free (email_value);
+}
+
+static void
+contact_ready_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ EContact *contact;
+ GError *error = NULL;
+
+ if (!e_book_client_get_contact_finish (E_BOOK_CLIENT (source_object), result, &contact, &error)) {
+ report_error ("get contact finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ verify_modify (contact);
+
+ g_object_unref (contact);
+
+ stop_main_loop (0);
+}
+
+static void
+contact_modified_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ EContact *contact = user_data;
+ GError *error = NULL;
+
+ if (!e_book_client_modify_contact_finish (E_BOOK_CLIENT (source_object), result, &error)) {
+ report_error ("modify contact finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ e_book_client_get_contact (E_BOOK_CLIENT (source_object), e_contact_get_const (contact, E_CONTACT_UID), NULL, contact_ready_cb, NULL);
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+ EContact *contact, *book_contact;
+
+ main_initialize ();
+
+ /*
+ * Setup
+ */
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ /*
+ * Sync version
+ */
+ if (!add_contact_from_test_case_verify (book_client, "name-only", &contact)) {
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ verify_premodify_and_prepare_contact (contact);
+
+ if (!e_book_client_modify_contact_sync (book_client, contact, NULL, &error)) {
+ report_error ("modify contact sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ if (!e_book_client_get_contact_sync (book_client, e_contact_get_const (contact, E_CONTACT_UID), &book_contact, NULL, &error)) {
+ report_error ("get contact sync", &error);
+ g_object_unref (contact);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ verify_modify (book_contact);
+
+ g_object_unref (book_contact);
+ g_object_unref (contact);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ /*
+ * Async version
+ */
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ if (!add_contact_from_test_case_verify (book_client, "name-only", &contact)) {
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ verify_premodify_and_prepare_contact (contact);
+
+ e_book_client_modify_contact (book_client, contact, NULL, contact_modified_cb, contact);
+
+ start_main_loop (NULL, NULL);
+
+ g_object_unref (contact);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libebook/client/test-client-nonexistent-id.c b/tests/libebook/client/test-client-nonexistent-id.c
new file mode 100644
index 0000000..058bf94
--- /dev/null
+++ b/tests/libebook/client/test-client-nonexistent-id.c
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <libebook/e-book-client.h>
+
+#include "client-test-utils.h"
+
+gint
+main (gint argc, gchar **argv)
+{
+ GError *error = NULL;
+ EBookClient *book_client = NULL;
+
+ main_initialize ();
+
+ printf ("loading addressbook\n");
+
+ book_client = open_system_book (FALSE);
+ if (!book_client)
+ return 1;
+
+ printf ("removing nonexistent contact\n");
+ if (!e_book_client_remove_contact_by_uid_sync (book_client, "ii", NULL, &error)) {
+ if (!g_error_matches (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND)) {
+ report_error ("remove contact sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ printf ("\tOK, ended with expected Not Found error\n");
+ g_error_free (error);
+ } else if (error) {
+ report_error ("remove contact sync returned error, but success", &error);
+ g_object_unref (book_client);
+ return 1;
+ } else {
+ report_error ("remove contact sync returned success, but should return error", NULL);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ return 0;
+}
diff --git a/tests/libebook/client/test-client-refresh.c b/tests/libebook/client/test-client-refresh.c
new file mode 100644
index 0000000..37db6df
--- /dev/null
+++ b/tests/libebook/client/test-client-refresh.c
@@ -0,0 +1,114 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <string.h>
+#include <libebook/e-book-client.h>
+
+#include "client-test-utils.h"
+
+static gboolean
+test_sync (EBookClient *book_client)
+{
+ GError *error = NULL;
+
+ g_print ("Refresh supported: %s\n", e_client_check_refresh_supported (E_CLIENT (book_client)) ? "yes" : "no");
+
+ if (!e_client_refresh_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("refresh sync", &error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* asynchronous callback with a main-loop running */
+static void
+async_refresh_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+
+ book_client = E_BOOK_CLIENT (source_object);
+
+ if (!e_client_refresh_finish (E_CLIENT (book_client), result, &error)) {
+ report_error ("refresh finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ stop_main_loop (0);
+}
+
+/* synchronously in idle with main-loop running */
+static gboolean
+test_sync_in_idle (gpointer user_data)
+{
+ EBookClient *book_client = user_data;
+
+ g_return_val_if_fail (book_client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (book_client), FALSE);
+
+ if (!test_sync (book_client)) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ g_print ("Refresh supported: %s\n", e_client_check_refresh_supported (E_CLIENT (book_client)) ? "yes" : "no");
+
+ e_client_refresh (E_CLIENT (book_client), NULL, async_refresh_result_ready, NULL);
+
+ return FALSE;
+}
+
+/* synchronously in a dedicated thread with main-loop running */
+static gpointer
+test_sync_in_thread (gpointer user_data)
+{
+ if (!test_sync (user_data)) {
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ g_idle_add (test_sync_in_idle, user_data);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+
+ main_initialize ();
+
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ /* synchronously without main-loop */
+ if (!test_sync (book_client)) {
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ start_in_thread_with_main_loop (test_sync_in_thread, book_client);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ if (get_main_loop_stop_result () == 0)
+ g_print ("Test finished successfully.\n");
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libebook/client/test-client-remove-contact-by-uid.c b/tests/libebook/client/test-client-remove-contact-by-uid.c
new file mode 100644
index 0000000..b55615a
--- /dev/null
+++ b/tests/libebook/client/test-client-remove-contact-by-uid.c
@@ -0,0 +1,127 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <libebook/e-book-client.h>
+
+#include "client-test-utils.h"
+
+static void
+remove_contact_by_uid_cb (GObject *source_object, GAsyncResult *result, gpointer uid)
+{
+ GError *error = NULL;
+ EContact *contact = NULL;
+
+ if (!e_book_client_remove_contact_by_uid_finish (E_BOOK_CLIENT (source_object), result, &error)) {
+ report_error ("remove contact by uid finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ if (!e_book_client_get_contact_sync (E_BOOK_CLIENT (source_object), uid, &contact, NULL, &error) &&
+ g_error_matches (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND)) {
+ g_clear_error (&error);
+ stop_main_loop (0);
+ } else {
+ report_error ("fail with get contact on removed contact", &error);
+ if (contact)
+ g_object_unref (contact);
+ stop_main_loop (1);
+ }
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+ EContact *contact;
+ gchar *uid;
+
+ main_initialize ();
+
+ /*
+ * Setup
+ */
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ /*
+ * Sync version
+ */
+ if (!add_contact_from_test_case_verify (book_client, "simple-1", &contact)) {
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ uid = e_contact_get (contact, E_CONTACT_UID);
+ g_object_unref (contact);
+
+ if (!e_book_client_remove_contact_by_uid_sync (book_client, uid, NULL, &error)) {
+ report_error ("remove contact sync", &error);
+ g_object_unref (book_client);
+ g_free (uid);
+ return 1;
+ }
+
+ if (!e_book_client_get_contact_sync (book_client, uid, &contact, NULL, &error) &&
+ g_error_matches (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND)) {
+ g_clear_error (&error);
+ } else {
+ report_error ("fail with get contact sync on removed contact", &error);
+ g_object_unref (book_client);
+ g_free (uid);
+ return 1;
+ }
+
+ g_free (uid);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ /*
+ * Async version
+ */
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ contact = NULL;
+
+ if (!add_contact_from_test_case_verify (book_client, "simple-1", &contact)) {
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ uid = e_contact_get (contact, E_CONTACT_UID);
+ g_object_unref (contact);
+ e_book_client_remove_contact_by_uid (book_client, uid, NULL, remove_contact_by_uid_cb, uid);
+
+ start_main_loop (NULL, NULL);
+
+ g_free (uid);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ return 0;
+}
diff --git a/tests/libebook/client/test-client-remove-contact.c b/tests/libebook/client/test-client-remove-contact.c
new file mode 100644
index 0000000..f944684
--- /dev/null
+++ b/tests/libebook/client/test-client-remove-contact.c
@@ -0,0 +1,130 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <libebook/e-book-client.h>
+
+#include "client-test-utils.h"
+
+static void
+remove_contact_cb (GObject *source_object, GAsyncResult *result, gpointer uid)
+{
+ GError *error = NULL;
+ EContact *contact = NULL;
+
+ if (!e_book_client_remove_contact_finish (E_BOOK_CLIENT (source_object), result, &error)) {
+ report_error ("remove contact finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ if (!e_book_client_get_contact_sync (E_BOOK_CLIENT (source_object), uid, &contact, NULL, &error) &&
+ g_error_matches (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND)) {
+ g_clear_error (&error);
+ stop_main_loop (0);
+ } else {
+ report_error ("fail with get contact on removed contact", &error);
+ if (contact)
+ g_object_unref (contact);
+ stop_main_loop (1);
+ }
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+ EContact *contact;
+ gchar *uid;
+
+ main_initialize ();
+
+ /*
+ * Setup
+ */
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ /*
+ * Sync version
+ */
+ if (!add_contact_from_test_case_verify (book_client, "simple-1", &contact)) {
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ uid = e_contact_get (contact, E_CONTACT_UID);
+
+ if (!e_book_client_remove_contact_sync (book_client, contact, NULL, &error)) {
+ report_error ("remove contact sync", &error);
+ g_object_unref (contact);
+ g_object_unref (book_client);
+ g_free (uid);
+ return 1;
+ }
+
+ g_object_unref (contact);
+
+ if (!e_book_client_get_contact_sync (book_client, uid, &contact, NULL, &error) &&
+ g_error_matches (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND)) {
+ g_clear_error (&error);
+ } else {
+ report_error ("fail with get contact sync on removed contact", &error);
+ g_object_unref (book_client);
+ g_free (uid);
+ return 1;
+ }
+
+ g_free (uid);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ /*
+ * Async version
+ */
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ contact = NULL;
+
+ if (!add_contact_from_test_case_verify (book_client, "simple-1", &contact)) {
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ uid = e_contact_get (contact, E_CONTACT_UID);
+ e_book_client_remove_contact (book_client, contact, NULL, remove_contact_cb, uid);
+
+ g_object_unref (contact);
+
+ start_main_loop (NULL, NULL);
+
+ g_free (uid);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ return 0;
+}
diff --git a/tests/libebook/client/test-client-remove-contacts.c b/tests/libebook/client/test-client-remove-contacts.c
new file mode 100644
index 0000000..49c4dd1
--- /dev/null
+++ b/tests/libebook/client/test-client-remove-contacts.c
@@ -0,0 +1,160 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <libebook/e-book-client.h>
+
+#include "client-test-utils.h"
+
+static gboolean
+check_removed (EBookClient *book_client, const GSList *uids)
+{
+ g_return_val_if_fail (book_client != NULL, FALSE);
+ g_return_val_if_fail (uids != NULL, FALSE);
+
+ while (uids) {
+ GError *error = NULL;
+ EContact *contact = NULL;
+
+ if (!e_book_client_get_contact_sync (book_client, uids->data, &contact, NULL, &error) &&
+ g_error_matches (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND)) {
+ g_clear_error (&error);
+ } else {
+ report_error ("fail with get contact on removed contact", &error);
+ if (contact)
+ g_object_unref (contact);
+ return FALSE;
+ }
+
+ uids = uids->next;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+fill_book_client (EBookClient *book_client, GSList **uids)
+{
+ EContact *contact;
+
+ g_return_val_if_fail (book_client != NULL, FALSE);
+ g_return_val_if_fail (uids != NULL, FALSE);
+
+ *uids = NULL;
+
+ if (!add_contact_from_test_case_verify (book_client, "simple-1", &contact))
+ return FALSE;
+
+ *uids = g_slist_append (*uids, e_contact_get (contact, E_CONTACT_UID));
+ g_object_unref (contact);
+
+ if (!add_contact_from_test_case_verify (book_client, "simple-2", &contact))
+ return FALSE;
+
+ *uids = g_slist_append (*uids, e_contact_get (contact, E_CONTACT_UID));
+ g_object_unref (contact);
+
+ return TRUE;
+}
+
+static void
+remove_contacts_cb (GObject *source_object, GAsyncResult *result, gpointer uids)
+{
+ GError *error = NULL;
+
+ if (!e_book_client_remove_contacts_finish (E_BOOK_CLIENT (source_object), result, &error)) {
+ report_error ("remove contacts finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ stop_main_loop (check_removed (E_BOOK_CLIENT (source_object), uids) ? 0 : 1);
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+ GSList *uids;
+
+ main_initialize ();
+
+ /*
+ * Setup
+ */
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ /*
+ * Sync version
+ */
+ if (!fill_book_client (book_client, &uids)) {
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ if (!e_book_client_remove_contacts_sync (book_client, uids, NULL, &error)) {
+ report_error ("remove contact sync", &error);
+ g_object_unref (book_client);
+ g_slist_foreach (uids, (GFunc) g_free, NULL);
+ g_slist_free (uids);
+ return 1;
+ }
+
+ if (!check_removed (book_client, uids)) {
+ g_object_unref (book_client);
+ g_slist_foreach (uids, (GFunc) g_free, NULL);
+ g_slist_free (uids);
+ return 1;
+ }
+
+ g_slist_foreach (uids, (GFunc) g_free, NULL);
+ g_slist_free (uids);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ /*
+ * Async version
+ */
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ if (!fill_book_client (book_client, &uids)) {
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ e_book_client_remove_contacts (book_client, uids, NULL, remove_contacts_cb, uids);
+
+ start_main_loop (NULL, NULL);
+
+ g_slist_foreach (uids, (GFunc) g_free, NULL);
+ g_slist_free (uids);
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libebook/client/test-client-remove.c b/tests/libebook/client/test-client-remove.c
new file mode 100644
index 0000000..a463f4b
--- /dev/null
+++ b/tests/libebook/client/test-client-remove.c
@@ -0,0 +1,69 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libebook/e-book-client.h>
+
+#include "client-test-utils.h"
+
+static void
+client_removed_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ GError *error = NULL;
+
+ if (!e_client_remove_finish (E_CLIENT (source_object), result, &error)) {
+ report_error ("client remove finish", &error);
+ stop_main_loop (1);
+ } else {
+ stop_main_loop (0);
+ }
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+
+ main_initialize ();
+
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ /*
+ * Sync version
+ */
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+
+ /*
+ * Async version
+ */
+
+ book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ e_client_remove (E_CLIENT (book_client), NULL, client_removed_cb, NULL);
+
+ start_main_loop (NULL, NULL);
+
+ g_object_unref (book_client);
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libebook/client/test-client-search.c b/tests/libebook/client/test-client-search.c
new file mode 100644
index 0000000..f9b0c81
--- /dev/null
+++ b/tests/libebook/client/test-client-search.c
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libebook/e-book-client.h>
+#include <libebook/e-book-query.h>
+
+#include "client-test-utils.h"
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client;
+ const gchar *query_string;
+ EBookQuery *query;
+ gchar *sexp;
+ GSList *c, *contacts;
+ GError *error = NULL;
+
+ main_initialize ();
+
+ if (argc != 2) {
+ query_string = "contains \"full_name\" \"a\"";
+ printf ("usage: test-search <query>\n");
+ printf (" using default query \"%s\"\n", query_string);
+ } else {
+ query_string = argv[1];
+ }
+
+ query = e_book_query_from_string (query_string);
+ if (!query) {
+ fprintf (stderr, " * Failed to parse query string '%s'\n", query_string);
+ return 1;
+ }
+
+ sexp = e_book_query_to_string (query);
+ e_book_query_unref (query);
+
+ book_client = open_system_book (FALSE);
+ if (!book_client) {
+ g_free (sexp);
+ return 1;
+ }
+
+ if (!e_book_client_get_contacts_sync (book_client, sexp, &contacts, NULL, &error)) {
+ report_error ("get contacts sync", &error);
+ g_free (sexp);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ for (c = contacts; c; c = c->next) {
+ EContact *contact = E_CONTACT (c->data);
+ gchar *vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+
+ printf ("%s\n\n", vcard);
+
+ g_free (vcard);
+ }
+
+ g_slist_foreach (contacts, (GFunc) g_object_unref, NULL);
+ g_slist_free (contacts);
+
+ g_free (sexp);
+ g_object_unref (book_client);
+
+ return 0;
+}
diff --git a/tests/libebook/client/test-client-self.c b/tests/libebook/client/test-client-self.c
new file mode 100644
index 0000000..f0867a1
--- /dev/null
+++ b/tests/libebook/client/test-client-self.c
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libebook/e-book-client.h>
+
+#include "client-test-utils.h"
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client = NULL;
+ EContact *contact = NULL;
+ GError *error = NULL;
+ gchar *vcard;
+
+ main_initialize ();
+
+ printf ("getting the self contact\n");
+
+ if (!e_book_client_get_self (&contact, &book_client, &error)) {
+ report_error ("get self", &error);
+ return 1;
+ }
+
+ if (!contact) {
+ fprintf (stderr, " * Self contact not set\n");
+ if (book_client)
+ g_object_unref (book_client);
+ return 0;
+ }
+
+ if (!book_client) {
+ fprintf (stderr, " * Book client for a self contact not returned\n");
+ g_object_unref (contact);
+ return 1;
+ }
+
+ vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+ printf ("self contact = \n%s\n", vcard);
+ g_free (vcard);
+
+ g_object_unref (contact);
+ g_object_unref (book_client);
+
+ return 0;
+}
diff --git a/tests/libebook/client/test-client-stress-factory--fifo.c b/tests/libebook/client/test-client-stress-factory--fifo.c
new file mode 100644
index 0000000..240142c
--- /dev/null
+++ b/tests/libebook/client/test-client-stress-factory--fifo.c
@@ -0,0 +1,50 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libebook/e-book-client.h>
+
+#include "client-test-utils.h"
+
+#define NUM_CLIENTS 200
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_clients[NUM_CLIENTS];
+ GError *error = NULL;
+ gint ii;
+
+ main_initialize ();
+
+ /* Create and open many books; then remove each of them */
+
+ for (ii = 0; ii < NUM_CLIENTS; ii++) {
+ book_clients[ii] = new_temp_client (NULL);
+ g_return_val_if_fail (book_clients[ii] != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_clients[ii]), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ while (ii >= 0) {
+ g_object_unref (book_clients[ii]);
+ ii--;
+ }
+
+ return 1;
+ }
+ }
+
+ for (ii = 0; ii < NUM_CLIENTS; ii++) {
+ if (!e_client_remove_sync (E_CLIENT (book_clients[ii]), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ while (ii < NUM_CLIENTS) {
+ g_object_unref (book_clients[ii]);
+ ii++;
+ }
+ return 1;
+ }
+
+ g_object_unref (book_clients[ii]);
+ }
+
+ return 0;
+}
diff --git a/tests/libebook/client/test-client-stress-factory--serial.c b/tests/libebook/client/test-client-stress-factory--serial.c
new file mode 100644
index 0000000..7a76ae5
--- /dev/null
+++ b/tests/libebook/client/test-client-stress-factory--serial.c
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <libebook/e-book-client.h>
+
+#include "client-test-utils.h"
+
+#define NUM_CLIENTS 200
+
+gint
+main (gint argc, gchar **argv)
+{
+ GError *error = NULL;
+ gint ii;
+
+ main_initialize ();
+
+ /* Serially create, open, (close), and remove many books */
+ for (ii = 0; ii < NUM_CLIENTS; ii++) {
+ EBookClient *book_client = new_temp_client (NULL);
+ g_return_val_if_fail (book_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ return 1;
+ }
+
+ if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ return 1;
+ }
+
+ g_object_unref (book_client);
+ }
+
+ return 0;
+}
diff --git a/tests/libebook/client/test-client-stress-factory--single-book.c b/tests/libebook/client/test-client-stress-factory--single-book.c
new file mode 100644
index 0000000..919d67a
--- /dev/null
+++ b/tests/libebook/client/test-client-stress-factory--single-book.c
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libebook/e-book-client.h>
+
+#include "client-test-utils.h"
+
+#define NUM_OPENS 200
+
+gint
+main (gint argc, gchar **argv)
+{
+ gchar *uri = NULL;
+ EBookClient *book_client;
+ GError *error = NULL;
+ gint ii;
+
+ main_initialize ();
+
+ book_client = new_temp_client (&uri);
+ g_return_val_if_fail (book_client != NULL, 1);
+ g_return_val_if_fail (uri != NULL, 1);
+
+ g_object_unref (book_client);
+
+ /* open and close the same book repeatedly */
+ for (ii = 0; ii < NUM_OPENS; ii++) {
+ book_client = e_book_client_new_from_uri (uri, &error);
+ if (!book_client) {
+ report_error ("new from uri", &error);
+ break;
+ }
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ break;
+ }
+
+ g_object_unref (book_client);
+ }
+
+ book_client = e_book_client_new_from_uri (uri, &error);
+ if (!book_client) {
+ g_clear_error (&error);
+ } else if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (book_client);
+ g_free (uri);
+ return 1;
+ } else if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (book_client);
+ g_free (uri);
+ return 1;
+ }
+
+ g_free (uri);
+ g_object_unref (book_client);
+
+ return ii == NUM_OPENS ? 0 : 1;
+}
diff --git a/tests/libebook/client/test-client-stress-views.c b/tests/libebook/client/test-client-stress-views.c
new file mode 100644
index 0000000..e6638da
--- /dev/null
+++ b/tests/libebook/client/test-client-stress-views.c
@@ -0,0 +1,128 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libebook/e-book-client.h>
+#include <libebook/e-book-query.h>
+
+#include "client-test-utils.h"
+
+#define NUM_VIEWS 200
+
+static void
+objects_added (EBookClientView *view, const GSList *contacts)
+{
+ const GSList *l;
+
+ for (l = contacts; l; l = l->next) {
+ print_email (l->data);
+ }
+}
+
+static void
+objects_removed (EBookClientView *view, const GSList *ids)
+{
+ const GSList *l;
+
+ for (l = ids; l; l = l->next) {
+ printf (" Removed contact: %s\n", (gchar *) l->data);
+ }
+}
+
+static void
+complete (EBookClientView *view, const GError *error)
+{
+ printf ("view_complete (status == %d, error_msg == %s%s%s)\n", error ? error->code : 0, error ? "'" : "", error ? error->message : "NULL", error ? "'" : "");
+}
+
+static gint
+stress_book_views (EBookClient *book_client, gboolean in_thread)
+{
+ EBookQuery *query;
+ EBookClientView *view = NULL;
+ EBookClientView *new_view;
+ gchar *sexp;
+ gint i;
+
+ g_return_val_if_fail (book_client != NULL, -1);
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (book_client), -1);
+
+ query = e_book_query_any_field_contains ("");
+ sexp = e_book_query_to_string (query);
+ e_book_query_unref (query);
+
+ for (i = 0; i < NUM_VIEWS; i++) {
+ GError *error = NULL;
+
+ if (!e_book_client_get_view_sync (book_client, sexp, &new_view, NULL, &error)) {
+ report_error ("get book view sync", &error);
+ g_object_unref (view);
+ g_free (sexp);
+ return 1;
+ }
+
+ g_signal_connect (new_view, "objects-added", G_CALLBACK (objects_added), NULL);
+ g_signal_connect (new_view, "objects-removed", G_CALLBACK (objects_removed), NULL);
+ g_signal_connect (new_view, "complete", G_CALLBACK (complete), NULL);
+
+ e_book_client_view_start (new_view, NULL);
+
+ if (view) {
+ /* wait 100 ms when in a thread */
+ if (in_thread)
+ g_usleep (100000);
+
+ e_book_client_view_stop (view, NULL);
+ g_object_unref (view);
+ }
+
+ view = new_view;
+ }
+
+ e_book_client_view_stop (view, NULL);
+ g_object_unref (view);
+
+ g_free (sexp);
+
+ return 0;
+}
+
+static gpointer
+stress_book_views_thread (gpointer user_data)
+{
+ stop_main_loop (stress_book_views (user_data, TRUE));
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+
+ main_initialize ();
+
+ printf ("loading addressbook\n");
+
+ book_client = e_book_client_new_system (&error);
+ if (!book_client) {
+ report_error ("create local addressbook", &error);
+ return 1;
+ }
+
+ if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) {
+ g_object_unref (book_client);
+ report_error ("open client sync", &error);
+ return 1;
+ }
+
+ /* test from main thread */
+ stress_book_views (book_client, FALSE);
+
+ /* test from dedicated thread */
+ start_in_thread_with_main_loop (stress_book_views_thread, book_client);
+
+ g_object_unref (book_client);
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libebook/client/test-client.c b/tests/libebook/client/test-client.c
new file mode 100644
index 0000000..45011ab
--- /dev/null
+++ b/tests/libebook/client/test-client.c
@@ -0,0 +1,82 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libebook/e-book-client.h>
+#include <libebook/e-book-query.h>
+
+#include "client-test-utils.h"
+
+static void
+print_all_emails (EBookClient *book)
+{
+ GError *error = NULL;
+ EBookQuery *query;
+ gchar *sexp;
+ gboolean result;
+ GSList *cards, *c;
+
+ query = e_book_query_field_exists (E_CONTACT_FULL_NAME);
+ sexp = e_book_query_to_string (query);
+ e_book_query_unref (query);
+
+ result = e_book_client_get_contacts_sync (book, sexp, &cards, NULL, &error);
+
+ g_free (sexp);
+
+ if (!result) {
+ fprintf (stderr, "Error getting card list: %s\n", error ? error->message : "Unknown error");
+ if (error)
+ g_error_free (error);
+ exit (1);
+ }
+
+ for (c = cards; c; c = c->next) {
+ EContact *contact = E_CONTACT (c->data);
+
+ print_email (contact);
+
+ g_object_unref (contact);
+ }
+
+ g_slist_free (cards);
+}
+
+static void
+print_one_email (EBookClient *book_client)
+{
+ EContact *contact;
+ GError *error = NULL;
+
+ if (!e_book_client_get_contact_sync (book_client, "pas-id-0002023", &contact, NULL, &error)) {
+ report_error ("get_contact_sync", &error);
+ return;
+ }
+
+ print_email (contact);
+
+ g_object_unref (contact);
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ EBookClient *book_client;
+
+ main_initialize ();
+
+ printf ("loading addressbook\n");
+
+ book_client = open_system_book (FALSE);
+ if (!book_client)
+ return 1;
+
+ printf ("printing one contact\n");
+ print_one_email (book_client);
+
+ printf ("printing all contacts\n");
+ print_all_emails (book_client);
+
+ g_object_unref (book_client);
+
+ return 0;
+}
diff --git a/tests/libebook/test-categories.c b/tests/libebook/test-categories.c
index bf24a74..2b73b6a 100644
--- a/tests/libebook/test-categories.c
+++ b/tests/libebook/test-categories.c
@@ -1,6 +1,6 @@
#include <stdlib.h>
#include <string.h>
-#include <libebook/e-book.h>
+#include <libebook/e-contact.h>
gint
main (gint argc, gchar **argv)
diff --git a/tests/libebook/test-date.c b/tests/libebook/test-date.c
index c2c6ad8..caf90a5 100644
--- a/tests/libebook/test-date.c
+++ b/tests/libebook/test-date.c
@@ -1,5 +1,5 @@
#include <stdlib.h>
-#include <libebook/e-book.h>
+#include <libebook/e-contact.h>
gint
main (gint argc, gchar **argv)
diff --git a/tests/libebook/test-photo.c b/tests/libebook/test-photo.c
index 8848b9b..2200689 100644
--- a/tests/libebook/test-photo.c
+++ b/tests/libebook/test-photo.c
@@ -1,6 +1,6 @@
#include <stdlib.h>
#include <string.h>
-#include <libebook/e-book.h>
+#include <libebook/e-contact.h>
static const gchar *photo_data =
"/9j/4AAQSkZJRgABAQEARwBHAAD//gAXQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q/9sAQwAIBgYHB\
diff --git a/tests/libebook/test-query.c b/tests/libebook/test-query.c
index 33c6143..44b593d 100644
--- a/tests/libebook/test-query.c
+++ b/tests/libebook/test-query.c
@@ -1,5 +1,5 @@
#include <string.h>
-#include <libebook/e-book.h>
+#include <libebook/e-book-query.h>
#define QUERY_STRING1
#define QUERY_STRING2
diff --git a/tests/libebook/test-string.c b/tests/libebook/test-string.c
index 953802e..b958eac 100644
--- a/tests/libebook/test-string.c
+++ b/tests/libebook/test-string.c
@@ -1,6 +1,6 @@
#include <stdlib.h>
#include <string.h>
-#include <libebook/e-book.h>
+#include <libebook/e-contact.h>
#define TEST_ID "test-uid"
diff --git a/tests/libebook/test-undefinedfield.c b/tests/libebook/test-undefinedfield.c
index 75e1dc0..03a393b 100644
--- a/tests/libebook/test-undefinedfield.c
+++ b/tests/libebook/test-undefinedfield.c
@@ -1,5 +1,5 @@
#include <stdlib.h>
-#include <libebook/e-book.h>
+#include <libebook/e-contact.h>
gint
main (gint argc, gchar **argv)
diff --git a/tests/libebook/test-untyped-phones.c b/tests/libebook/test-untyped-phones.c
index 8ebb8f9..c5ef691 100644
--- a/tests/libebook/test-untyped-phones.c
+++ b/tests/libebook/test-untyped-phones.c
@@ -1,6 +1,6 @@
#include <stdlib.h>
#include <string.h>
-#include <libebook/e-book.h>
+#include <libebook/e-contact.h>
/* TEL;WORK:... should map to PHONE_BUSINESS
TEL;FAX:... should map to OTHER_FAX. */
diff --git a/tests/libecal/Makefile.am b/tests/libecal/Makefile.am
index e1fbff0..4227613 100644
--- a/tests/libecal/Makefile.am
+++ b/tests/libecal/Makefile.am
@@ -1,3 +1,5 @@
+SUBDIRS = client
+
noinst_LTLIBRARIES = libecal-test-utils.la
libecal_test_utils_la_SOURCES = ecal-test-utils.c ecal-test-utils.h
diff --git a/tests/libecal/client/Makefile.am b/tests/libecal/client/Makefile.am
new file mode 100644
index 0000000..9b9d08c
--- /dev/null
+++ b/tests/libecal/client/Makefile.am
@@ -0,0 +1,89 @@
+noinst_LTLIBRARIES = libclient-test-utils.la
+
+libclient_test_utils_la_SOURCES = client-test-utils.c client-test-utils.h
+
+libclient_test_utils_la_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ -I$(top_srcdir)/calendar \
+ -I$(top_builddir)/calendar \
+ -DSRCDIR=\""$(srcdir)"\" \
+ $(EVOLUTION_CALENDAR_CFLAGS) \
+ $(NULL)
+
+libclient_test_utils_la_LIBADD = \
+ $(top_builddir)/calendar/libecal/libecal-1.2.la \
+ $(EVOLUTION_CALENDAR_LIBS) \
+ $(NULL)
+
+# ordered by relative complexity
+TESTS = \
+ test-client-open \
+ test-client-refresh \
+ test-client-get-free-busy \
+ test-client-add-timezone \
+ test-client-examine \
+ test-client-create-object \
+ test-client-remove-object \
+ test-client-get-object-list \
+ test-client-modify-object \
+ test-client-send-objects \
+ test-client-receive-objects \
+ test-client-get-attachment-uris \
+ test-client-get-view \
+ test-client-stress-views \
+ test-client-stress-factory--serial \
+ test-client-stress-factory--fifo \
+ test-client-stress-factory--single-cal \
+ $(NULL)
+
+# The test program
+noinst_PROGRAMS = $(TESTS)
+
+TEST_CPPFLAGS= \
+ $(libclient_test_utils_la_CPPFLAGS) \
+ $(NULL)
+
+TEST_LIBS = \
+ $(libclient_test_utils_la_LIBS) \
+ libclient-test-utils.la \
+ $(NULL)
+
+# ordered alphanumerically
+test_client_add_timezone_LDADD=$(TEST_LIBS)
+test_client_add_timezone_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_create_object_LDADD=$(TEST_LIBS)
+test_client_create_object_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_examine_LDADD=$(TEST_LIBS)
+test_client_examine_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_get_attachment_uris_LDADD=$(TEST_LIBS)
+test_client_get_attachment_uris_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_get_free_busy_LDADD=$(TEST_LIBS)
+test_client_get_free_busy_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_get_object_list_LDADD=$(TEST_LIBS)
+test_client_get_object_list_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_get_view_LDADD=$(TEST_LIBS)
+test_client_get_view_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_modify_object_LDADD=$(TEST_LIBS)
+test_client_modify_object_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_open_LDADD=$(TEST_LIBS)
+test_client_open_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_receive_objects_LDADD=$(TEST_LIBS)
+test_client_receive_objects_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_refresh_LDADD=$(TEST_LIBS)
+test_client_refresh_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_remove_object_LDADD=$(TEST_LIBS)
+test_client_remove_object_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_send_objects_LDADD=$(TEST_LIBS)
+test_client_send_objects_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_stress_factory__fifo_LDADD=$(TEST_LIBS)
+test_client_stress_factory__fifo_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_stress_factory__serial_LDADD=$(TEST_LIBS)
+test_client_stress_factory__serial_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_stress_factory__single_cal_LDADD=$(TEST_LIBS)
+test_client_stress_factory__single_cal_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_stress_views_LDADD=$(TEST_LIBS)
+test_client_stress_views_CPPFLAGS=$(TEST_CPPFLAGS)
+
+-include $(top_srcdir)/git.mk
diff --git a/tests/libecal/client/client-test-utils.c b/tests/libecal/client/client-test-utils.c
new file mode 100644
index 0000000..4ff6915
--- /dev/null
+++ b/tests/libecal/client/client-test-utils.c
@@ -0,0 +1,350 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdio.h>
+
+#include "client-test-utils.h"
+
+void
+print_ecomp (ECalComponent *ecalcomp)
+{
+ const gchar *uid = NULL;
+ ECalComponentText summary = { 0 };
+
+ g_return_if_fail (ecalcomp != NULL);
+
+ e_cal_component_get_uid (ecalcomp, &uid);
+ e_cal_component_get_summary (ecalcomp, &summary);
+
+ g_print (" Component: %s\n", uid ? uid : "no-uid");
+ g_print (" Summary: %s\n", summary.value ? summary.value : "NULL");
+ g_print ("\n");
+}
+
+void
+print_icomp (icalcomponent *icalcomp)
+{
+ ECalComponent *ecomp;
+
+ g_return_if_fail (icalcomp != NULL);
+
+ ecomp = e_cal_component_new ();
+ icalcomp = icalcomponent_new_clone (icalcomp);
+
+ if (!e_cal_component_set_icalcomponent (ecomp, icalcomp)) {
+ icalcomponent_free (icalcomp);
+ g_object_unref (ecomp);
+ g_printerr ("%s: Failed to assing icalcomp to ECalComponent\n", G_STRFUNC);
+ g_print ("\n");
+ return;
+ }
+
+ print_ecomp (ecomp);
+
+ g_object_unref (ecomp);
+}
+
+void
+report_error (const gchar *operation, GError **error)
+{
+ g_return_if_fail (operation != NULL);
+
+ g_printerr ("Failed to %s: %s\n", operation, (error && *error) ? (*error)->message : "Unknown error");
+
+ g_clear_error (error);
+}
+
+void
+main_initialize (void)
+{
+ static gboolean initialized = FALSE;
+
+ if (initialized)
+ return;
+
+ g_type_init ();
+ g_thread_init (NULL);
+
+ initialized = TRUE;
+}
+
+struct IdleData {
+ GThreadFunc func;
+ gpointer data;
+ gboolean run_in_thread; /* FALSE to run in idle callback */
+};
+
+static gboolean
+idle_cb (gpointer data)
+{
+ struct IdleData *idle = data;
+
+ g_return_val_if_fail (idle != NULL, FALSE);
+ g_return_val_if_fail (idle->func != NULL, FALSE);
+
+ if (idle->run_in_thread) {
+ GError *error = NULL;
+
+ g_thread_create (idle->func, idle->data, FALSE, &error);
+
+ if (error) {
+ report_error ("create thread", &error);
+ stop_main_loop (1);
+ }
+ } else {
+ idle->func (idle->data);
+ }
+
+ g_free (idle);
+
+ return FALSE;
+}
+
+static GMainLoop *loop = NULL;
+static gint main_stop_result = 0;
+
+static void
+do_start (GThreadFunc func, gpointer data)
+{
+ main_initialize ();
+
+ g_return_if_fail (loop == NULL);
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ if (func)
+ func (data);
+
+ g_main_loop_run (loop);
+
+ g_main_loop_unref (loop);
+ loop = NULL;
+}
+
+/* Starts new main-loop, but just before that calls 'func'.
+ Main-loop is kept running, and this function blocks,
+ until call of stop_main_loop().
+*/
+void
+start_main_loop (GThreadFunc func, gpointer data)
+{
+ g_return_if_fail (loop == NULL);
+
+ do_start (func, data);
+}
+
+/* Starts new main-loop and then invokes func in a new thread.
+ Main-loop is kept running, and this function blocks,
+ until call of stop_main_loop().
+*/
+void
+start_in_thread_with_main_loop (GThreadFunc func, gpointer data)
+{
+ struct IdleData *idle;
+
+ g_return_if_fail (func != NULL);
+ g_return_if_fail (loop == NULL);
+
+ main_initialize ();
+
+ idle = g_new0 (struct IdleData, 1);
+ idle->func = func;
+ idle->data = data;
+ idle->run_in_thread = TRUE;
+
+ g_idle_add (idle_cb, idle);
+
+ do_start (NULL, NULL);
+}
+
+/* Starts new main-loop and then invokes func in an idle callback.
+ Main-loop is kept running, and this function blocks,
+ until call of stop_main_loop().
+*/
+void
+start_in_idle_with_main_loop (GThreadFunc func, gpointer data)
+{
+ struct IdleData *idle;
+
+ g_return_if_fail (func != NULL);
+ g_return_if_fail (loop == NULL);
+
+ main_initialize ();
+
+ idle = g_new0 (struct IdleData, 1);
+ idle->func = func;
+ idle->data = data;
+ idle->run_in_thread = FALSE;
+
+ g_idle_add (idle_cb, idle);
+
+ do_start (NULL, NULL);
+}
+
+/* Stops main-loop previously run by start_main_loop,
+ start_in_thread_with_main_loop or start_in_idle_with_main_loop.
+*/
+void
+stop_main_loop (gint stop_result)
+{
+ g_return_if_fail (loop != NULL);
+
+ main_stop_result = stop_result;
+ g_main_loop_quit (loop);
+}
+
+/* returns value used in stop_main_loop() */
+gint
+get_main_loop_stop_result (void)
+{
+ return main_stop_result;
+}
+
+void
+foreach_configured_source (ECalClientSourceType source_type, void (*func) (ESource *source, ECalClientSourceType source_type))
+{
+ gpointer foreach_async_data;
+ ESource *source = NULL;
+
+ g_return_if_fail (func != NULL);
+
+ main_initialize ();
+
+ foreach_async_data = foreach_configured_source_async_start (source_type, &source);
+ if (!foreach_async_data)
+ return;
+
+ do {
+ func (source, source_type);
+ } while (foreach_configured_source_async_next (&foreach_async_data, &source));
+}
+
+struct ForeachConfiguredData
+{
+ ECalClientSourceType source_type;
+ ESourceList *source_list;
+ GSList *current_group;
+ GSList *current_source;
+};
+
+gpointer
+foreach_configured_source_async_start (ECalClientSourceType source_type, ESource **source)
+{
+ struct ForeachConfiguredData *async_data;
+ ESourceList *source_list = NULL;
+ GError *error = NULL;
+
+ g_return_val_if_fail (source != NULL, NULL);
+
+ main_initialize ();
+
+ if (!e_cal_client_get_sources (&source_list, source_type, &error)) {
+ report_error ("get addressbooks", &error);
+ return NULL;
+ }
+
+ g_return_val_if_fail (source_list != NULL, NULL);
+
+ async_data = g_new0 (struct ForeachConfiguredData, 1);
+ async_data->source_type = source_type;
+ async_data->source_list = source_list;
+ async_data->current_group = e_source_list_peek_groups (source_list);
+ if (!async_data->current_group) {
+ gpointer ad = async_data;
+
+ foreach_configured_source_async_next (&ad, source);
+ return ad;
+ }
+
+ async_data->current_source = e_source_group_peek_sources (async_data->current_group->data);
+ if (!async_data->current_source) {
+ gpointer ad = async_data;
+
+ if (foreach_configured_source_async_next (&ad, source))
+ return ad;
+
+ return NULL;
+ }
+
+ *source = async_data->current_source->data;
+
+ return async_data;
+}
+
+gboolean
+foreach_configured_source_async_next (gpointer *foreach_async_data, ESource **source)
+{
+ struct ForeachConfiguredData *async_data;
+
+ g_return_val_if_fail (foreach_async_data != NULL, FALSE);
+ g_return_val_if_fail (source != NULL, FALSE);
+
+ async_data = *foreach_async_data;
+ g_return_val_if_fail (async_data != NULL, FALSE);
+ g_return_val_if_fail (async_data->source_list != NULL, FALSE);
+ g_return_val_if_fail (async_data->current_group != NULL, FALSE);
+
+ if (async_data->current_source)
+ async_data->current_source = async_data->current_source->next;
+ if (async_data->current_source) {
+ *source = async_data->current_source->data;
+ return TRUE;
+ }
+
+ do {
+ async_data->current_group = async_data->current_group->next;
+ if (async_data->current_group) {
+ async_data->current_source = e_source_group_peek_sources (async_data->current_group->data);
+ }
+ } while (async_data->current_group && !async_data->current_source);
+
+ if (async_data->current_source) {
+ *source = async_data->current_source->data;
+ return TRUE;
+ }
+
+ g_object_unref (async_data->source_list);
+ g_free (async_data);
+
+ *foreach_async_data = NULL;
+
+ return FALSE;
+}
+
+ECalClientSourceType
+foreach_configured_source_async_get_source_type (gpointer foreach_async_data)
+{
+ struct ForeachConfiguredData *async_data = foreach_async_data;
+
+ g_return_val_if_fail (foreach_async_data != NULL, E_CAL_CLIENT_SOURCE_TYPE_LAST);
+
+ return async_data->source_type;
+}
+
+ECalClient *
+new_temp_client (ECalClientSourceType source_type, gchar **uri)
+{
+ ECalClient *cal_client;
+ ESource *source;
+ gchar *abs_uri, *filename;
+ GError *error = NULL;
+
+ filename = g_build_filename (g_get_tmp_dir (), "e-cal-client-test-XXXXXX/", NULL);
+ abs_uri = g_strconcat ("local:", filename, NULL);
+ g_free (filename);
+
+ source = e_source_new_with_absolute_uri ("Test cal", abs_uri);
+ if (uri)
+ *uri = abs_uri;
+ else
+ g_free (abs_uri);
+
+ g_return_val_if_fail (source != NULL, NULL);
+
+ cal_client = e_cal_client_new (source, source_type, &error);
+ g_object_unref (source);
+
+ if (error)
+ report_error ("new temp client", &error);
+
+ return cal_client;
+}
diff --git a/tests/libecal/client/client-test-utils.h b/tests/libecal/client/client-test-utils.h
new file mode 100644
index 0000000..127a642
--- /dev/null
+++ b/tests/libecal/client/client-test-utils.h
@@ -0,0 +1,25 @@
+#ifndef CLIENT_TEST_UTILS_H
+#define CLIENT_TEST_UTILS_H
+
+#include <glib.h>
+#include <libecal/e-cal-client.h>
+
+void print_ecomp (ECalComponent *ecalcomp);
+void print_icomp (icalcomponent *icalcomp);
+void report_error (const gchar *operation, GError **error);
+
+void main_initialize (void);
+void start_main_loop (GThreadFunc func, gpointer data);
+void start_in_thread_with_main_loop (GThreadFunc func, gpointer data);
+void start_in_idle_with_main_loop (GThreadFunc func, gpointer data);
+void stop_main_loop (gint stop_result);
+gint get_main_loop_stop_result (void);
+
+void foreach_configured_source (ECalClientSourceType source_type, void (*func) (ESource *source, ECalClientSourceType source_type));
+gpointer foreach_configured_source_async_start (ECalClientSourceType source_type, ESource **source);
+gboolean foreach_configured_source_async_next (gpointer *foreach_async_data, ESource **source);
+ECalClientSourceType foreach_configured_source_async_get_source_type (gpointer foreach_async_data);
+
+ECalClient *new_temp_client (ECalClientSourceType source_type, gchar **uri);
+
+#endif /* CLIENT_TEST_UTILS_H */
diff --git a/tests/libecal/client/test-client-add-timezone.c b/tests/libecal/client/test-client-add-timezone.c
new file mode 100644
index 0000000..ece2391
--- /dev/null
+++ b/tests/libecal/client/test-client-add-timezone.c
@@ -0,0 +1,209 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libecal/e-cal-client.h>
+#include <libical/ical.h>
+
+#include "client-test-utils.h"
+
+#define TZID_NEW "XYZ"
+#define TZNAME_NEW "Ex Wye Zee"
+
+static gboolean
+test_zones (icaltimezone *zone1, icaltimezone *zone2)
+{
+ if (!zone2) {
+ g_printerr ("Failure: get timezone returned NULL\n");
+ return FALSE;
+ }
+
+ if (g_strcmp0 (icaltimezone_get_tzid (zone1), icaltimezone_get_tzid (zone2)) != 0) {
+ g_printerr ("Failure: tzid doesn't match, expected '%s', got '%s'\n", icaltimezone_get_tzid (zone1), icaltimezone_get_tzid (zone2));
+ return FALSE;
+ }
+
+ if (g_strcmp0 (icaltimezone_get_tznames (zone1), icaltimezone_get_tznames (zone2)) != 0) {
+ g_printerr ("Failure: tznames doesn't match, expected '%s', got '%s'\n", icaltimezone_get_tznames (zone1), icaltimezone_get_tznames (zone2));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+test_sync (icaltimezone *zone)
+{
+ ECalClient *cal_client;
+ icaltimezone *zone2 = NULL;
+ GError *error = NULL;
+ gboolean res;
+
+ g_return_val_if_fail (zone != NULL, FALSE);
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ return FALSE;
+ }
+
+ if (!e_cal_client_add_timezone_sync (cal_client, zone, NULL, &error)) {
+ report_error ("add timezone sync", &error);
+ g_object_unref (cal_client);
+ return FALSE;
+ }
+
+ if (!e_cal_client_get_timezone_sync (cal_client, TZID_NEW, &zone2, NULL, &error)) {
+ report_error ("get timezone sync", &error);
+ g_object_unref (cal_client);
+ return FALSE;
+ }
+
+ res = test_zones (zone, zone2);
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ return FALSE;
+ }
+
+ g_object_unref (cal_client);
+
+ return res;
+}
+
+/* asynchronous read callback with a main-loop running */
+static void
+async_read_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ icaltimezone *zone1 = user_data, *zone2 = NULL;
+ gboolean res;
+
+ g_return_if_fail (zone1 != NULL);
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_cal_client_get_timezone_finish (cal_client, result, &zone2, &error)) {
+ report_error ("get timezone finish", &error);
+ g_object_unref (cal_client);
+ stop_main_loop (1);
+ return;
+ }
+
+ res = test_zones (zone1, zone2);
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ }
+
+ g_object_unref (cal_client);
+
+ stop_main_loop (res ? 0 : 1);
+}
+
+/* asynchronous write callback with a main-loop running */
+static void
+async_write_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ g_return_if_fail (user_data != NULL);
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_cal_client_add_timezone_finish (cal_client, result, &error)) {
+ report_error ("add timezone finish", &error);
+ g_object_unref (cal_client);
+ stop_main_loop (1);
+ return;
+ }
+
+ e_cal_client_get_timezone (cal_client, TZID_NEW, NULL, async_read_result_ready, user_data);
+}
+
+/* synchronously in idle with main-loop running */
+static gboolean
+test_sync_in_idle (gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ icaltimezone *zone = user_data;
+
+ g_return_val_if_fail (zone != NULL, FALSE);
+
+ if (!test_sync (zone)) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ e_cal_client_add_timezone (cal_client, zone, NULL, async_write_result_ready, zone);
+
+ return FALSE;
+}
+
+/* synchronously in a dedicated thread with main-loop running */
+static gpointer
+test_sync_in_thread (gpointer user_data)
+{
+ icaltimezone *zone = user_data;
+
+ g_return_val_if_fail (zone != NULL, NULL);
+
+ if (!test_sync (zone)) {
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ g_idle_add (test_sync_in_idle, zone);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ icalproperty *property;
+ icalcomponent *component;
+ icaltimezone *zone;
+
+ main_initialize ();
+
+ /* Build up new timezone */
+ component = icalcomponent_new_vtimezone ();
+ property = icalproperty_new_tzid (TZID_NEW);
+ icalcomponent_add_property (component, property);
+ property = icalproperty_new_tzname (TZNAME_NEW);
+ icalcomponent_add_property (component, property);
+ zone = icaltimezone_new ();
+ icaltimezone_set_component (zone, component);
+
+ /* synchronously without main-loop */
+ if (!test_sync (zone)) {
+ icaltimezone_free (zone, TRUE);
+ return 1;
+ }
+
+ start_in_thread_with_main_loop (test_sync_in_thread, zone);
+
+ icaltimezone_free (zone, TRUE);
+
+ if (get_main_loop_stop_result () == 0)
+ g_print ("Test finished successfully.\n");
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-create-object.c b/tests/libecal/client/test-client-create-object.c
new file mode 100644
index 0000000..25af903
--- /dev/null
+++ b/tests/libecal/client/test-client-create-object.c
@@ -0,0 +1,297 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libecal/e-cal-client.h>
+#include <libical/ical.h>
+
+#include "client-test-utils.h"
+
+static gboolean
+test_icalcomps (icalcomponent *icalcomp1, icalcomponent *icalcomp2)
+{
+ struct icaltimetype t1, t2;
+
+ if (!icalcomp2) {
+ g_printerr ("Failure: get object returned NULL\n");
+ return FALSE;
+ }
+
+ if (g_strcmp0 (icalcomponent_get_uid (icalcomp1), icalcomponent_get_uid (icalcomp2)) != 0) {
+ g_printerr ("Failure: uid doesn't match, expected '%s', got '%s'\n", icalcomponent_get_uid (icalcomp1), icalcomponent_get_uid (icalcomp2));
+ return FALSE;
+ }
+
+ if (g_strcmp0 (icalcomponent_get_summary (icalcomp1), icalcomponent_get_summary (icalcomp2)) != 0) {
+ g_printerr ("Failure: summary doesn't match, expected '%s', got '%s'\n", icalcomponent_get_summary (icalcomp1), icalcomponent_get_summary (icalcomp2));
+ return FALSE;
+ }
+
+ t1 = icalcomponent_get_dtstart (icalcomp1);
+ t2 = icalcomponent_get_dtstart (icalcomp2);
+
+ if (icaltime_compare (t1, t2) != 0) {
+ g_printerr ("Failure: dtend doesn't match, expected '%s', got '%s'\n", icaltime_as_ical_string (t1), icaltime_as_ical_string (t2));
+ return FALSE;
+ }
+
+ t1 = icalcomponent_get_dtend (icalcomp1);
+ t2 = icalcomponent_get_dtend (icalcomp2);
+
+ if (icaltime_compare (t1, t2) != 0) {
+ g_printerr ("Failure: dtend doesn't match, expected '%s', got '%s'\n", icaltime_as_ical_string (t1), icaltime_as_ical_string (t2));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+test_sync (icalcomponent *icalcomp)
+{
+ ECalClient *cal_client;
+ icalcomponent *icalcomp2 = NULL, *clone;
+ GError *error = NULL;
+ gchar *uid = NULL;
+ gboolean res;
+
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ return FALSE;
+ }
+
+ if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error)) {
+ report_error ("create object sync", &error);
+ g_object_unref (cal_client);
+ return FALSE;
+ }
+
+ if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icalcomp2, NULL, &error)) {
+ report_error ("get object sync", &error);
+ g_free (uid);
+ g_object_unref (cal_client);
+ return FALSE;
+ }
+
+ clone = icalcomponent_new_clone (icalcomp);
+ icalcomponent_set_uid (clone, uid);
+
+ res = test_icalcomps (clone, icalcomp2);
+
+ icalcomponent_free (icalcomp2);
+
+ if (res) {
+ GSList *ecalcomps = NULL;
+
+ if (!e_cal_client_get_objects_for_uid_sync (cal_client, uid, &ecalcomps, NULL, &error)) {
+ report_error ("get objects for uid sync", &error);
+ res = FALSE;
+ }
+
+ if (g_slist_length (ecalcomps) != 1) {
+ g_printerr ("Failure: expected 1 component, bug got %d\n", g_slist_length (ecalcomps));
+ res = FALSE;
+ } else {
+ ECalComponent *ecalcomp = ecalcomps->data;
+
+ res = test_icalcomps (clone, e_cal_component_get_icalcomponent (ecalcomp));
+ }
+
+ e_cal_client_free_ecalcomp_slist (ecalcomps);
+ }
+
+ icalcomponent_free (clone);
+ g_free (uid);
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ return FALSE;
+ }
+
+ g_object_unref (cal_client);
+
+ return res;
+}
+
+/* asynchronous read2 callback with a main-loop running */
+static void
+async_read2_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ icalcomponent *icalcomp1 = user_data;
+ GSList *ecalcomps = NULL;
+ gboolean res;
+
+ g_return_if_fail (icalcomp1 != NULL);
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_cal_client_get_objects_for_uid_finish (cal_client, result, &ecalcomps, &error)) {
+ report_error ("get objects for uid finish", &error);
+ g_object_unref (cal_client);
+ icalcomponent_free (icalcomp1);
+ stop_main_loop (1);
+ return;
+ }
+
+ if (g_slist_length (ecalcomps) != 1) {
+ g_printerr ("Failure: expected 1 component, bug got %d\n", g_slist_length (ecalcomps));
+ res = FALSE;
+ } else {
+ ECalComponent *ecalcomp = ecalcomps->data;
+
+ res = test_icalcomps (icalcomp1, e_cal_component_get_icalcomponent (ecalcomp));
+ }
+
+ e_cal_client_free_ecalcomp_slist (ecalcomps);
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ }
+
+ g_object_unref (cal_client);
+ icalcomponent_free (icalcomp1);
+
+ stop_main_loop (res ? 0 : 1);
+}
+
+/* asynchronous read callback with a main-loop running */
+static void
+async_read_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ icalcomponent *icalcomp1 = user_data, *icalcomp2 = NULL;
+
+ g_return_if_fail (icalcomp1 != NULL);
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_cal_client_get_object_finish (cal_client, result, &icalcomp2, &error)) {
+ report_error ("get object finish", &error);
+ g_object_unref (cal_client);
+ icalcomponent_free (icalcomp1);
+ stop_main_loop (1);
+ return;
+ }
+
+ test_icalcomps (icalcomp1, icalcomp2);
+
+ icalcomponent_free (icalcomp2);
+
+ e_cal_client_get_objects_for_uid (cal_client, icalcomponent_get_uid (icalcomp1), NULL, async_read2_result_ready, icalcomp1);
+}
+
+/* asynchronous write callback with a main-loop running */
+static void
+async_write_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ gchar *uid = NULL;
+ icalcomponent *clone, *icalcomp = user_data;
+
+ g_return_if_fail (icalcomp != NULL);
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_cal_client_create_object_finish (cal_client, result, &uid, &error)) {
+ report_error ("create object finish", &error);
+ g_object_unref (cal_client);
+ stop_main_loop (1);
+ return;
+ }
+
+ clone = icalcomponent_new_clone (icalcomp);
+ icalcomponent_set_uid (clone, uid);
+
+ e_cal_client_get_object (cal_client, uid, NULL, NULL, async_read_result_ready, clone);
+
+ g_free (uid);
+}
+
+/* synchronously in idle with main-loop running */
+static gboolean
+test_sync_in_idle (gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ icalcomponent *icalcomp = user_data;
+
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+
+ if (!test_sync (icalcomp)) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ e_cal_client_create_object (cal_client, icalcomp, NULL, async_write_result_ready, icalcomp);
+
+ return FALSE;
+}
+
+/* synchronously in a dedicated thread with main-loop running */
+static gpointer
+test_sync_in_thread (gpointer user_data)
+{
+ icalcomponent *icalcomp = user_data;
+
+ g_return_val_if_fail (icalcomp != NULL, NULL);
+
+ if (!test_sync (icalcomp)) {
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ g_idle_add (test_sync_in_idle, icalcomp);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ icalcomponent *icalcomp;
+ struct icaltimetype now;
+
+ main_initialize ();
+
+ /* Build up new component */
+ now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+ icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
+ icalcomponent_set_summary (icalcomp, "Test event summary");
+ icalcomponent_set_dtstart (icalcomp, now);
+ icalcomponent_set_dtend (icalcomp, icaltime_from_timet (icaltime_as_timet (now) + 60 * 60 * 60, 0));
+
+ /* synchronously without main-loop */
+ if (!test_sync (icalcomp)) {
+ icalcomponent_free (icalcomp);
+ return 1;
+ }
+
+ start_in_thread_with_main_loop (test_sync_in_thread, icalcomp);
+
+ icalcomponent_free (icalcomp);
+
+ if (get_main_loop_stop_result () == 0)
+ g_print ("Test finished successfully.\n");
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-examine.c b/tests/libecal/client/test-client-examine.c
new file mode 100644
index 0000000..3a1298e
--- /dev/null
+++ b/tests/libecal/client/test-client-examine.c
@@ -0,0 +1,487 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <string.h>
+#include <libecal/e-cal-client.h>
+#include <libedataserver/e-source-group.h>
+
+#include "client-test-utils.h"
+
+static gint running_async = 0;
+
+static GSList *
+get_known_prop_names (void)
+{
+ GSList *prop_names = NULL;
+
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENED);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENING);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_ONLINE);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_READONLY);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CACHE_DIR);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CAPABILITIES);
+ prop_names = g_slist_append (prop_names, (gpointer) CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS);
+ prop_names = g_slist_append (prop_names, (gpointer) CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS);
+ prop_names = g_slist_append (prop_names, (gpointer) CAL_BACKEND_PROPERTY_DEFAULT_OBJECT);
+
+ return prop_names;
+}
+
+typedef struct _ExtraValues {
+ gpointer async_data;
+
+ GSList *todo_prop_names;
+ GHashTable *retrieved_props;
+ const gchar *cache_dir;
+ icalcomponent *default_object;
+} ExtraValues;
+
+static void
+extra_values_free (ExtraValues *evals)
+{
+ if (!evals)
+ return;
+
+ if (evals->default_object)
+ icalcomponent_free (evals->default_object);
+ g_slist_free (evals->todo_prop_names);
+ g_hash_table_destroy (evals->retrieved_props);
+ g_free (evals);
+}
+
+static void
+print_with_prefix (const gchar *str, const gchar *prefix)
+{
+ const gchar *p = str, *n;
+ while (n = strchr (p, '\n'), p) {
+ if (!n) {
+ g_print ("%s%s\n", prefix, p);
+ break;
+ } else {
+ g_print ("%s%.*s\n", prefix, (gint) (n - p), p);
+ n++;
+ }
+
+ p = n;
+ }
+}
+
+static void
+print_each_property (gpointer prop_name, gpointer prop_value, gpointer user_data)
+{
+ g_return_if_fail (prop_name != NULL);
+
+ if (prop_value == NULL) {
+ g_print ("\t %s: NULL\n", (const gchar *) prop_name);
+ return;
+ }
+
+ g_print ("\t %s: ", (const gchar *) prop_name);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ GSList *values = e_client_util_parse_comma_strings (prop_value), *v;
+
+
+ for (v = values; v; v = v->next) {
+ if (v != values)
+ g_print (", ");
+
+ g_print ("'%s'", (const gchar *) v->data);
+ }
+
+ e_client_util_free_string_slist (values);
+ } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
+ g_print ("\n");
+ print_with_prefix (prop_value, "\t\t");
+ } else {
+ g_print ("'%s'", (const gchar *) prop_value);
+ }
+
+ g_print ("\n");
+}
+
+static void
+print_values (const ExtraValues *evals, EClient *client)
+{
+ const GSList *values;
+
+ g_return_if_fail (evals != NULL);
+
+ g_print ("\treadonly:%s\n", e_client_is_readonly (client) ? "yes" : "no");
+ g_print ("\tonline:%s\n", e_client_is_online (client) ? "yes" : "no");
+ g_print ("\topened:%s\n", e_client_is_opened (client) ? "yes" : "no");
+ g_print ("\tcache dir: %s%s%s\n", evals->cache_dir ? "'" : "", evals->cache_dir ? evals->cache_dir : "none", evals->cache_dir ? "'" : "");
+ g_print ("\tcapabilities: ");
+ values = e_client_get_capabilities (client);
+ if (!values) {
+ g_print ("NULL");
+ } else {
+ while (values) {
+ const gchar *cap = values->data;
+
+ g_print ("'%s'", cap);
+ if (!e_client_check_capability (client, cap))
+ g_print (" (not found in EClient)");
+
+ values = values->next;
+
+ if (values)
+ g_print (", ");
+ }
+ }
+ g_print ("\n");
+
+ g_print ("\tdefault object: %s\n", evals->default_object ? "" : "none");
+ if (evals->default_object) {
+ gchar *comp_str = icalcomponent_as_ical_string_r (evals->default_object);
+ print_with_prefix (comp_str, "\t ");
+ g_free (comp_str);
+ }
+
+ g_print ("\tbackend properties:\n");
+ g_hash_table_foreach (evals->retrieved_props, print_each_property, NULL);
+}
+
+static void
+identify_source (ESource *source, ECalClientSourceType source_type)
+{
+ const gchar *name, *uri, *type;
+ gchar *abs_uri = NULL;
+
+ g_return_if_fail (source != NULL);
+
+ switch (source_type) {
+ case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
+ type = "events";
+ break;
+ case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
+ type = "tasks";
+ break;
+ case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
+ type = "memos";
+ break;
+ default:
+ type = "unknown-type";
+ break;
+ }
+
+ name = e_source_peek_name (source);
+ if (!name)
+ name = "Unknown name";
+
+ uri = e_source_peek_absolute_uri (source);
+ if (!uri) {
+ abs_uri = e_source_build_absolute_uri (source);
+ uri = abs_uri;
+ }
+ if (!uri)
+ uri = e_source_peek_relative_uri (source);
+ if (!uri)
+ uri = "Unknown uri";
+
+ g_print ("\n Checking %s source '%s' (%s)\n", type, name, uri);
+
+ g_free (abs_uri);
+}
+
+static void
+identify_client (ECalClient *cal_client)
+{
+ g_return_if_fail (cal_client != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (cal_client));
+
+ identify_source (e_client_get_source (E_CLIENT (cal_client)), e_cal_client_get_source_type (cal_client));
+}
+
+static void client_opened_async (GObject *source_object, GAsyncResult *result, gpointer async_data);
+
+static void
+continue_next_source (gpointer async_data)
+{
+ ESource *source = NULL;
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ g_return_if_fail (async_data != NULL);
+
+ while (async_data && foreach_configured_source_async_next (&async_data, &source)) {
+ ECalClientSourceType source_type = foreach_configured_source_async_get_source_type (async_data);
+
+ cal_client = e_cal_client_new (source, source_type, &error);
+ if (!cal_client) {
+ identify_source (source, source_type);
+ report_error ("cal client new", &error);
+ continue;
+ }
+
+ e_client_open (E_CLIENT (cal_client), TRUE, NULL, client_opened_async, async_data);
+ break;
+ }
+
+ if (!async_data) {
+ running_async--;
+ if (!running_async)
+ stop_main_loop (0);
+ }
+}
+
+static void
+client_got_backend_property_async (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ExtraValues *evals = user_data;
+ gchar *prop_value = NULL;
+ GError *error = NULL;
+ ECalClient *cal_client;
+
+ g_return_if_fail (source_object != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (source_object));
+ g_return_if_fail (evals != NULL);
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_client_get_backend_property_finish (E_CLIENT (cal_client), result, &prop_value, &error)) {
+ identify_client (cal_client);
+ report_error ("get backend property finish", &error);
+ }
+
+ g_hash_table_insert (evals->retrieved_props, evals->todo_prop_names->data, prop_value);
+ evals->todo_prop_names = g_slist_remove (evals->todo_prop_names, evals->todo_prop_names->data);
+
+ if (!evals->todo_prop_names) {
+ evals->cache_dir = e_cal_client_get_local_attachment_store (cal_client);
+
+ /* to cache them, as it can be fetched with idle as well */
+ e_client_get_capabilities (E_CLIENT (source_object));
+
+ identify_client (cal_client);
+ print_values (evals, E_CLIENT (source_object));
+
+ g_object_unref (source_object);
+
+ continue_next_source (evals->async_data);
+ extra_values_free (evals);
+ } else {
+ e_client_get_backend_property (E_CLIENT (cal_client), evals->todo_prop_names->data, NULL, client_got_backend_property_async, evals);
+ }
+}
+
+static void
+client_set_backend_property_async (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ExtraValues *evals = user_data;
+ GError *error = NULL;
+ ECalClient *cal_client;
+
+ g_return_if_fail (source_object != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (source_object));
+ g_return_if_fail (evals != NULL);
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_client_set_backend_property_finish (E_CLIENT (cal_client), result, &error)) {
+ /* it may fail on the set_backend_property */
+ g_clear_error (&error);
+ } else {
+ identify_client (cal_client);
+ g_printerr (" Might fail on set_backend_property, but reported success\n");
+ }
+
+ e_client_get_backend_property (E_CLIENT (cal_client), evals->todo_prop_names->data, NULL, client_got_backend_property_async, evals);
+}
+
+static void
+client_got_default_object_async (GObject *source_object, GAsyncResult *result, gpointer evals_data)
+{
+ ExtraValues *evals = evals_data;
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ g_return_if_fail (source_object != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (source_object));
+ g_return_if_fail (evals != NULL);
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_cal_client_get_default_object_finish (cal_client, result, &evals->default_object, &error)) {
+ identify_client (cal_client);
+ report_error ("get default object finish", &error);
+ }
+
+ e_client_set_backend_property (E_CLIENT (cal_client), "*unknown*property*", "*value*", NULL, client_set_backend_property_async, evals);
+}
+
+static void
+client_opened_async (GObject *source_object, GAsyncResult *result, gpointer async_data)
+{
+ ExtraValues *evals;
+ GError *error = NULL;
+ ECalClient *cal_client;
+
+ g_return_if_fail (source_object != NULL);
+ g_return_if_fail (E_IS_CAL_CLIENT (source_object));
+ g_return_if_fail (async_data != NULL);
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_client_open_finish (E_CLIENT (source_object), result, &error)) {
+ identify_client (cal_client);
+ report_error ("client open finish", &error);
+ g_object_unref (source_object);
+ continue_next_source (async_data);
+ return;
+ }
+
+ evals = g_new0 (ExtraValues, 1);
+ evals->async_data = async_data;
+ evals->todo_prop_names = get_known_prop_names ();
+ evals->retrieved_props = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+
+ e_cal_client_get_default_object (cal_client, NULL, client_got_default_object_async, evals);
+}
+
+static void
+check_source_sync (ESource *source, ECalClientSourceType source_type)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ GSList *properties, *p;
+ ExtraValues evals = { 0 };
+
+ g_return_if_fail (source != NULL);
+
+ identify_source (source, source_type);
+
+ cal_client = e_cal_client_new (source, source_type, &error);
+ if (!cal_client) {
+ report_error ("cal client new", &error);
+ return;
+ }
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), TRUE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ return;
+ }
+
+ if (!e_cal_client_get_default_object_sync (cal_client, &evals.default_object, NULL, &error)) {
+ report_error ("get default object sync", &error);
+ }
+
+ if (!e_client_set_backend_property_sync (E_CLIENT (cal_client), "*unknown*property*", "*value*", NULL, &error)) {
+ g_clear_error (&error);
+ } else {
+ identify_client (cal_client);
+ g_printerr (" Might fail on set_backend_property, but reported success\n");
+ }
+
+ evals.retrieved_props = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+
+ properties = get_known_prop_names ();
+ for (p = properties; p != NULL; p = p->next) {
+ gchar *prop_value = NULL;
+
+ if (!e_client_get_backend_property_sync (E_CLIENT (cal_client), p->data, &prop_value, NULL, &error)) {
+ identify_client (cal_client);
+ report_error ("get backend property sync", &error);
+ } else {
+ g_hash_table_insert (evals.retrieved_props, p->data, prop_value);
+ }
+ }
+ g_slist_free (properties);
+
+ evals.cache_dir = e_cal_client_get_local_attachment_store (cal_client);
+
+ print_values (&evals, E_CLIENT (cal_client));
+
+ g_hash_table_destroy (evals.retrieved_props);
+ icalcomponent_free (evals.default_object);
+ g_object_unref (cal_client);
+}
+
+static gboolean
+foreach_async (ECalClientSourceType source_type)
+{
+ gpointer async_data;
+ ESource *source = NULL;
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ async_data = foreach_configured_source_async_start (source_type, &source);
+ if (!async_data) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ running_async++;
+
+ while (cal_client = e_cal_client_new (source, source_type, &error), !cal_client) {
+ identify_source (source, source_type);
+ report_error ("cal client new", &error);
+
+ if (!foreach_configured_source_async_next (&async_data, &source)) {
+ running_async--;
+ if (!running_async)
+ stop_main_loop (0);
+ return FALSE;
+ }
+
+ identify_source (source, source_type);
+ }
+
+ e_client_open (E_CLIENT (cal_client), TRUE, NULL, client_opened_async, async_data);
+
+ return TRUE;
+}
+
+static gboolean
+in_main_thread_idle_cb (gpointer unused)
+{
+ g_print ("* run in main thread with mainloop running\n");
+ foreach_configured_source (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, check_source_sync);
+ foreach_configured_source (E_CAL_CLIENT_SOURCE_TYPE_TASKS, check_source_sync);
+ foreach_configured_source (E_CAL_CLIENT_SOURCE_TYPE_MEMOS, check_source_sync);
+ g_print ("---------------------------------------------------------\n\n");
+
+ g_print ("* run in main thread async\n");
+
+ if (!foreach_async (E_CAL_CLIENT_SOURCE_TYPE_EVENTS))
+ return FALSE;
+
+ if (!foreach_async (E_CAL_CLIENT_SOURCE_TYPE_TASKS))
+ return FALSE;
+
+ if (!foreach_async (E_CAL_CLIENT_SOURCE_TYPE_MEMOS))
+ return FALSE;
+
+ return FALSE;
+}
+
+static gpointer
+worker_thread (gpointer unused)
+{
+ g_print ("* run in dedicated thread with mainloop running\n");
+ foreach_configured_source (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, check_source_sync);
+ foreach_configured_source (E_CAL_CLIENT_SOURCE_TYPE_TASKS, check_source_sync);
+ foreach_configured_source (E_CAL_CLIENT_SOURCE_TYPE_MEMOS, check_source_sync);
+ g_print ("---------------------------------------------------------\n\n");
+
+ g_idle_add (in_main_thread_idle_cb, NULL);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ main_initialize ();
+
+ g_print ("* run in main thread without mainloop\n");
+ foreach_configured_source (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, check_source_sync);
+ foreach_configured_source (E_CAL_CLIENT_SOURCE_TYPE_TASKS, check_source_sync);
+ foreach_configured_source (E_CAL_CLIENT_SOURCE_TYPE_MEMOS, check_source_sync);
+ g_print ("---------------------------------------------------------\n\n");
+
+ start_in_thread_with_main_loop (worker_thread, NULL);
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-get-attachment-uris.c b/tests/libecal/client/test-client-get-attachment-uris.c
new file mode 100644
index 0000000..0d9a5ce
--- /dev/null
+++ b/tests/libecal/client/test-client-get-attachment-uris.c
@@ -0,0 +1,191 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <string.h>
+#include <libecal/e-cal-client.h>
+#include <libical/ical.h>
+
+#include "client-test-utils.h"
+
+#define ATTACH1 "file:///tmp/file1.x"
+#define ATTACH2 "file:///tmp/file2"
+#define ATTACH3 "file:///tmp/dir/fileÄ?Å¡Ä?Å?žýáÃé3"
+
+static gboolean
+manage_result (GSList *attachment_uris)
+{
+ gboolean res;
+
+ g_return_val_if_fail (attachment_uris != NULL, FALSE);
+ g_return_val_if_fail (g_slist_length (attachment_uris) == 3, FALSE);
+
+ res = g_slist_find_custom (attachment_uris, ATTACH1, g_str_equal)
+ && g_slist_find_custom (attachment_uris, ATTACH2, g_str_equal)
+ && g_slist_find_custom (attachment_uris, ATTACH3, g_str_equal);
+
+ if (!res) {
+ GSList *au;
+
+ g_printerr ("Failed: didn't return same three attachment uris, got instead:\n");
+ for (au = attachment_uris; au; au = au->next)
+ g_printerr ("\t'%s'\n", (const gchar *) au->data);
+ }
+
+ e_client_util_free_string_slist (attachment_uris);
+
+ return res;
+}
+
+static gboolean
+test_sync (ECalClient *cal_client)
+{
+ GError *error = NULL;
+ GSList *attachment_uris = NULL;
+ const gchar *uid = g_object_get_data (G_OBJECT (cal_client), "use-uid");
+
+ g_return_val_if_fail (uid != NULL, FALSE);
+
+ if (!e_cal_client_get_attachment_uris_sync (cal_client, uid, NULL, &attachment_uris, NULL, &error)) {
+ report_error ("get attachment uris sync", &error);
+ return FALSE;
+ }
+
+ return manage_result (attachment_uris);
+}
+
+/* asynchronous callback with a main-loop running */
+static void
+async_attachment_uris_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ GSList *attachment_uris = NULL;
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_cal_client_get_attachment_uris_finish (cal_client, result, &attachment_uris, &error)) {
+ report_error ("get attachment uris finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ stop_main_loop (manage_result (attachment_uris) ? 0 : 1);
+}
+
+/* synchronously in idle with main-loop running */
+static gboolean
+test_sync_in_idle (gpointer user_data)
+{
+ ECalClient *cal_client = user_data;
+ const gchar *uid;
+
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), FALSE);
+
+ if (!test_sync (cal_client)) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ uid = g_object_get_data (G_OBJECT (cal_client), "use-uid");
+
+ e_cal_client_get_attachment_uris (cal_client, uid, NULL, NULL, async_attachment_uris_result_ready, NULL);
+
+ return FALSE;
+}
+
+/* synchronously in a dedicated thread with main-loop running */
+static gpointer
+test_sync_in_thread (gpointer user_data)
+{
+ if (!test_sync (user_data)) {
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ g_idle_add (test_sync_in_idle, user_data);
+
+ return NULL;
+}
+
+static void
+add_attach (icalcomponent *icalcomp, const gchar *uri)
+{
+ gsize buf_size;
+ gchar *buf;
+ icalproperty *prop;
+ icalattach *attach;
+
+ g_return_if_fail (icalcomp != NULL);
+ g_return_if_fail (uri != NULL);
+
+ buf_size = 2 * strlen (uri);
+ buf = g_malloc0 (buf_size);
+ icalvalue_encode_ical_string (uri, buf, buf_size);
+ attach = icalattach_new_from_url (uri);
+ prop = icalproperty_new_attach (attach);
+ icalcomponent_add_property (icalcomp, prop);
+ icalattach_unref (attach);
+ g_free (buf);
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ icalcomponent *icalcomp;
+ struct icaltimetype now;
+ gchar *uid = NULL;
+
+ main_initialize ();
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+ icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
+ icalcomponent_set_summary (icalcomp, "Test event summary");
+ icalcomponent_set_dtstart (icalcomp, now);
+ icalcomponent_set_dtend (icalcomp, icaltime_from_timet (icaltime_as_timet (now) + 60 * 60 * 60, 0));
+ add_attach (icalcomp, ATTACH1);
+ add_attach (icalcomp, ATTACH2);
+ add_attach (icalcomp, ATTACH3);
+
+ if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error)) {
+ report_error ("create object sync", &error);
+ icalcomponent_free (icalcomp);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ icalcomponent_free (icalcomp);
+ g_object_set_data_full (G_OBJECT (cal_client), "use-uid", uid, g_free);
+
+ /* synchronously without main-loop */
+ if (!test_sync (cal_client)) {
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ start_in_thread_with_main_loop (test_sync_in_thread, cal_client);
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ g_object_unref (cal_client);
+
+ if (get_main_loop_stop_result () == 0)
+ g_print ("Test finished successfully.\n");
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-get-free-busy.c b/tests/libecal/client/test-client-get-free-busy.c
new file mode 100644
index 0000000..a493c97
--- /dev/null
+++ b/tests/libecal/client/test-client-get-free-busy.c
@@ -0,0 +1,164 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libecal/e-cal-client.h>
+#include <libecal/e-cal-time-util.h>
+#include <libical/ical.h>
+
+#include "client-test-utils.h"
+
+#define USER_EMAIL "user example com"
+
+static void
+free_busy_data_cb (ECalClient *client, const GSList *free_busy, const gchar *func_name)
+{
+ g_print (" Received %d Free/Busy components from %s\n", g_slist_length ((GSList *) free_busy), func_name);
+}
+
+static gboolean
+test_sync (void)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ icaltimezone *utc;
+ GSList *users = NULL;
+ time_t start, end;
+ gulong sig_id;
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ return FALSE;
+ }
+
+ utc = icaltimezone_get_utc_timezone ();
+ start = time_from_isodate ("20040212T000000Z");
+ end = time_add_day_with_zone (start, 2, utc);
+ users = g_slist_append (users, (gpointer) USER_EMAIL);
+
+ sig_id = g_signal_connect (cal_client, "free-busy-data", G_CALLBACK (free_busy_data_cb), (gpointer) G_STRFUNC);
+
+ if (!e_cal_client_get_free_busy_sync (cal_client, start, end, users, NULL, &error)) {
+ report_error ("get free busy sync", &error);
+ g_signal_handler_disconnect (cal_client, sig_id);
+ g_object_unref (cal_client);
+ g_slist_free (users);
+ return FALSE;
+ }
+
+ g_signal_handler_disconnect (cal_client, sig_id);
+
+ g_slist_free (users);
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ return FALSE;
+ }
+
+ g_object_unref (cal_client);
+
+ return TRUE;
+}
+
+/* asynchronous get_free_busy callback with a main-loop running */
+static void
+async_get_free_busy_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_cal_client_get_free_busy_finish (cal_client, result, &error)) {
+ report_error ("create object finish", &error);
+ g_object_unref (cal_client);
+ stop_main_loop (1);
+ return;
+ }
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ stop_main_loop (1);
+ return;
+ }
+
+ g_object_unref (cal_client);
+
+ stop_main_loop (0);
+}
+
+/* synchronously in idle with main-loop running */
+static gboolean
+test_async_in_idle (gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ icaltimezone *utc;
+ GSList *users = NULL;
+ time_t start, end;
+
+ if (!test_sync ()) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ utc = icaltimezone_get_utc_timezone ();
+ start = time_from_isodate ("20040212T000000Z");
+ end = time_add_day_with_zone (start, 2, utc);
+ users = g_slist_append (users, (gpointer) USER_EMAIL);
+
+ /* here is all Free/Busy information received */
+ g_signal_connect (cal_client, "free-busy-data", G_CALLBACK (free_busy_data_cb), (gpointer) G_STRFUNC);
+
+ e_cal_client_get_free_busy (cal_client, start, end, users, NULL, async_get_free_busy_result_ready, NULL);
+
+ g_slist_free (users);
+
+ return FALSE;
+}
+
+/* synchronously in a dedicated thread with main-loop running */
+static gpointer
+test_sync_in_thread (gpointer user_data)
+{
+ if (!test_sync ()) {
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ g_idle_add (test_async_in_idle, NULL);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ main_initialize ();
+
+ /* synchronously without main-loop */
+ if (!test_sync ())
+ return 1;
+
+ start_in_thread_with_main_loop (test_sync_in_thread, NULL);
+
+ if (get_main_loop_stop_result () == 0)
+ g_print ("Test finished successfully.\n");
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-get-object-list.c b/tests/libecal/client/test-client-get-object-list.c
new file mode 100644
index 0000000..0566f2e
--- /dev/null
+++ b/tests/libecal/client/test-client-get-object-list.c
@@ -0,0 +1,203 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libecal/e-cal-client.h>
+#include <libical/ical.h>
+
+#include "client-test-utils.h"
+
+#define EVENT_SUMMARY "Creation of new test event"
+#define EVENT_QUERY "(contains? \"summary\" \"" EVENT_SUMMARY "\")"
+
+static gboolean
+test_result (icalcomponent *icalcomp)
+{
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+ g_return_val_if_fail (g_strcmp0 (icalcomponent_get_summary (icalcomp), EVENT_SUMMARY) == 0, FALSE);
+
+ return TRUE;
+}
+
+static gboolean
+test_sync (ECalClient *cal_client)
+{
+ GError *error = NULL;
+ GSList *icalcomps = NULL, *ecalcomps = NULL;
+ gboolean res = TRUE;
+
+ if (!e_cal_client_get_object_list_sync (cal_client, EVENT_QUERY, &icalcomps, NULL, &error)) {
+ report_error ("get object list sync", &error);
+ return FALSE;
+ }
+
+ if (g_slist_length (icalcomps) != 1) {
+ g_printerr ("Failure: expected 1 item returned in icalcomps, got %d\n", g_slist_length (icalcomps));
+ res = FALSE;
+ } else {
+ res = res && test_result (icalcomps->data);
+ }
+
+ e_cal_client_free_icalcomp_slist (icalcomps);
+
+ if (!e_cal_client_get_object_list_as_comps_sync (cal_client, EVENT_QUERY, &ecalcomps, NULL, &error)) {
+ report_error ("get object list as comps sync", &error);
+ return FALSE;
+ }
+
+ if (g_slist_length (ecalcomps) != 1) {
+ g_printerr ("Failure: expected 1 item returned in ecalcomps, got %d\n", g_slist_length (ecalcomps));
+ res = FALSE;
+ } else {
+ res = res && test_result (e_cal_component_get_icalcomponent (ecalcomps->data));
+ }
+
+ e_cal_client_free_ecalcomp_slist (ecalcomps);
+
+ return res;
+}
+
+/* asynchronous callback with a main-loop running */
+static void
+async_get_object_list_as_comps_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ GSList *ecalcomps = NULL;
+ gboolean res = TRUE;
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_cal_client_get_object_list_as_comps_finish (cal_client, result, &ecalcomps, &error)) {
+ report_error ("get object list as comps finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ if (g_slist_length (ecalcomps) != 1) {
+ g_printerr ("Failure: expected 1 item returned in ecalcomps, got %d\n", g_slist_length (ecalcomps));
+ res = FALSE;
+ } else {
+ res = res && test_result (e_cal_component_get_icalcomponent (ecalcomps->data));
+ }
+
+ e_cal_client_free_ecalcomp_slist (ecalcomps);
+ stop_main_loop (res ? 0 : 1);
+}
+
+/* asynchronous callback with a main-loop running */
+static void
+async_get_object_list_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ GSList *icalcomps = NULL;
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_cal_client_get_object_list_finish (cal_client, result, &icalcomps, &error)) {
+ report_error ("get object list finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ if (g_slist_length (icalcomps) != 1) {
+ g_printerr ("Failure: expected 1 item returned in icalcomps, got %d\n", g_slist_length (icalcomps));
+ } else {
+ test_result (icalcomps->data);
+ }
+
+ e_cal_client_free_icalcomp_slist (icalcomps);
+
+ e_cal_client_get_object_list_as_comps (cal_client, EVENT_QUERY, NULL, async_get_object_list_as_comps_result_ready, NULL);
+}
+
+/* synchronously in idle with main-loop running */
+static gboolean
+test_sync_in_idle (gpointer user_data)
+{
+ ECalClient *cal_client = user_data;
+
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), FALSE);
+
+ if (!test_sync (cal_client)) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ e_cal_client_get_object_list (cal_client, EVENT_QUERY, NULL, async_get_object_list_result_ready, NULL);
+
+ return FALSE;
+}
+
+/* synchronously in a dedicated thread with main-loop running */
+static gpointer
+test_sync_in_thread (gpointer user_data)
+{
+ if (!test_sync (user_data)) {
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ g_idle_add (test_sync_in_idle, user_data);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ icalcomponent *icalcomp;
+ struct icaltimetype now;
+ gchar *uid = NULL;
+
+ main_initialize ();
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+ icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
+ icalcomponent_set_summary (icalcomp, EVENT_SUMMARY);
+ icalcomponent_set_dtstart (icalcomp, now);
+ icalcomponent_set_dtend (icalcomp, icaltime_from_timet (icaltime_as_timet (now) + 60 * 60 * 60, 0));
+
+ if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error)) {
+ report_error ("create object sync", &error);
+ g_object_unref (cal_client);
+ icalcomponent_free (icalcomp);
+ return 1;
+ }
+
+ icalcomponent_free (icalcomp);
+ g_free (uid);
+
+ /* synchronously without main-loop */
+ if (!test_sync (cal_client)) {
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ start_in_thread_with_main_loop (test_sync_in_thread, cal_client);
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ g_object_unref (cal_client);
+
+ if (get_main_loop_stop_result () == 0)
+ g_print ("Test finished successfully.\n");
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-get-view.c b/tests/libecal/client/test-client-get-view.c
new file mode 100644
index 0000000..2142b22
--- /dev/null
+++ b/tests/libecal/client/test-client-get-view.c
@@ -0,0 +1,230 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libecal/e-cal-client.h>
+#include <libical/ical.h>
+
+#include "client-test-utils.h"
+
+typedef enum {
+ SUBTEST_OBJECTS_ADDED,
+ SUBTEST_OBJECTS_MODIFIED,
+ SUBTEST_OBJECTS_REMOVED,
+ SUBTEST_VIEW_DONE,
+ NUM_SUBTESTS,
+ SUBTEST_RESET
+} SubTestId;
+
+static void
+subtest_passed (SubTestId id)
+{
+ static guint subtests_complete = 0;
+
+ if (id == SUBTEST_RESET) {
+ subtests_complete = 0;
+ return;
+ }
+
+ subtests_complete |= (1 << id);
+
+ if (subtests_complete == ((1 << NUM_SUBTESTS) - 1))
+ stop_main_loop (0);
+}
+
+static void
+objects_added_cb (GObject *object, const GSList *objects, gpointer data)
+{
+ const GSList *l;
+
+ for (l = objects; l; l = l->next)
+ g_print ("Object added %s (%s)\n", icalcomponent_get_uid (l->data), icalcomponent_get_summary (l->data));
+
+ subtest_passed (SUBTEST_OBJECTS_ADDED);
+}
+
+static void
+objects_modified_cb (GObject *object, const GSList *objects, gpointer data)
+{
+ const GSList *l;
+
+ for (l = objects; l; l = l->next)
+ g_print ("Object modified %s (%s)\n", icalcomponent_get_uid (l->data), icalcomponent_get_summary (l->data));
+
+ subtest_passed (SUBTEST_OBJECTS_MODIFIED);
+}
+
+static void
+objects_removed_cb (GObject *object, const GSList *objects, gpointer data)
+{
+ const GSList *l;
+
+ for (l = objects; l; l = l->next) {
+ ECalComponentId *id = l->data;
+
+ g_print ("Object removed: uid: %s, rid: %s\n", id->uid, id->rid);
+ }
+
+ subtest_passed (SUBTEST_OBJECTS_REMOVED);
+}
+
+static void
+complete_cb (GObject *object, const GError *error, gpointer data)
+{
+ g_print ("View complete (status: %d, error_msg:%s)\n", error ? error->code : 0, error ? error->message : "NULL");
+
+ subtest_passed (SUBTEST_VIEW_DONE);
+}
+
+static gpointer
+alter_cal_client (gpointer user_data)
+{
+ ECalClient *cal_client = user_data;
+ GError *error = NULL;
+ icalcomponent *icalcomp;
+ struct icaltimetype now;
+ gchar *uid = NULL;
+
+ g_return_val_if_fail (cal_client != NULL, NULL);
+
+ now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+ icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
+ icalcomponent_set_summary (icalcomp, "Initial event summary");
+ icalcomponent_set_dtstart (icalcomp, now);
+ icalcomponent_set_dtend (icalcomp, icaltime_from_timet (icaltime_as_timet (now) + 60 * 60 * 60, 0));
+
+ if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error)) {
+ report_error ("create object sync", &error);
+ icalcomponent_free (icalcomp);
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ icalcomponent_set_uid (icalcomp, uid);
+ icalcomponent_set_summary (icalcomp, "Modified event summary");
+
+ if (!e_cal_client_modify_object_sync (cal_client, icalcomp, CALOBJ_MOD_ALL, NULL, &error)) {
+ report_error ("modify object sync", &error);
+ icalcomponent_free (icalcomp);
+ g_free (uid);
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ if (!e_cal_client_remove_object_sync (cal_client, uid, NULL, CALOBJ_MOD_ALL, NULL, &error)) {
+ report_error ("remove object sync", &error);
+ icalcomponent_free (icalcomp);
+ g_free (uid);
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ g_free (uid);
+ icalcomponent_free (icalcomp);
+
+ return NULL;
+}
+
+static void
+async_get_view_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client = E_CAL_CLIENT (source_object);
+ ECalClientView *view = NULL;
+ GError *error = NULL;
+
+ g_return_if_fail (cal_client != NULL);
+
+ if (!e_cal_client_get_view_finish (cal_client, result, &view, &error)) {
+ report_error ("get view finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ subtest_passed (SUBTEST_RESET);
+ g_signal_connect (view, "objects_added", G_CALLBACK (objects_added_cb), cal_client);
+ g_signal_connect (view, "objects_modified", G_CALLBACK (objects_modified_cb), cal_client);
+ g_signal_connect (view, "objects_removed", G_CALLBACK (objects_removed_cb), cal_client);
+ g_signal_connect (view, "complete", G_CALLBACK (complete_cb), cal_client);
+
+ g_object_set_data_full (G_OBJECT (cal_client), "cal-view", view, g_object_unref);
+
+ e_cal_client_view_set_fields_of_interest (view, NULL, &error);
+ if (error)
+ report_error ("set fields of interest", &error);
+ e_cal_client_view_start (view, NULL);
+
+ alter_cal_client (cal_client);
+}
+
+static gpointer
+get_view_async (gpointer user_data)
+{
+ ECalClient *cal_client = user_data;
+
+ g_return_val_if_fail (user_data != NULL, NULL);
+
+ e_cal_client_get_view (cal_client, "(contains? \"any\" \"event\")", NULL, async_get_view_ready, NULL);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ ECalClientView *view = NULL;
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ main_initialize ();
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ if (!e_cal_client_get_view_sync (cal_client, "(contains? \"any\" \"event\")", &view, NULL, &error)) {
+ report_error ("get view sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ subtest_passed (SUBTEST_RESET);
+ g_signal_connect (view, "objects_added", G_CALLBACK (objects_added_cb), cal_client);
+ g_signal_connect (view, "objects_modified", G_CALLBACK (objects_modified_cb), cal_client);
+ g_signal_connect (view, "objects_removed", G_CALLBACK (objects_removed_cb), cal_client);
+ g_signal_connect (view, "complete", G_CALLBACK (complete_cb), cal_client);
+
+ e_cal_client_view_set_fields_of_interest (view, NULL, &error);
+ if (error)
+ report_error ("set fields of interest", &error);
+ e_cal_client_view_start (view, NULL);
+
+ start_in_thread_with_main_loop (alter_cal_client, cal_client);
+
+ g_object_unref (view);
+
+ if (get_main_loop_stop_result () != 0) {
+ g_object_unref (cal_client);
+ return get_main_loop_stop_result ();
+ }
+
+ start_in_idle_with_main_loop (get_view_async, cal_client);
+
+ g_object_set_data (G_OBJECT (cal_client), "cal-view", NULL);
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ g_object_unref (cal_client);
+
+ if (get_main_loop_stop_result () == 0)
+ g_print ("Test finished successfully.\n");
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-modify-object.c b/tests/libecal/client/test-client-modify-object.c
new file mode 100644
index 0000000..f8e9641
--- /dev/null
+++ b/tests/libecal/client/test-client-modify-object.c
@@ -0,0 +1,194 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libecal/e-cal-client.h>
+#include <libical/ical.h>
+
+#include "client-test-utils.h"
+
+#define EVENT_SUMMARY "Creation of new test event"
+
+static gboolean
+test_result (icalcomponent *icalcomp)
+{
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+ g_return_val_if_fail (g_strcmp0 (icalcomponent_get_summary (icalcomp), EVENT_SUMMARY) == 0, FALSE);
+
+ return TRUE;
+}
+
+static gboolean
+test_sync (ECalClient *cal_client)
+{
+ GError *error = NULL;
+ icalcomponent *icalcomp = NULL;
+ const gchar *uid = g_object_get_data (G_OBJECT (cal_client), "use-uid");
+
+ g_return_val_if_fail (uid != NULL, FALSE);
+
+ if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icalcomp, NULL, &error)) {
+ report_error ("get object sync", &error);
+ return FALSE;
+ }
+
+ icalcomponent_set_summary (icalcomp, EVENT_SUMMARY);
+
+ if (!e_cal_client_modify_object_sync (cal_client, icalcomp, CALOBJ_MOD_ALL, NULL, &error)) {
+ report_error ("modify object sync", &error);
+ icalcomponent_free (icalcomp);
+ return FALSE;
+ }
+
+ icalcomponent_free (icalcomp);
+
+ if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icalcomp, NULL, &error)) {
+ report_error ("get object sync after modification", &error);
+ return FALSE;
+ }
+
+ if (!test_result (icalcomp)) {
+ icalcomponent_free (icalcomp);
+ return FALSE;
+ }
+
+ icalcomponent_free (icalcomp);
+
+ return TRUE;
+}
+
+/* asynchronous callback with a main-loop running */
+static void
+async_modify_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ icalcomponent *icalcomp = NULL;
+ const gchar *uid;
+
+ cal_client = E_CAL_CLIENT (source_object);
+ uid = g_object_get_data (G_OBJECT (cal_client), "use-uid");
+
+ if (!e_cal_client_modify_object_finish (cal_client, result, &error)) {
+ report_error ("modify object finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icalcomp, NULL, &error)) {
+ report_error ("get object sync after async modification", &error);
+ return;
+ }
+
+ if (!test_result (icalcomp)) {
+ stop_main_loop (1);
+ } else {
+ stop_main_loop (0);
+ }
+
+ icalcomponent_free (icalcomp);
+}
+
+/* synchronously in idle with main-loop running */
+static gboolean
+test_sync_in_idle (gpointer user_data)
+{
+ ECalClient *cal_client = user_data;
+ const gchar *uid = g_object_get_data (G_OBJECT (cal_client), "use-uid");
+ icalcomponent *icalcomp = NULL;
+ GError *error = NULL;
+
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), FALSE);
+
+ if (!test_sync (cal_client)) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ if (!e_cal_client_get_object_sync (cal_client, uid, NULL, &icalcomp, NULL, &error)) {
+ report_error ("get object sync", &error);
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ icalcomponent_set_summary (icalcomp, EVENT_SUMMARY);
+
+ e_cal_client_modify_object (cal_client, icalcomp, CALOBJ_MOD_ALL, NULL, async_modify_result_ready, NULL);
+
+ icalcomponent_free (icalcomp);
+
+ return FALSE;
+}
+
+/* synchronously in a dedicated thread with main-loop running */
+static gpointer
+test_sync_in_thread (gpointer user_data)
+{
+ if (!test_sync (user_data)) {
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ g_idle_add (test_sync_in_idle, user_data);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ icalcomponent *icalcomp;
+ struct icaltimetype now;
+ gchar *uid = NULL;
+
+ main_initialize ();
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+ icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
+ icalcomponent_set_summary (icalcomp, "Initial" EVENT_SUMMARY);
+ icalcomponent_set_dtstart (icalcomp, now);
+ icalcomponent_set_dtend (icalcomp, icaltime_from_timet (icaltime_as_timet (now) + 60 * 60 * 60, 0));
+
+ if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error)) {
+ report_error ("create object sync", &error);
+ g_object_unref (cal_client);
+ icalcomponent_free (icalcomp);
+ return 1;
+ }
+
+ icalcomponent_free (icalcomp);
+
+ g_object_set_data_full (G_OBJECT (cal_client), "use-uid", uid, g_free);
+
+ /* synchronously without main-loop */
+ if (!test_sync (cal_client)) {
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ start_in_thread_with_main_loop (test_sync_in_thread, cal_client);
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ g_object_unref (cal_client);
+
+ if (get_main_loop_stop_result () == 0)
+ g_print ("Test finished successfully.\n");
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-open.c b/tests/libecal/client/test-client-open.c
new file mode 100644
index 0000000..4aa3e21
--- /dev/null
+++ b/tests/libecal/client/test-client-open.c
@@ -0,0 +1,124 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libecal/e-cal-client.h>
+#include <libical/ical.h>
+
+#include "client-test-utils.h"
+
+static gboolean
+test_sync (void)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ return FALSE;
+ }
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ return FALSE;
+ }
+
+ g_object_unref (cal_client);
+
+ return TRUE;
+}
+
+/* asynchronous remove callback with a main-loop running */
+static void
+async_remove_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_client_remove_finish (E_CLIENT (cal_client), result, &error)) {
+ report_error ("remove finish", &error);
+ g_object_unref (cal_client);
+ stop_main_loop (1);
+ return;
+ }
+
+ g_object_unref (cal_client);
+
+ stop_main_loop (0);
+}
+
+/* asynchronous open callback with a main-loop running */
+static void
+async_open_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_client_open_finish (E_CLIENT (cal_client), result, &error)) {
+ report_error ("open finish", &error);
+ g_object_unref (cal_client);
+ stop_main_loop (1);
+ return;
+ }
+
+ e_client_remove (E_CLIENT (cal_client), NULL, async_remove_ready, NULL);
+}
+
+/* synchronously in idle with main-loop running */
+static gboolean
+test_sync_in_idle (gpointer user_data)
+{
+ ECalClient *cal_client;
+
+ if (!test_sync ()) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ e_client_open (E_CLIENT (cal_client), FALSE, NULL, async_open_ready, NULL);
+
+ return FALSE;
+}
+
+/* synchronously in a dedicated thread with main-loop running */
+static gpointer
+test_sync_in_thread (gpointer user_data)
+{
+ if (!test_sync ()) {
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ g_idle_add (test_sync_in_idle, NULL);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ main_initialize ();
+
+ /* synchronously without main-loop */
+ if (!test_sync ()) {
+ return 1;
+ }
+
+ start_in_thread_with_main_loop (test_sync_in_thread, NULL);
+
+ if (get_main_loop_stop_result () == 0)
+ g_print ("Test finished successfully.\n");
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-receive-objects.c b/tests/libecal/client/test-client-receive-objects.c
new file mode 100644
index 0000000..90858f4
--- /dev/null
+++ b/tests/libecal/client/test-client-receive-objects.c
@@ -0,0 +1,142 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libecal/e-cal-client.h>
+#include <libical/ical.h>
+
+#include "client-test-utils.h"
+
+static icalcomponent *
+create_object (void)
+{
+ icalcomponent *icalcomp;
+ struct icaltimetype now;
+
+ now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+ icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
+ icalcomponent_set_summary (icalcomp, "To-be-received event summary");
+ icalcomponent_set_dtstart (icalcomp, now);
+ icalcomponent_set_dtend (icalcomp, icaltime_from_timet (icaltime_as_timet (now) + 60 * 60 * 60, 0));
+
+ return icalcomp;
+}
+
+static gboolean
+test_sync (ECalClient *cal_client)
+{
+ GError *error = NULL;
+ icalcomponent *icalcomp;
+
+ icalcomp = create_object ();
+
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+
+ if (!e_cal_client_receive_objects_sync (cal_client, icalcomp, NULL, &error)) {
+ report_error ("receive objects sync", &error);
+ icalcomponent_free (icalcomp);
+ return FALSE;
+ }
+
+ icalcomponent_free (icalcomp);
+
+ return TRUE;
+}
+
+/* asynchronous callback with a main-loop running */
+static void
+async_receive_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_cal_client_receive_objects_finish (cal_client, result, &error)) {
+ report_error ("receive objects finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ stop_main_loop (0);
+}
+
+/* synchronously in idle with main-loop running */
+static gboolean
+test_sync_in_idle (gpointer user_data)
+{
+ ECalClient *cal_client = user_data;
+ icalcomponent *icalcomp;
+
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), FALSE);
+
+ if (!test_sync (cal_client)) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ icalcomp = create_object ();
+ if (!icalcomp) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ e_cal_client_receive_objects (cal_client, icalcomp, NULL, async_receive_result_ready, NULL);
+
+ icalcomponent_free (icalcomp);
+
+ return FALSE;
+}
+
+/* synchronously in a dedicated thread with main-loop running */
+static gpointer
+test_sync_in_thread (gpointer user_data)
+{
+ if (!test_sync (user_data)) {
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ g_idle_add (test_sync_in_idle, user_data);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ main_initialize ();
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ /* synchronously without main-loop */
+ if (!test_sync (cal_client)) {
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ start_in_thread_with_main_loop (test_sync_in_thread, cal_client);
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ g_object_unref (cal_client);
+
+ if (get_main_loop_stop_result () == 0)
+ g_print ("Test finished successfully.\n");
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-refresh.c b/tests/libecal/client/test-client-refresh.c
new file mode 100644
index 0000000..5ebae91
--- /dev/null
+++ b/tests/libecal/client/test-client-refresh.c
@@ -0,0 +1,134 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <string.h>
+#include <libecal/e-cal-client.h>
+#include <libical/ical.h>
+
+#include "client-test-utils.h"
+
+static gboolean
+test_sync (ECalClient *cal_client)
+{
+ GError *error = NULL;
+
+ g_print ("Refresh supported: %s\n", e_client_check_refresh_supported (E_CLIENT (cal_client)) ? "yes" : "no");
+
+ if (!e_client_refresh_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("refresh sync", &error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* asynchronous callback with a main-loop running */
+static void
+async_refresh_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_client_refresh_finish (E_CLIENT (cal_client), result, &error)) {
+ report_error ("refresh finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ stop_main_loop (0);
+}
+
+/* synchronously in idle with main-loop running */
+static gboolean
+test_sync_in_idle (gpointer user_data)
+{
+ ECalClient *cal_client = user_data;
+
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), FALSE);
+
+ if (!test_sync (cal_client)) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ g_print ("Refresh supported: %s\n", e_client_check_refresh_supported (E_CLIENT (cal_client)) ? "yes" : "no");
+
+ e_client_refresh (E_CLIENT (cal_client), NULL, async_refresh_result_ready, NULL);
+
+ return FALSE;
+}
+
+/* synchronously in a dedicated thread with main-loop running */
+static gpointer
+test_sync_in_thread (gpointer user_data)
+{
+ if (!test_sync (user_data)) {
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ g_idle_add (test_sync_in_idle, user_data);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ icalcomponent *icalcomp;
+ struct icaltimetype now;
+ gchar *uid = NULL;
+
+ main_initialize ();
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+ icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
+ icalcomponent_set_summary (icalcomp, "Test event summary");
+ icalcomponent_set_dtstart (icalcomp, now);
+ icalcomponent_set_dtend (icalcomp, icaltime_from_timet (icaltime_as_timet (now) + 60 * 60 * 60, 0));
+
+ if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error)) {
+ report_error ("create object sync", &error);
+ icalcomponent_free (icalcomp);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ icalcomponent_free (icalcomp);
+ g_free (uid);
+
+ /* synchronously without main-loop */
+ if (!test_sync (cal_client)) {
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ start_in_thread_with_main_loop (test_sync_in_thread, cal_client);
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ g_object_unref (cal_client);
+
+ if (get_main_loop_stop_result () == 0)
+ g_print ("Test finished successfully.\n");
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-remove-object.c b/tests/libecal/client/test-client-remove-object.c
new file mode 100644
index 0000000..6fbd02d
--- /dev/null
+++ b/tests/libecal/client/test-client-remove-object.c
@@ -0,0 +1,156 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libecal/e-cal-client.h>
+#include <libical/ical.h>
+
+#include "client-test-utils.h"
+
+static gchar *
+create_object (ECalClient *cal_client)
+{
+ icalcomponent *icalcomp;
+ struct icaltimetype now;
+ gchar *uid = NULL;
+ GError *error = NULL;
+
+ g_return_val_if_fail (cal_client != NULL, NULL);
+
+ now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+ icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
+ icalcomponent_set_summary (icalcomp, "To-be-removed event summary");
+ icalcomponent_set_dtstart (icalcomp, now);
+ icalcomponent_set_dtend (icalcomp, icaltime_from_timet (icaltime_as_timet (now) + 60 * 60 * 60, 0));
+
+ if (!e_cal_client_create_object_sync (cal_client, icalcomp, &uid, NULL, &error)) {
+ report_error ("create object sync", &error);
+ icalcomponent_free (icalcomp);
+ return NULL;
+ }
+
+ icalcomponent_free (icalcomp);
+
+ g_return_val_if_fail (uid != NULL, NULL);
+
+ return uid;
+}
+
+static gboolean
+test_sync (ECalClient *cal_client)
+{
+ GError *error = NULL;
+ gchar *uid;
+
+ uid = create_object (cal_client);
+
+ g_return_val_if_fail (uid != NULL, FALSE);
+
+ if (!e_cal_client_remove_object_sync (cal_client, uid, NULL, CALOBJ_MOD_ALL, NULL, &error)) {
+ report_error ("remove object sync", &error);
+ g_free (uid);
+ return FALSE;
+ }
+
+ g_free (uid);
+
+ return TRUE;
+}
+
+/* asynchronous callback with a main-loop running */
+static void
+async_remove_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_cal_client_remove_object_finish (cal_client, result, &error)) {
+ report_error ("remove object finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ stop_main_loop (0);
+}
+
+/* synchronously in idle with main-loop running */
+static gboolean
+test_sync_in_idle (gpointer user_data)
+{
+ ECalClient *cal_client = user_data;
+ gchar *uid;
+
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), FALSE);
+
+ if (!test_sync (cal_client)) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ uid = create_object (cal_client);
+ if (!uid) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ e_cal_client_remove_object (cal_client, uid, NULL, CALOBJ_MOD_ALL, NULL, async_remove_result_ready, NULL);
+
+ g_free (uid);
+
+ return FALSE;
+}
+
+/* synchronously in a dedicated thread with main-loop running */
+static gpointer
+test_sync_in_thread (gpointer user_data)
+{
+ if (!test_sync (user_data)) {
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ g_idle_add (test_sync_in_idle, user_data);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ main_initialize ();
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ /* synchronously without main-loop */
+ if (!test_sync (cal_client)) {
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ start_in_thread_with_main_loop (test_sync_in_thread, cal_client);
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ g_object_unref (cal_client);
+
+ if (get_main_loop_stop_result () == 0)
+ g_print ("Test finished successfully.\n");
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-send-objects.c b/tests/libecal/client/test-client-send-objects.c
new file mode 100644
index 0000000..f8dfb7a
--- /dev/null
+++ b/tests/libecal/client/test-client-send-objects.c
@@ -0,0 +1,169 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libecal/e-cal-client.h>
+#include <libical/ical.h>
+
+#include "client-test-utils.h"
+
+static icalcomponent *
+create_object (void)
+{
+ icalcomponent *icalcomp;
+ struct icaltimetype now;
+
+ now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+ icalcomp = icalcomponent_new (ICAL_VEVENT_COMPONENT);
+ icalcomponent_set_summary (icalcomp, "To-be-sent event summary");
+ icalcomponent_set_dtstart (icalcomp, now);
+ icalcomponent_set_dtend (icalcomp, icaltime_from_timet (icaltime_as_timet (now) + 60 * 60 * 60, 0));
+
+ return icalcomp;
+}
+
+static gboolean
+manage_result (GSList *users, icalcomponent *modified_icalcomp)
+{
+ g_print ("Wishes to send to %d users", g_slist_length (users));
+ if (users) {
+ GSList *u;
+
+ g_print (": ");
+
+ for (u = users; u; u = u->next)
+ g_print ("%s%s", u == users ? "" : ", ", (const gchar *) u->data);
+ }
+ g_print ("\n");
+
+ if (!modified_icalcomp)
+ g_print ("No modified icalcomp, would send the same\n");
+ else
+ print_icomp (modified_icalcomp);
+
+ e_client_util_free_string_slist (users);
+ if (modified_icalcomp)
+ icalcomponent_free (modified_icalcomp);
+
+ return TRUE;
+}
+
+static gboolean
+test_sync (ECalClient *cal_client)
+{
+ GError *error = NULL;
+ icalcomponent *icalcomp, *modified_icalcomp = NULL;
+ GSList *users = NULL;
+
+ icalcomp = create_object ();
+
+ if (!e_cal_client_send_objects_sync (cal_client, icalcomp, &users, &modified_icalcomp, NULL, &error)) {
+ report_error ("send objects sync", &error);
+ icalcomponent_free (icalcomp);
+ return FALSE;
+ }
+
+ icalcomponent_free (icalcomp);
+
+ return manage_result (users, modified_icalcomp);
+}
+
+/* asynchronous callback with a main-loop running */
+static void
+async_send_result_ready (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+ GSList *users = NULL;
+ icalcomponent *modified_icalcomp = NULL;
+
+ cal_client = E_CAL_CLIENT (source_object);
+
+ if (!e_cal_client_send_objects_finish (cal_client, result, &users, &modified_icalcomp, &error)) {
+ report_error ("send objects finish", &error);
+ stop_main_loop (1);
+ return;
+ }
+
+ stop_main_loop (manage_result (users, modified_icalcomp) ? 0 : 1);
+}
+
+/* synchronously in idle with main-loop running */
+static gboolean
+test_sync_in_idle (gpointer user_data)
+{
+ ECalClient *cal_client = user_data;
+ icalcomponent *icalcomp;
+
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), FALSE);
+
+ if (!test_sync (cal_client)) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ icalcomp = create_object ();
+ if (!icalcomp) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ e_cal_client_send_objects (cal_client, icalcomp, NULL, async_send_result_ready, NULL);
+
+ icalcomponent_free (icalcomp);
+
+ return FALSE;
+}
+
+/* synchronously in a dedicated thread with main-loop running */
+static gpointer
+test_sync_in_thread (gpointer user_data)
+{
+ if (!test_sync (user_data)) {
+ stop_main_loop (1);
+ return NULL;
+ }
+
+ g_idle_add (test_sync_in_idle, user_data);
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ main_initialize ();
+
+ cal_client = new_temp_client (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, NULL);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ /* synchronously without main-loop */
+ if (!test_sync (cal_client)) {
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ start_in_thread_with_main_loop (test_sync_in_thread, cal_client);
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ g_object_unref (cal_client);
+
+ if (get_main_loop_stop_result () == 0)
+ g_print ("Test finished successfully.\n");
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/client/test-client-stress-factory--fifo.c b/tests/libecal/client/test-client-stress-factory--fifo.c
new file mode 100644
index 0000000..5a9db0a
--- /dev/null
+++ b/tests/libecal/client/test-client-stress-factory--fifo.c
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libecal/e-cal-client.h>
+
+#include "client-test-utils.h"
+
+#define NUM_CLIENTS 200
+
+gint
+main (gint argc, gchar **argv)
+{
+ ECalClientSourceType source_type = E_CAL_CLIENT_SOURCE_TYPE_EVENTS;
+ ECalClient *cal_clients[NUM_CLIENTS];
+ GError *error = NULL;
+ gint ii;
+
+ main_initialize ();
+
+ /* Create and open many cals; then remove each of them */
+
+ for (ii = 0; ii < NUM_CLIENTS; ii++) {
+ cal_clients[ii] = new_temp_client (source_type, NULL);
+ g_return_val_if_fail (cal_clients[ii] != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (cal_clients[ii]), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ while (ii >= 0) {
+ g_object_unref (cal_clients[ii]);
+ ii--;
+ }
+
+ return 1;
+ }
+ }
+
+ for (ii = 0; ii < NUM_CLIENTS; ii++) {
+ if (!e_client_remove_sync (E_CLIENT (cal_clients[ii]), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ while (ii < NUM_CLIENTS) {
+ g_object_unref (cal_clients[ii]);
+ ii++;
+ }
+ return 1;
+ }
+
+ g_object_unref (cal_clients[ii]);
+ }
+
+ return 0;
+}
diff --git a/tests/libecal/client/test-client-stress-factory--serial.c b/tests/libecal/client/test-client-stress-factory--serial.c
new file mode 100644
index 0000000..c178487
--- /dev/null
+++ b/tests/libecal/client/test-client-stress-factory--serial.c
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <libecal/e-cal-client.h>
+
+#include "client-test-utils.h"
+
+#define NUM_CLIENTS 200
+
+gint
+main (gint argc, gchar **argv)
+{
+ ECalClientSourceType source_type = E_CAL_CLIENT_SOURCE_TYPE_EVENTS;
+ GError *error = NULL;
+ gint ii;
+
+ main_initialize ();
+
+ /* Serially create, open, (close), and remove many cals */
+ for (ii = 0; ii < NUM_CLIENTS; ii++) {
+ ECalClient *cal_client = new_temp_client (source_type, NULL);
+ g_return_val_if_fail (cal_client != NULL, 1);
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ return 1;
+ }
+
+ if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ return 1;
+ }
+
+ g_object_unref (cal_client);
+ }
+
+ return 0;
+}
diff --git a/tests/libecal/client/test-client-stress-factory--single-cal.c b/tests/libecal/client/test-client-stress-factory--single-cal.c
new file mode 100644
index 0000000..579dffc
--- /dev/null
+++ b/tests/libecal/client/test-client-stress-factory--single-cal.c
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libecal/e-cal-client.h>
+
+#include "client-test-utils.h"
+
+#define NUM_OPENS 200
+
+gint
+main (gint argc, gchar **argv)
+{
+ ECalClientSourceType source_type = E_CAL_CLIENT_SOURCE_TYPE_EVENTS;
+ gchar *uri = NULL;
+ ECalClient *cal_client;
+ GError *error = NULL;
+ gint ii;
+
+ main_initialize ();
+
+ cal_client = new_temp_client (source_type, &uri);
+ g_return_val_if_fail (cal_client != NULL, 1);
+ g_return_val_if_fail (uri != NULL, 1);
+
+ g_object_unref (cal_client);
+
+ /* open and close the same cal repeatedly */
+ for (ii = 0; ii < NUM_OPENS; ii++) {
+ cal_client = e_cal_client_new_from_uri (uri, source_type, &error);
+ if (!cal_client) {
+ report_error ("new from uri", &error);
+ break;
+ }
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ break;
+ }
+
+ g_object_unref (cal_client);
+ }
+
+ cal_client = e_cal_client_new_from_uri (uri, source_type, &error);
+ if (!cal_client) {
+ g_clear_error (&error);
+ } else if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ report_error ("client open sync", &error);
+ g_object_unref (cal_client);
+ g_free (uri);
+ return 1;
+ } else if (!e_client_remove_sync (E_CLIENT (cal_client), NULL, &error)) {
+ report_error ("client remove sync", &error);
+ g_object_unref (cal_client);
+ g_free (uri);
+ return 1;
+ }
+
+ g_free (uri);
+ g_object_unref (cal_client);
+
+ return ii == NUM_OPENS ? 0 : 1;
+}
diff --git a/tests/libecal/client/test-client-stress-views.c b/tests/libecal/client/test-client-stress-views.c
new file mode 100644
index 0000000..7086b76
--- /dev/null
+++ b/tests/libecal/client/test-client-stress-views.c
@@ -0,0 +1,116 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <libecal/e-cal-client.h>
+
+#include "client-test-utils.h"
+
+#define NUM_VIEWS 200
+
+static void
+objects_added (ECalClientView *cal_view, const GSList *objects)
+{
+ const GSList *l;
+
+ for (l = objects; l; l = l->next) {
+ print_icomp (l->data);
+ }
+}
+
+static void
+objects_removed (ECalClientView *view, const GSList *ids)
+{
+ const GSList *l;
+
+ for (l = ids; l; l = l->next) {
+ printf (" Removed contact: %s\n", (gchar *) l->data);
+ }
+}
+
+static void
+complete (ECalClientView *view, const GError *error)
+{
+ printf ("view_complete (status == %d, error_msg == %s%s%s)\n", error ? error->code : 0, error ? "'" : "", error ? error->message : "NULL", error ? "'" : "");
+}
+
+static gint
+stress_cal_views (ECalClient *cal_client, gboolean in_thread)
+{
+ ECalClientView *view = NULL;
+ ECalClientView *new_view;
+ gint i;
+
+ g_return_val_if_fail (cal_client != NULL, -1);
+ g_return_val_if_fail (E_IS_CAL_CLIENT (cal_client), -1);
+
+ for (i = 0; i < NUM_VIEWS; i++) {
+ GError *error = NULL;
+
+ if (!e_cal_client_get_view_sync (cal_client, "#t", &new_view, NULL, &error)) {
+ report_error ("get cal view sync", &error);
+ g_object_unref (view);
+ return 1;
+ }
+
+ g_signal_connect (new_view, "objects_added", G_CALLBACK (objects_added), NULL);
+ g_signal_connect (new_view, "objects_removed", G_CALLBACK (objects_removed), NULL);
+ g_signal_connect (new_view, "complete", G_CALLBACK (complete), NULL);
+
+ e_cal_client_view_start (new_view, NULL);
+
+ if (view) {
+ /* wait 100 ms when in a thread */
+ if (in_thread)
+ g_usleep (100000);
+
+ e_cal_client_view_stop (view, NULL);
+ g_object_unref (view);
+ }
+
+ view = new_view;
+ }
+
+ e_cal_client_view_stop (view, NULL);
+ g_object_unref (view);
+
+ return 0;
+}
+
+static gpointer
+stress_cal_views_thread (gpointer user_data)
+{
+ stop_main_loop (stress_cal_views (user_data, TRUE));
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ ECalClient *cal_client;
+ GError *error = NULL;
+
+ main_initialize ();
+
+ cal_client = e_cal_client_new_system (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, &error);
+ if (!cal_client) {
+ report_error ("create local calendar", &error);
+ return 1;
+ }
+
+ if (!e_client_open_sync (E_CLIENT (cal_client), FALSE, NULL, &error)) {
+ g_object_unref (cal_client);
+ report_error ("open client sync", &error);
+ return 1;
+ }
+
+ /* test from main thread */
+ stress_cal_views (cal_client, FALSE);
+
+ /* test from dedicated thread */
+ start_in_thread_with_main_loop (stress_cal_views_thread, cal_client);
+
+ g_object_unref (cal_client);
+
+ return get_main_loop_stop_result ();
+}
diff --git a/tests/libecal/ecal-test-utils.c b/tests/libecal/ecal-test-utils.c
index 7f90366..9273796 100644
--- a/tests/libecal/ecal-test-utils.c
+++ b/tests/libecal/ecal-test-utils.c
@@ -632,7 +632,6 @@ ecal_test_utils_cal_get_free_busy (ECal *cal,
comp_string = e_cal_component_get_as_string (comp);
test_print ("%s\n", comp_string);
- g_object_unref (comp);
g_free (comp_string);
}
} else {
diff --git a/tests/libecal/test-ecal-get-free-busy.c b/tests/libecal/test-ecal-get-free-busy.c
index 7ed04d2..796bf98 100644
--- a/tests/libecal/test-ecal-get-free-busy.c
+++ b/tests/libecal/test-ecal-get-free-busy.c
@@ -25,8 +25,7 @@ main (gint argc, gchar **argv)
utc = icaltimezone_get_utc_timezone ();
start = time_from_isodate ("20040212T000000Z");
end = time_add_day_with_zone (start, 2, utc);
- /* XXX: create dummy list, which the file backend will ignore */
- users = g_list_prepend (users, NULL);
+ users = g_list_prepend (users, (gpointer) "user example com");
free_busy = ecal_test_utils_cal_get_free_busy (cal, users, start, end);
diff --git a/tests/libedataserverui/Makefile.am b/tests/libedataserverui/Makefile.am
index 4473a07..4603dff 100644
--- a/tests/libedataserverui/Makefile.am
+++ b/tests/libedataserverui/Makefile.am
@@ -1,5 +1,6 @@
noinst_PROGRAMS = \
test-category-completion \
+ test-client-examine-auth \
test-source-combo-box \
test-source-selector \
test-contact-store \
@@ -27,6 +28,10 @@ test_category_completion_CPPFLAGS = $(TEST_EDATASERVERUI_CPPFLAGS)
test_category_completion_SOURCES = test-category-completion.c
test_category_completion_LDADD = $(TEST_EDATASERVERUI_LDFLAGS)
+test_client_examine_auth_CPPFLAGS = $(TEST_EDATASERVERUI_CPPFLAGS)
+test_client_examine_auth_SOURCES = test-client-examine-auth.c
+test_client_examine_auth_LDADD = $(TEST_EDATASERVERUI_LDFLAGS)
+
test_source_selector_CPPFLAGS = $(TEST_EDATASERVERUI_CPPFLAGS)
test_source_selector_SOURCES = test-source-selector.c
test_source_selector_LDADD = $(TEST_EDATASERVERUI_LDFLAGS)
diff --git a/tests/libedataserverui/test-client-examine-auth.c b/tests/libedataserverui/test-client-examine-auth.c
new file mode 100644
index 0000000..d63f4d5
--- /dev/null
+++ b/tests/libedataserverui/test-client-examine-auth.c
@@ -0,0 +1,418 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <glib.h>
+
+#include <libedataserver/e-source-group.h>
+#include <libedataserverui/e-client-utils.h>
+#include <libedataserverui/e-passwords.h>
+
+static void stop_main_loop (gint stop_result);
+static void report_error (const gchar *operation, GError **error);
+static gpointer foreach_configured_source_async_start (ESource **source);
+static gboolean foreach_configured_source_async_next (gpointer *foreach_async_data, ESource **source);
+static gboolean foreach_async (void);
+
+static gint running_async = 0;
+static EClientSourceType source_type = E_CLIENT_SOURCE_TYPE_CONTACTS;
+
+static GSList *
+get_known_prop_names (void)
+{
+ GSList *prop_names = NULL;
+
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENED);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENING);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_ONLINE);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_READONLY);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CACHE_DIR);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CAPABILITIES);
+
+ return prop_names;
+}
+
+typedef struct _ExtraValues {
+ gpointer async_data;
+
+ GSList *todo_prop_names;
+ GHashTable *retrieved_props;
+} ExtraValues;
+
+static void
+extra_values_free (ExtraValues *evals)
+{
+ if (!evals)
+ return;
+
+ g_slist_free (evals->todo_prop_names);
+ g_hash_table_destroy (evals->retrieved_props);
+ g_free (evals);
+}
+
+static void
+print_each_property (gpointer prop_name, gpointer prop_value, gpointer user_data)
+{
+ g_return_if_fail (prop_name != NULL);
+
+ if (prop_value == NULL) {
+ g_print ("\t %s: NULL\n", (const gchar *) prop_name);
+ return;
+ }
+
+ g_print ("\t %s: ", (const gchar *) prop_name);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ GSList *values = e_client_util_parse_comma_strings (prop_value), *v;
+
+
+ for (v = values; v; v = v->next) {
+ if (v != values)
+ g_print (", ");
+
+ g_print ("'%s'", (const gchar *) v->data);
+ }
+
+ e_client_util_free_string_slist (values);
+ } else {
+ g_print ("'%s'", (const gchar *) prop_value);
+ }
+
+ g_print ("\n");
+}
+
+static void
+print_values (const ExtraValues *evals, EClient *client)
+{
+ const GSList *values;
+
+ g_return_if_fail (evals != NULL);
+
+ g_print ("\treadonly:%s\n", e_client_is_readonly (client) ? "yes" : "no");
+ g_print ("\tonline:%s\n", e_client_is_online (client) ? "yes" : "no");
+ g_print ("\topened:%s\n", e_client_is_opened (client) ? "yes" : "no");
+ g_print ("\tcapabilities: ");
+ values = e_client_get_capabilities (client);
+ if (!values) {
+ g_print ("NULL");
+ } else {
+ while (values) {
+ const gchar *cap = values->data;
+
+ g_print ("'%s'", cap);
+ if (!e_client_check_capability (client, cap))
+ g_print (" (not found in EClient)");
+
+ values = values->next;
+
+ if (values)
+ g_print (", ");
+ }
+ }
+ g_print ("\n");
+
+ g_print ("\tbackend properties:\n");
+ g_hash_table_foreach (evals->retrieved_props, print_each_property, NULL);
+}
+
+static void
+identify_source (ESource *source)
+{
+ const gchar *name, *uri;
+ gchar *abs_uri = NULL;
+
+ g_return_if_fail (source != NULL);
+
+ name = e_source_peek_name (source);
+ if (!name)
+ name = "Unknown name";
+
+ uri = e_source_peek_absolute_uri (source);
+ if (!uri) {
+ abs_uri = e_source_build_absolute_uri (source);
+ uri = abs_uri;
+ }
+ if (!uri)
+ uri = e_source_peek_relative_uri (source);
+ if (!uri)
+ uri = "Unknown uri";
+
+ g_print ("\n Checking source '%s' (%s)\n", name, uri);
+
+ g_free (abs_uri);
+}
+
+static void client_opened_async (GObject *source_object, GAsyncResult *result, gpointer async_data);
+
+static void
+continue_next_source (gpointer async_data)
+{
+ ESource *source = NULL;
+
+ g_return_if_fail (async_data != NULL);
+
+ while (async_data && foreach_configured_source_async_next (&async_data, &source)) {
+ identify_source (source);
+ e_client_utils_open_new (source, source_type, TRUE,
+ e_client_utils_authenticate_handler, NULL,
+ NULL, client_opened_async, async_data);
+ break;
+ }
+
+ if (!async_data) {
+ running_async--;
+ if (!running_async) {
+ while (source_type++, source_type < E_CLIENT_SOURCE_TYPE_LAST) {
+ if (foreach_async ())
+ return;
+ }
+
+ stop_main_loop (0);
+ }
+ }
+}
+
+static void
+client_got_backend_property_async (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ExtraValues *evals = user_data;
+ gchar *prop_value = NULL;
+ GError *error = NULL;
+ EClient *client;
+
+ g_return_if_fail (source_object != NULL);
+ g_return_if_fail (E_IS_CLIENT (source_object));
+ g_return_if_fail (evals != NULL);
+
+ client = E_CLIENT (source_object);
+
+ if (!e_client_get_backend_property_finish (client, result, &prop_value, &error)) {
+ report_error ("get backend property finish", &error);
+ }
+
+ g_hash_table_insert (evals->retrieved_props, evals->todo_prop_names->data, prop_value);
+ evals->todo_prop_names = g_slist_remove (evals->todo_prop_names, evals->todo_prop_names->data);
+
+ if (!evals->todo_prop_names) {
+ /* to cache them, as it can be fetched with idle as well */
+ e_client_get_capabilities (client);
+
+ print_values (evals, client);
+
+ g_object_unref (source_object);
+
+ continue_next_source (evals->async_data);
+ extra_values_free (evals);
+ } else {
+ e_client_get_backend_property (client, evals->todo_prop_names->data, NULL, client_got_backend_property_async, evals);
+ }
+}
+
+static void
+client_set_backend_property_async (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ ExtraValues *evals = user_data;
+ GError *error = NULL;
+ EClient *client;
+
+ g_return_if_fail (source_object != NULL);
+ g_return_if_fail (E_IS_CLIENT (source_object));
+ g_return_if_fail (evals != NULL);
+
+ client = E_CLIENT (source_object);
+
+ if (!e_client_set_backend_property_finish (client, result, &error)) {
+ /* it may fail on the set_backend_property */
+ g_clear_error (&error);
+ } else {
+ g_printerr (" Might fail on set_backend_property, but reported success\n");
+ }
+
+ e_client_get_backend_property (client, evals->todo_prop_names->data, NULL, client_got_backend_property_async, evals);
+}
+
+static void
+client_opened_async (GObject *source_object, GAsyncResult *result, gpointer async_data)
+{
+ ExtraValues *evals;
+ GError *error = NULL;
+ EClient *client = NULL;
+
+ g_return_if_fail (source_object == NULL);
+ g_return_if_fail (async_data != NULL);
+
+ if (!e_client_utils_open_new_finish (result, &client, &error)) {
+ report_error ("client utils open new finish", &error);
+ continue_next_source (async_data);
+ return;
+ }
+
+ evals = g_new0 (ExtraValues, 1);
+ evals->async_data = async_data;
+ evals->todo_prop_names = get_known_prop_names ();
+ evals->retrieved_props = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+
+ e_client_set_backend_property (client, "*unknown*property*", "*value*", NULL, client_set_backend_property_async, evals);
+}
+
+static gboolean
+foreach_async (void)
+{
+ gpointer async_data;
+ ESource *source = NULL;
+
+ async_data = foreach_configured_source_async_start (&source);
+ if (!async_data) {
+ stop_main_loop (1);
+ return FALSE;
+ }
+
+ running_async++;
+
+ identify_source (source);
+ e_client_utils_open_new (source, source_type, TRUE,
+ e_client_utils_authenticate_handler, NULL,
+ NULL, client_opened_async, async_data);
+
+ return TRUE;
+}
+
+static gboolean
+in_main_thread_idle_cb (gpointer unused)
+{
+ if (!foreach_async ())
+ return FALSE;
+
+ return FALSE;
+}
+
+static GMainLoop *loop = NULL;
+static gint main_stop_result = 0;
+
+static void
+stop_main_loop (gint stop_result)
+{
+ g_return_if_fail (loop != NULL);
+
+ main_stop_result = stop_result;
+ g_main_loop_quit (loop);
+}
+
+static gint
+get_main_loop_stop_result (void)
+{
+ return main_stop_result;
+}
+
+struct ForeachConfiguredData
+{
+ ESourceList *source_list;
+ GSList *current_group;
+ GSList *current_source;
+};
+
+static gpointer
+foreach_configured_source_async_start (ESource **source)
+{
+ struct ForeachConfiguredData *async_data;
+ ESourceList *source_list = NULL;
+ GError *error = NULL;
+
+ g_return_val_if_fail (source != NULL, NULL);
+
+ if (!e_client_utils_get_sources (&source_list, source_type, &error)) {
+ report_error ("get sources", &error);
+ return NULL;
+ }
+
+ g_return_val_if_fail (source_list != NULL, NULL);
+
+ async_data = g_new0 (struct ForeachConfiguredData, 1);
+ async_data->source_list = source_list;
+ async_data->current_group = e_source_list_peek_groups (source_list);
+ if (!async_data->current_group) {
+ gpointer ad = async_data;
+
+ foreach_configured_source_async_next (&ad, source);
+ return ad;
+ }
+
+ async_data->current_source = e_source_group_peek_sources (async_data->current_group->data);
+ if (!async_data->current_source) {
+ gpointer ad = async_data;
+
+ if (foreach_configured_source_async_next (&ad, source))
+ return ad;
+
+ return NULL;
+ }
+
+ *source = async_data->current_source->data;
+
+ return async_data;
+}
+
+static gboolean
+foreach_configured_source_async_next (gpointer *foreach_async_data, ESource **source)
+{
+ struct ForeachConfiguredData *async_data;
+
+ g_return_val_if_fail (foreach_async_data != NULL, FALSE);
+ g_return_val_if_fail (source != NULL, FALSE);
+
+ async_data = *foreach_async_data;
+ g_return_val_if_fail (async_data != NULL, FALSE);
+ g_return_val_if_fail (async_data->source_list != NULL, FALSE);
+ g_return_val_if_fail (async_data->current_group != NULL, FALSE);
+
+ if (async_data->current_source)
+ async_data->current_source = async_data->current_source->next;
+ if (async_data->current_source) {
+ *source = async_data->current_source->data;
+ return TRUE;
+ }
+
+ do {
+ async_data->current_group = async_data->current_group->next;
+ if (async_data->current_group)
+ async_data->current_source = e_source_group_peek_sources (async_data->current_group->data);
+ } while (async_data->current_group && !async_data->current_source);
+
+ if (async_data->current_source) {
+ *source = async_data->current_source->data;
+ return TRUE;
+ }
+
+ g_object_unref (async_data->source_list);
+ g_free (async_data);
+
+ *foreach_async_data = NULL;
+
+ return FALSE;
+}
+
+static void
+report_error (const gchar *operation, GError **error)
+{
+ g_return_if_fail (operation != NULL);
+
+ g_printerr ("Failed to %s: %s\n", operation, (error && *error) ? (*error)->message : "Unknown error");
+
+ g_clear_error (error);
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ g_type_init ();
+ g_thread_init (NULL);
+ gtk_init (&argc, &argv);
+
+ e_passwords_init ();
+
+ g_idle_add (in_main_thread_idle_cb, NULL);
+
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+
+ return get_main_loop_stop_result ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]