[evolution-data-server/dbus] Port libedata and libebook to DBUS
- From: Rob Bradford <rbradford src gnome org>
- To: svn-commits-list gnome org
- Subject: [evolution-data-server/dbus] Port libedata and libebook to DBUS
- Date: Fri, 24 Apr 2009 15:49:52 -0400 (EDT)
commit e93b8da22b9b7494517cfee8465f0b901230bb1b
Author: Rob Bradford <rob linux intel com>
Date: Fri Apr 24 19:42:06 2009 +0100
Port libedata and libebook to DBUS
---
addressbook/libebook/Makefile.am | 67 +-
addressbook/libebook/e-book-marshal.list | 5 +
addressbook/libebook/e-book-view-private.h | 29 +-
addressbook/libebook/e-book-view.c | 512 +--
addressbook/libebook/e-book-view.h | 20 +-
addressbook/libebook/e-book.c | 4778 ++++++--------------
addressbook/libebook/e-book.h | 23 +-
addressbook/libebook/e-error.h | 40 +
addressbook/libebook/libebook.pc.in | 5 +-
addressbook/libedata-book/Makefile.am | 90 +-
addressbook/libedata-book/e-book-backend-sync.h | 1 -
addressbook/libedata-book/e-book-backend.c | 54 +-
addressbook/libedata-book/e-book-backend.h | 7 +-
addressbook/libedata-book/e-data-book-factory.c | 761 ++--
addressbook/libedata-book/e-data-book-factory.h | 85 +-
addressbook/libedata-book/e-data-book-types.h | 99 +-
addressbook/libedata-book/e-data-book-view.c | 1044 ++---
addressbook/libedata-book/e-data-book-view.h | 79 +-
addressbook/libedata-book/e-data-book.c | 1355 +++----
addressbook/libedata-book/e-data-book.h | 178 +-
addressbook/libedata-book/glib-gen.mak | 42 +
addressbook/libedata-book/libedata-book.pc.in | 4 +-
addressbook/libedata-book/opid.c | 75 +
addressbook/libedata-book/opid.h | 28 +
...ome.evolution.dataserver.AddressBook.service.in | 3 +
25 files changed, 3445 insertions(+), 5939 deletions(-)
diff --git a/addressbook/libebook/Makefile.am b/addressbook/libebook/Makefile.am
index f78cf36..46f14af 100644
--- a/addressbook/libebook/Makefile.am
+++ b/addressbook/libebook/Makefile.am
@@ -5,56 +5,37 @@ INCLUDES = \
-I$(top_builddir) \
-I$(top_srcdir)/addressbook \
-I$(top_builddir)/addressbook \
- -I$(top_builddir)/addressbook/libebook \
- $(EVOLUTION_ADDRESSBOOK_CFLAGS)
+ $(EVOLUTION_ADDRESSBOOK_CFLAGS)
-# The corba stubs and skels
-CORBA_GENERATED_C = \
- Evolution-DataServer-Addressbook-common.c \
- Evolution-DataServer-Addressbook-skels.c \
- Evolution-DataServer-Addressbook-stubs.c
-CORBA_GENERATED_H = \
- Evolution-DataServer-Addressbook.h
-
-CORBA_GENERATED = $(CORBA_GENERATED_C) $(CORBA_GENERATED_H)
-
-idls = \
- $(srcdir)/../idl/Evolution-DataServer-Addressbook.idl
-
-idl_flags = $(IDL_INCLUDES)
-
-$(CORBA_GENERATED_H): $(idls)
- $(ORBIT_IDL) $(idl_flags) $(srcdir)/../idl/Evolution-DataServer-Addressbook.idl
-$(CORBA_GENERATED_C): $(CORBA_GENERATED_H)
+# The marshallers
+MARSHAL_GENERATED = e-book-marshal.c e-book-marshal.h
+ EVO_MARSHAL_RULE@
# The library
lib_LTLIBRARIES = libebook-1.2.la
-libebook_1_2_la_SOURCES = \
- $(CORBA_GENERATED_C) \
- $(CORBA_GENERATED_H) \
+libebook_1_2_la_SOURCES = \
+ $(MARSHAL_GENERATED) \
+ $(DBUS_GENERATED_H) \
e-address-western.c \
- e-book-listener.c \
- e-book-listener.h \
e-book-query.c \
- e-book-view-listener.c \
- e-book-view-listener.h \
- e-book-view-private.h \
e-book-view.c \
+ e-book-view-private.h \
e-book.c \
e-contact.c \
e-destination.c \
e-name-western.c \
- e-name-western-tables.h \
- e-vcard.c
+ e-name-western-tables.h \
+ e-vcard.c \
+ e-error.h
libebook_1_2_la_LIBADD = \
- $(top_builddir)/camel/libcamel-1.2.la \
- $(top_builddir)/libedataserver/libedataserver-1.2.la \
- $(EVOLUTION_ADDRESSBOOK_LIBS)
+ $(EVOLUTION_ADDRESSBOOK_LIBS) \
+ $(top_builddir)/camel/libcamel-$(API_VERSION).la \
+ $(top_builddir)/libedataserver/libedataserver-$(API_VERSION).la
libebook_1_2_la_LDFLAGS = \
- -version-info $(LIBEBOOK_CURRENT):$(LIBEBOOK_REVISION):$(LIBEBOOK_AGE) $(NO_UNDEFINED)
+ -version-info $(LIBEBOOK_CURRENT):$(LIBEBOOK_REVISION):$(LIBEBOOK_AGE)
libebookincludedir = $(privincludedir)/libebook
@@ -72,20 +53,24 @@ libebookinclude_HEADERS = \
%-$(API_VERSION).pc: %.pc
cp $< $@
-e-name-western-tables.h: e-name-western-tables.h.in
- ${srcdir}/gen-western-table.py < $< > $@
-
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libebook-$(API_VERSION).pc
-BUILT_SOURCES = $(CORBA_GENERATED)
+DBUS_GENERATED_H = e-data-book-factory-bindings.h e-data-book-bindings.h e-data-book-view-bindings.h
+%-glue.h: $(top_srcdir)/addressbook/libedata-book/%.xml
+ dbus-binding-tool --mode=glib-server --output=$@ --prefix=$(subst -,_,$*) $^
+
+%-bindings.h: $(top_srcdir)/addressbook/libedata-book/%.xml
+ dbus-binding-tool --mode=glib-client --output=$@ --prefix=$(subst -,_,$*) $^
+
+BUILT_SOURCES = $(DBUS_GENERATED_H) $(MARSHAL_GENERATED)
CLEANFILES = $(BUILT_SOURCES)
DISTCLEANFILES = $(pkgconfig_DATA)
EXTRA_DIST = \
- $(pkgconfig_DATA:-$(API_VERSION).pc=.pc.in) \
- e-name-western-tables.h.in \
- gen-western-table.py
+ e-book-marshal.list \
+ $(pkgconfig_DATA:-$(API_VERSION).pc=.pc.in)
dist-hook:
cd $(distdir); rm -f $(BUILT_SOURCES)
+
diff --git a/addressbook/libebook/e-book-marshal.list b/addressbook/libebook/e-book-marshal.list
new file mode 100644
index 0000000..680ea03
--- /dev/null
+++ b/addressbook/libebook/e-book-marshal.list
@@ -0,0 +1,5 @@
+NONE:NONE
+NONE:BOOL
+NONE:POINTER
+NONE:STRING
+NONE:INT
diff --git a/addressbook/libebook/e-book-view-private.h b/addressbook/libebook/e-book-view-private.h
index a8e546a..1737df3 100644
--- a/addressbook/libebook/e-book-view-private.h
+++ b/addressbook/libebook/e-book-view-private.h
@@ -1,25 +1,30 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * The Evolution addressbook client object.
+ * Copyright (C) 2006 OpenedHand Ltd
*
- * Author:
- * Nat Friedman (nat 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.
*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Ross Burton <ross openedhand com>
*/
#ifndef __E_BOOK_VIEW_PRIVATE_H__
#define __E_BOOK_VIEW_PRIVATE_H__
-#include <glib.h>
-#include <glib-object.h>
-
-#include "Evolution-DataServer-Addressbook.h"
-#include "e-book-view-listener.h"
-
-EBookView *e_book_view_new (GNOME_Evolution_Addressbook_BookView corba_book_view, EBookViewListener *listener);
+#include "e-book.h"
+#include "e-book-view.h"
-void e_book_view_set_book (EBookView *book_view, struct _EBook *book);
+EBookView *_e_book_view_new (EBook *book, DBusGProxy *view_proxy);
G_END_DECLS
diff --git a/addressbook/libebook/e-book-view.c b/addressbook/libebook/e-book-view.c
index acb6cf4..3777c18 100644
--- a/addressbook/libebook/e-book-view.c
+++ b/addressbook/libebook/e-book-view.c
@@ -1,208 +1,253 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * The Evolution addressbook client object.
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
*
- * Author:
- * Nat Friedman (nat 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.
*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Ross Burton <ross linux intel com>
*/
-#include <config.h>
-
-#include "e-book-view-listener.h"
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include "e-book.h"
#include "e-book-view.h"
#include "e-book-view-private.h"
-#include "e-book.h"
-
-static GObjectClass *parent_class;
-
-struct _EBookViewPrivate {
- GNOME_Evolution_Addressbook_BookView corba_book_view;
+#include <libedata-book/e-data-book-view-bindings.h>
+#include "e-book-marshal.h"
- EBook *book;
+G_DEFINE_TYPE(EBookView, e_book_view, G_TYPE_OBJECT);
- EBookViewListener *listener;
+#define E_BOOK_VIEW_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_BOOK_VIEW, EBookViewPrivate))
- int response_id;
+struct _EBookViewPrivate {
+ EBook *book;
+ DBusGProxy *view_proxy;
+ gboolean running;
};
enum {
- CONTACTS_CHANGED,
- CONTACTS_REMOVED,
- CONTACTS_ADDED,
- SEQUENCE_COMPLETE,
- STATUS_MESSAGE,
- LAST_SIGNAL
+ CONTACTS_CHANGED,
+ CONTACTS_REMOVED,
+ CONTACTS_ADDED,
+ SEQUENCE_COMPLETE,
+ STATUS_MESSAGE,
+ LAST_SIGNAL
};
-
-static guint e_book_view_signals [LAST_SIGNAL];
+static guint signals [LAST_SIGNAL];
static void
-e_book_view_do_added_event (EBookView *book_view,
- EBookViewListenerResponse *resp)
+e_book_view_dispose (GObject *object)
{
- g_signal_emit (book_view, e_book_view_signals [CONTACTS_ADDED], 0,
- resp->contacts);
+ EBookView *view = E_BOOK_VIEW (object);
+
+ if (view->priv->view_proxy) {
+ org_gnome_evolution_dataserver_addressbook_BookView_dispose (view->priv->view_proxy, NULL);
+ g_object_unref (view->priv->view_proxy);
+ view->priv->view_proxy = NULL;
+ }
+
+ if (view->priv->book) {
+ g_object_unref (view->priv->book);
+ view->priv->book = NULL;
+ }
}
static void
-e_book_view_do_modified_event (EBookView *book_view,
- EBookViewListenerResponse *resp)
+e_book_view_class_init (EBookViewClass *klass)
{
- g_signal_emit (book_view, e_book_view_signals [CONTACTS_CHANGED], 0,
- resp->contacts);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = e_book_view_dispose;
+
+ g_type_class_add_private (klass, sizeof (EBookViewPrivate));
+
+ signals [CONTACTS_CHANGED] = g_signal_new ("contacts_changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookViewClass, contacts_changed),
+ NULL, NULL,
+ e_book_marshal_NONE__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+ signals [CONTACTS_REMOVED] = g_signal_new ("contacts_removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookViewClass, contacts_removed),
+ NULL, NULL,
+ e_book_marshal_NONE__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+ signals [CONTACTS_ADDED] = g_signal_new ("contacts_added",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookViewClass, contacts_added),
+ NULL, NULL,
+ e_book_marshal_NONE__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+ signals [SEQUENCE_COMPLETE] = g_signal_new ("sequence_complete",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookViewClass, sequence_complete),
+ NULL, NULL,
+ e_book_marshal_NONE__INT,
+ G_TYPE_NONE, 1, G_TYPE_INT);
+ signals [STATUS_MESSAGE] = g_signal_new ("status_message",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookViewClass, status_message),
+ NULL, NULL,
+ e_book_marshal_NONE__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
}
static void
-e_book_view_do_removed_event (EBookView *book_view,
- EBookViewListenerResponse *resp)
+e_book_view_init (EBookView *view)
{
- g_signal_emit (book_view, e_book_view_signals [CONTACTS_REMOVED], 0,
- resp->ids);
-}
+ EBookViewPrivate *priv = E_BOOK_VIEW_GET_PRIVATE (view);
-static void
-e_book_view_do_complete_event (EBookView *book_view,
- EBookViewListenerResponse *resp)
-{
- g_signal_emit (book_view, e_book_view_signals [SEQUENCE_COMPLETE], 0,
- resp->status);
+ priv->book = NULL;
+ priv->view_proxy = NULL;
+ priv->running = FALSE;
+
+ view->priv = priv;
}
static void
-e_book_view_do_status_message_event (EBookView *book_view,
- EBookViewListenerResponse *resp)
+status_message_cb (DBusGProxy *proxy, const char *message, EBookView *book_view)
{
- g_signal_emit (book_view, e_book_view_signals [STATUS_MESSAGE], 0,
- resp->message);
-}
+ if (!book_view->priv->running)
+ return;
+ g_signal_emit (book_view, signals[STATUS_MESSAGE], 0, message);
+}
static void
-e_book_view_handle_response (EBookViewListener *listener, EBookViewListenerResponse *resp, EBookView *book_view)
+contacts_added_cb (DBusGProxy *proxy, const char **vcards, EBookView *book_view)
{
- /* we shouldn't need this check. EBVL only emits the signal when resp != NULL */
- if (resp == NULL)
- return;
-
- switch (resp->op) {
- case ContactsAddedEvent:
- e_book_view_do_added_event (book_view, resp);
- break;
- case ContactsModifiedEvent:
- e_book_view_do_modified_event (book_view, resp);
- break;
- case ContactsRemovedEvent:
- e_book_view_do_removed_event (book_view, resp);
- break;
- case SequenceCompleteEvent:
- e_book_view_do_complete_event (book_view, resp);
- break;
- case StatusMessageEvent:
- e_book_view_do_status_message_event (book_view, resp);
- break;
- default:
- g_error ("EBookView: Unknown operation %d in listener queue!\n",
- resp->op);
- break;
- }
-}
+ const char **p;
+ GList *contacts = NULL;
-static gboolean
-e_book_view_construct (EBookView *book_view, GNOME_Evolution_Addressbook_BookView corba_book_view, EBookViewListener *listener)
-{
- CORBA_Environment ev;
- g_return_val_if_fail (book_view != NULL, FALSE);
- g_return_val_if_fail (E_IS_BOOK_VIEW (book_view), FALSE);
+ if (!book_view->priv->running)
+ return;
- /*
- * Copy in the corba_book_view.
- */
- CORBA_exception_init (&ev);
+ for (p = vcards; *p; p++) {
+ contacts = g_list_prepend (contacts, e_contact_new_from_vcard (*p));
+ }
+ contacts = g_list_reverse (contacts);
- book_view->priv->corba_book_view = bonobo_object_dup_ref(corba_book_view, &ev);
+ g_signal_emit (book_view, signals[CONTACTS_ADDED], 0, contacts);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_view_construct: Exception duplicating corba_book_view.\n");
- CORBA_exception_free (&ev);
- book_view->priv->corba_book_view = CORBA_OBJECT_NIL;
- return FALSE;
- }
+ g_list_foreach (contacts, (GFunc)g_object_unref, NULL);
+ g_list_free (contacts);
+}
+
+static void
+contacts_changed_cb (DBusGProxy *proxy, const char **vcards, EBookView *book_view)
+{
+ const char **p;
+ GList *contacts = NULL;
- CORBA_exception_free (&ev);
+ if (!book_view->priv->running)
+ return;
- /*
- * Create our local BookListener interface.
- */
- book_view->priv->listener = listener;
- book_view->priv->response_id = g_signal_connect (book_view->priv->listener, "response",
- G_CALLBACK (e_book_view_handle_response), book_view);
+ for (p = vcards; *p; p++) {
+ contacts = g_list_prepend (contacts, e_contact_new_from_vcard (*p));
+ }
+ contacts = g_list_reverse (contacts);
- bonobo_object_ref(BONOBO_OBJECT(book_view->priv->listener));
+ g_signal_emit (book_view, signals[CONTACTS_CHANGED], 0, contacts);
- return TRUE;
+ g_list_foreach (contacts, (GFunc)g_object_unref, NULL);
+ g_list_free (contacts);
}
-/**
- * e_book_view_new:
- * @corba_book_view: a CORBA BookView object
- * @listener: an #EBookViewListener
- *
- * Creates a new #EBookView based on @corba_book_view and listening to
- * @listener. This is a private function, applications should call
- * #e_book_get_book_view or #e_book_async_get_book_view.
- *
- * Return value: A new #EBookView.
- **/
-EBookView *
-e_book_view_new (GNOME_Evolution_Addressbook_BookView corba_book_view, EBookViewListener *listener)
+static void
+contacts_removed_cb (DBusGProxy *proxy, const char **ids, EBookView *book_view)
{
- EBookView *book_view;
+ const char **p;
+ GList *list = NULL;
- book_view = g_object_new (E_TYPE_BOOK_VIEW, NULL);
+ if (!book_view->priv->running)
+ return;
- if (! e_book_view_construct (book_view, corba_book_view, listener)) {
- g_object_unref (book_view);
- return NULL;
- }
+ for (p = ids; *p; p++) {
+ list = g_list_prepend (list, (char*)*p);
+ }
+ list = g_list_reverse (list);
- return book_view;
+ g_signal_emit (book_view, signals[CONTACTS_REMOVED], 0, list);
+
+ /* No need to free the values, our caller will */
+ g_list_free (list);
}
-/**
- * e_book_view_set_book:
- * @book_view: an #EBookView
- * @book: an #EBook
- *
- * Makes @book_view listen to changes in @book. This function apparently
- * has no effect for the time being.
- **/
-void
-e_book_view_set_book (EBookView *book_view, EBook *book)
+static void
+complete_cb (DBusGProxy *proxy, guint status, EBookView *book_view)
{
- g_return_if_fail (book_view && E_IS_BOOK_VIEW (book_view));
- g_return_if_fail (book && E_IS_BOOK (book));
- g_return_if_fail (book_view->priv->book == NULL);
+ if (!book_view->priv->running)
+ return;
- book_view->priv->book = book;
- g_object_ref (book);
+ g_signal_emit (book_view, signals[SEQUENCE_COMPLETE], 0, status);
}
-/**
- * e_book_view_get_book:
- * @book_view: an #EBookView
+/*
+ * e_book_view_new:
+ * @book: an #EBook
+ * @view_proxy: The #DBusGProxy to get signals from
*
- * Returns the #EBook that this book view is monitoring.
+ * Creates a new #EBookView based on #EBook and listening to @view_proxy. This
+ * is a private function, applications should call #e_book_get_book_view or
+ * #e_book_async_get_book_view.
*
- * Return value: an #EBook.
+ * Return value: A new #EBookView.
**/
-EBook*
+EBookView*
+_e_book_view_new (EBook *book, DBusGProxy *view_proxy)
+{
+ EBookView *view;
+ EBookViewPrivate *priv;
+
+ view = g_object_new (E_TYPE_BOOK_VIEW, NULL);
+ priv = view->priv;
+
+ priv->book = g_object_ref (book);
+
+ /* Take ownership of the view_proxy object */
+ priv->view_proxy = view_proxy;
+ g_object_add_weak_pointer (G_OBJECT (view_proxy), (gpointer)&priv->view_proxy);
+
+ dbus_g_proxy_add_signal (view_proxy, "StatusMessage", G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (view_proxy, "StatusMessage", G_CALLBACK (status_message_cb), view, NULL);
+ dbus_g_proxy_add_signal (view_proxy, "ContactsAdded", G_TYPE_STRV, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (view_proxy, "ContactsAdded", G_CALLBACK (contacts_added_cb), view, NULL);
+ dbus_g_proxy_add_signal (view_proxy, "ContactsChanged", G_TYPE_STRV, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (view_proxy, "ContactsChanged", G_CALLBACK (contacts_changed_cb), view, NULL);
+ dbus_g_proxy_add_signal (view_proxy, "ContactsRemoved", G_TYPE_STRV, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (view_proxy, "ContactsRemoved", G_CALLBACK (contacts_removed_cb), view, NULL);
+ dbus_g_proxy_add_signal (view_proxy, "Complete", G_TYPE_UINT, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (view_proxy, "Complete", G_CALLBACK (complete_cb), view, NULL);
+
+ return view;
+}
+
+EBook *
e_book_view_get_book (EBookView *book_view)
{
- g_return_val_if_fail (book_view && E_IS_BOOK_VIEW (book_view), NULL);
+ g_return_val_if_fail (E_IS_BOOK_VIEW (book_view), NULL);
- return book_view->priv->book;
+ return book_view->priv->book;
}
/**
@@ -214,19 +259,25 @@ e_book_view_get_book (EBookView *book_view)
void
e_book_view_start (EBookView *book_view)
{
- CORBA_Environment ev;
+ GError *error = NULL;
- g_return_if_fail (book_view && E_IS_BOOK_VIEW (book_view));
+ g_return_if_fail (E_IS_BOOK_VIEW (book_view));
- CORBA_exception_init (&ev);
+ book_view->priv->running = TRUE;
- e_book_view_listener_start (book_view->priv->listener);
+ if (book_view->priv->view_proxy) {
+ org_gnome_evolution_dataserver_addressbook_BookView_start (book_view->priv->view_proxy, &error);
+ if (error) {
+ g_warning ("Cannot start book view: %s\n", error->message);
- GNOME_Evolution_Addressbook_BookView_start (book_view->priv->corba_book_view, &ev);
+ /* Fake a sequence-complete so that the application knows this failed */
+ /* TODO: use get_status_from_error */
+ g_signal_emit (book_view, signals[SEQUENCE_COMPLETE], 0,
+ E_BOOK_ERROR_CORBA_EXCEPTION);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("corba exception._major = %d\n", ev._major);
- }
+ g_error_free (error);
+ }
+ }
}
/**
@@ -238,154 +289,17 @@ e_book_view_start (EBookView *book_view)
void
e_book_view_stop (EBookView *book_view)
{
- CORBA_Environment ev;
-
- g_return_if_fail (book_view && E_IS_BOOK_VIEW (book_view));
-
- CORBA_exception_init (&ev);
-
- e_book_view_listener_stop (book_view->priv->listener);
-
- GNOME_Evolution_Addressbook_BookView_stop (book_view->priv->corba_book_view, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("corba exception._major = %d\n", ev._major);
- }
-}
-
-static void
-e_book_view_init (EBookView *book_view)
-{
- book_view->priv = g_new0 (EBookViewPrivate, 1);
- book_view->priv->book = NULL;
- book_view->priv->corba_book_view = CORBA_OBJECT_NIL;
- book_view->priv->listener = NULL;
- book_view->priv->response_id = 0;
-}
-
-static void
-e_book_view_dispose (GObject *object)
-{
- EBookView *book_view = E_BOOK_VIEW (object);
- CORBA_Environment ev;
-
- if (book_view->priv) {
- if (book_view->priv->book) {
- g_object_unref (book_view->priv->book);
- }
-
- if (book_view->priv->corba_book_view) {
- CORBA_exception_init (&ev);
-
- GNOME_Evolution_Addressbook_BookView_dispose (book_view->priv->corba_book_view, &ev);
-
- bonobo_object_release_unref (book_view->priv->corba_book_view, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("EBookView: Exception while releasing BookView\n");
- }
-
- CORBA_exception_free (&ev);
- }
+ GError *error = NULL;
- if (book_view->priv->listener) {
- if (book_view->priv->response_id)
- g_signal_handler_disconnect(book_view->priv->listener,
- book_view->priv->response_id);
- e_book_view_listener_stop (book_view->priv->listener);
- bonobo_object_unref (BONOBO_OBJECT(book_view->priv->listener));
- }
+ g_return_if_fail (E_IS_BOOK_VIEW (book_view));
- g_free (book_view->priv);
- book_view->priv = NULL;
- }
+ book_view->priv->running = FALSE;
- G_OBJECT_CLASS(parent_class)->dispose (object);
-}
-
-static void
-e_book_view_class_init (EBookViewClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- parent_class = g_type_class_ref (G_TYPE_OBJECT);
-
- e_book_view_signals [CONTACTS_CHANGED] =
- g_signal_new ("contacts_changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookViewClass, contacts_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
-
- e_book_view_signals [CONTACTS_ADDED] =
- g_signal_new ("contacts_added",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookViewClass, contacts_added),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
-
- e_book_view_signals [CONTACTS_REMOVED] =
- g_signal_new ("contacts_removed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookViewClass, contacts_removed),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
-
- e_book_view_signals [SEQUENCE_COMPLETE] =
- g_signal_new ("sequence_complete",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookViewClass, sequence_complete),
- NULL, NULL,
- g_cclosure_marshal_VOID__INT,
- G_TYPE_NONE, 1,
- G_TYPE_INT);
-
- e_book_view_signals [STATUS_MESSAGE] =
- g_signal_new ("status_message",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookViewClass, status_message),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1,
- G_TYPE_STRING);
-
- object_class->dispose = e_book_view_dispose;
-}
-
-/**
- * e_book_view_get_type:
- */
-GType
-e_book_view_get_type (void)
-{
- static GType type = 0;
-
- if (! type) {
- GTypeInfo info = {
- sizeof (EBookViewClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) e_book_view_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (EBookView),
- 0, /* n_preallocs */
- (GInstanceInitFunc) e_book_view_init
- };
-
- type = g_type_register_static (G_TYPE_OBJECT, "EBookView", &info, 0);
- }
-
- return type;
+ if (book_view->priv->view_proxy) {
+ org_gnome_evolution_dataserver_addressbook_BookView_stop (book_view->priv->view_proxy, &error);
+ if (error) {
+ g_warning ("Cannot stop book view: %s\n", error->message);
+ g_error_free (error);
+ }
+ }
}
diff --git a/addressbook/libebook/e-book-view.h b/addressbook/libebook/e-book-view.h
index 8a5321f..0c12741 100644
--- a/addressbook/libebook/e-book-view.h
+++ b/addressbook/libebook/e-book-view.h
@@ -1,11 +1,23 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * The Evolution addressbook client object.
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
*
- * Author:
- * Nat Friedman (nat 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.
*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Ross Burton <ross linux intel com>
*/
#ifndef __E_BOOK_VIEW_H__
diff --git a/addressbook/libebook/e-book.c b/addressbook/libebook/e-book.c
index e9b3b01..08eb5e8 100644
--- a/addressbook/libebook/e-book.c
+++ b/addressbook/libebook/e-book.c
@@ -1,81 +1,54 @@
/* -*- 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 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 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.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Ross Burton <ross linux intel com>
+ */
#include <config.h>
-
+#include <unistd.h>
#include <string.h>
-
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+#include <dbus/dbus-glib.h>
#include "e-book.h"
+#include "e-error.h"
+#include "e-contact.h"
#include "e-book-view-private.h"
-#include "e-vcard.h"
+#include "e-data-book-factory-bindings.h"
+#include "e-data-book-bindings.h"
+#include "libedata-book/e-data-book-types.h"
+#include "e-book-marshal.h"
-#include <bonobo-activation/bonobo-activation.h>
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib-lowlevel.h>
-#include <bonobo/bonobo-exception.h>
-#include <bonobo/bonobo-main.h>
-#include <gconf/gconf-client.h>
+#define E_DATA_BOOK_FACTORY_SERVICE_NAME "org.gnome.evolution.dataserver.AddressBook"
-#include <glib/gi18n-lib.h>
-#include "libedataserver/e-flag.h"
-#include "libedataserver/e-component-listener.h"
-
-#include "e-book-listener.h"
-
-#define d(x)
-
-GMainContext *_ebook_context;
-
-static GObjectClass *parent_class;
-
-#ifdef __PRETTY_FUNCTION__
-#define e_return_error_if_fail(expr,error_code,retval) 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__, \
- __PRETTY_FUNCTION__, \
- #expr); \
- g_set_error (error, E_BOOK_ERROR, (error_code), \
- "file %s: line %d (%s): assertion `%s' failed", \
- __FILE__, \
- __LINE__, \
- __PRETTY_FUNCTION__, \
- #expr); \
- return (retval); \
- }; }G_STMT_END
-#else
-#define e_return_error_if_fail(expr,error_code,retval) G_STMT_START{ \
- if G_LIKELY(expr) { } else \
- { \
- g_log (G_LOG_DOMAIN, \
- G_LOG_LEVEL_CRITICAL, \
- "file %s: line %d: assertion `%s' failed", \
- __FILE__, \
- __LINE__, \
- #expr); \
- g_set_error (error, E_BOOK_ERROR, (error_code), \
- "file %s: line %d: assertion `%s' failed", \
- __FILE__, \
- __LINE__, \
- #expr); \
- return (retval); \
- }; }G_STMT_END
-#endif
-
-/* XXX we need a better error message here */
-#define E_BOOK_CHECK_STATUS(status,error) G_STMT_START{ \
- if ((status) == E_BOOK_ERROR_OK) { \
- return TRUE; \
- } \
- else { \
- g_set_error ((error), E_BOOK_ERROR, (status), "EBookStatus returned %d", (status)); \
- return FALSE; \
- } }G_STMT_END
+static char** flatten_stringlist(GList *list);
+static GList *array_to_stringlist (char **list);
+static gboolean unwrap_gerror(GError *error, GError **client_error);
+static EBookStatus get_status_from_error (GError *error);
+
+G_DEFINE_TYPE(EBook, e_book, G_TYPE_OBJECT)
+#define E_BOOK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_BOOK, EBookPrivate))
enum {
- OPEN_PROGRESS,
WRITABLE_STATUS,
CONNECTION_STATUS,
AUTH_REQUIRED,
@@ -85,719 +58,610 @@ enum {
static guint e_book_signals [LAST_SIGNAL];
-typedef enum {
- STATE_WAITING,
- STATE_PROCESSING,
- STATE_CANCELLING
-} EBookOpState;
-
-typedef struct {
- gint32 opid;
- EBookOpState opstate;
- gint idle_id;
- gboolean synchronous;
- EFlag *flag;
- EBook *book;
- EBookStatus status;
- char *id;
- GList *list;
- EList *elist;
- EContact *contact;
-
- EBookView *view;
- EBookViewListener *listener;
-
- /* callbacks/closure for async calls */
- union {
- EBookIdCallback id;
- EBookCallback status;
- EBookContactCallback contact;
- EBookListCallback list;
- EBookBookViewCallback book_view;
- EBookEListCallback elist;
- } cb;
- gpointer closure;
-} EBookOp;
-
-typedef enum {
- E_BOOK_SOURCE_NOT_LOADED,
- E_BOOK_SOURCE_LOADING,
- E_BOOK_SOURCE_LOADED
-} EBookLoadState;
-
struct _EBookPrivate {
- /* cached capabilites */
- char *cap;
- gboolean cap_queried;
-
- /* cached writable status */
- gboolean writable;
- gboolean connected;
-
- EBookListener *listener;
- EComponentListener *comp_listener;
-
- GNOME_Evolution_Addressbook_Book corba_book;
-
- EBookLoadState load_state;
-
- GList *pending_idles;
- GHashTable *id_to_op;
- guint32 current_op_id;
-
- GMutex *mutex;
-
- /* Need to keep URI around, since the getter returns const */
- gchar *uri;
- ESource *source;
+ ESource *source;
+ char *uri;
+ DBusGProxy *proxy;
+ gboolean loaded;
+ gboolean writable;
+ gboolean connected;
+ char *cap;
+ gboolean cap_queried;
+};
- gulong listener_signal;
- gulong died_signal;
+static DBusGConnection *connection = NULL;
+static DBusGProxy *factory_proxy = NULL;
- gint writable_idle_id;
- gint connection_idle_id;
- gint auth_idle_id;
-};
+typedef struct {
+ EBook *book;
+ void *callback; /* TODO union */
+ gpointer closure;
+ gpointer data;
+} AsyncData;
-
-/* Error quark */
GQuark
e_book_error_quark (void)
{
static GQuark q = 0;
if (q == 0)
q = g_quark_from_static_string ("e-book-error-quark");
-
return q;
}
-
-
-/* EBookOp calls */
-
-static EBookOp*
-e_book_new_op (EBook *book, gboolean sync)
+/*
+ * Called when the addressbook server dies.
+ */
+static void
+proxy_destroyed (gpointer data, GObject *object)
{
- EBookOp *op = g_new0 (EBookOp, 1);
+ EBook *book = data;
- op->flag = e_flag_new ();
- op->opstate = STATE_WAITING;
+ g_assert (E_IS_BOOK (book));
- op->synchronous = sync;
- if (sync)
- op->opid = 0;
- else
- op->opid = book->priv->current_op_id++;
+ g_warning (G_STRLOC ": e-d-s proxy died");
- g_hash_table_insert (book->priv->id_to_op,
- &op->opid, op);
+ /* Ensure that everything relevant is NULL */
+ factory_proxy = NULL;
+ book->priv->proxy = NULL;
- return op;
+ g_signal_emit (G_OBJECT (book), e_book_signals [BACKEND_DIED], 0);
}
-static EBookOp*
-e_book_get_op (EBook *book, int opid)
+static void
+e_book_dispose (GObject *object)
{
- return (EBookOp*)g_hash_table_lookup (book->priv->id_to_op,
- &opid);
-}
+ EBook *book = E_BOOK (object);
-static EBookOp*
-e_book_get_current_sync_op (EBook *book)
-{
- return e_book_get_op (book, 0);
-}
+ book->priv->loaded = FALSE;
-static EBookOp *
-e_book_find_op (EBook *book, guint32 opid, const char *func_name)
-{
- EBookOp *op;
-
- op = e_book_get_op (book, opid);
-
- if (op == NULL) {
- g_warning ("%s: Cannot find operation", func_name);
- } else if (op->opstate != STATE_WAITING) {
- /* returns only operations, which are waiting */
- op = NULL;
- } else {
- /* set opstate to processing, thus it will not be canceled meanwhile */
- op->opstate = STATE_PROCESSING;
- }
+ if (book->priv->proxy) {
+ g_object_weak_unref (G_OBJECT (book->priv->proxy), proxy_destroyed, book);
+ org_gnome_evolution_dataserver_addressbook_Book_close (book->priv->proxy, NULL);
+ }
+ if (book->priv->source) {
+ g_object_unref (book->priv->source);
+ book->priv->source = NULL;
+ }
+ if (book->priv->proxy) {
+ g_object_unref (book->priv->proxy);
+ book->priv->proxy = NULL;
+ }
- return op;
+ if (G_OBJECT_CLASS (e_book_parent_class)->dispose)
+ G_OBJECT_CLASS (e_book_parent_class)->dispose (object);
}
static void
-e_book_op_free (EBookOp *op)
+e_book_finalize (GObject *object)
{
- e_flag_free (op->flag);
- g_free (op);
+ EBook *book = E_BOOK (object);
+
+ if (book->priv->uri)
+ g_free (book->priv->uri);
+
+ if (book->priv->cap)
+ g_free (book->priv->cap);
+
+ if (G_OBJECT_CLASS (e_book_parent_class)->finalize)
+ G_OBJECT_CLASS (e_book_parent_class)->finalize (object);
}
static void
-e_book_op_remove (EBook *book,
- EBookOp *op)
+e_book_class_init (EBookClass *e_book_class)
{
- g_hash_table_remove (book->priv->id_to_op,
- &op->opid);
-
- if (op->idle_id && g_list_find (book->priv->pending_idles, GINT_TO_POINTER (op->idle_id))) {
- book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
- g_source_remove (op->idle_id);
- op->idle_id = 0;
- }
+ GObjectClass *gobject_class = G_OBJECT_CLASS (e_book_class);
+
+ e_book_signals [WRITABLE_STATUS] =
+ g_signal_new ("writable_status",
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookClass, writable_status),
+ NULL, NULL,
+ e_book_marshal_NONE__BOOL,
+ G_TYPE_NONE, 1,
+ G_TYPE_BOOLEAN);
+
+ e_book_signals [CONNECTION_STATUS] =
+ g_signal_new ("connection_status",
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookClass, connection_status),
+ NULL, NULL,
+ e_book_marshal_NONE__BOOL,
+ G_TYPE_NONE, 1,
+ G_TYPE_BOOLEAN);
+
+ e_book_signals [AUTH_REQUIRED] =
+ g_signal_new ("auth_required",
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookClass, auth_required),
+ NULL, NULL,
+ e_book_marshal_NONE__NONE,
+ G_TYPE_NONE, 0);
+
+ e_book_signals [BACKEND_DIED] =
+ g_signal_new ("backend_died",
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EBookClass, backend_died),
+ NULL, NULL,
+ e_book_marshal_NONE__NONE,
+ G_TYPE_NONE, 0);
+
+ gobject_class->dispose = e_book_dispose;
+ gobject_class->finalize = e_book_finalize;
+
+ g_type_class_add_private (e_book_class, sizeof (EBookPrivate));
}
static void
-e_book_clear_op (EBook *book,
- EBookOp *op)
+e_book_init (EBook *book)
{
- e_book_op_remove (book, op);
- e_flag_clear (op->flag);
- e_book_op_free (op);
+ EBookPrivate *priv = E_BOOK_GET_PRIVATE (book);
+ priv->source = NULL;
+ priv->uri = NULL;
+ priv->proxy = NULL;
+ priv->loaded = FALSE;
+ priv->writable = FALSE;
+ priv->connected = FALSE;
+ priv->cap = NULL;
+ priv->cap_queried = FALSE;
+ book->priv = priv;
}
-
+/* one-time start up for libebook */
static gboolean
-do_add_contact (gboolean sync,
- EBook *book,
- EContact *contact,
- GError **error, /* for sync case */
- EBookIdCallback cb, /* for async case */
- gpointer closure)
-{
- EBookOp *our_op;
- EBookStatus status;
- CORBA_Environment ev;
- char *vcard_str;
-
- d(printf ("do_add_contact\n"));
-
- g_mutex_lock (book->priv->mutex);
-
- if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
- g_mutex_unlock (book->priv->mutex);
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
- /* translators: the placeholders will be filled by
- * function names, e.g.
- * "e_book_add_contact" on book before
- * "e_book_open */
- _("\"%s\" on book before \"%s\""),
- "e_book_add_contact", "e_book_open");
- }
- else {
- g_warning (_("\"%s\" on book before \"%s\""),
- "e_book_add_contact", "e_book_open");
- }
- return FALSE;
- }
-
- if (sync && e_book_get_current_sync_op (book) != NULL) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
- _("book busy"));
- return FALSE;
- }
-
- our_op = e_book_new_op (book, sync);
-
- g_mutex_unlock (book->priv->mutex);
-
- vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
-
- CORBA_exception_init (&ev);
-
- our_op->cb.id = cb;
- our_op->closure = closure;
-
- /* will eventually end up calling e_book_response_add_contact */
- GNOME_Evolution_Addressbook_Book_addContact (book->priv->corba_book, our_op->opid,
- (const GNOME_Evolution_Addressbook_VCard) vcard_str, &ev);
-
- g_free (vcard_str);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
+e_book_activate(GError **error)
+{
+ DBusError derror;
+
+ if (G_LIKELY (factory_proxy)) {
+ return TRUE;
+ }
+
+ if (!connection) {
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, error);
+ if (!connection)
+ return FALSE;
+ }
+
+ dbus_error_init (&derror);
+ if (!dbus_bus_start_service_by_name (dbus_g_connection_get_connection (connection),
+ E_DATA_BOOK_FACTORY_SERVICE_NAME,
+ 0, NULL, &derror)) {
+ dbus_set_g_error (error, &derror);
+ dbus_error_free (&derror);
+ return FALSE;
+ }
+
+ if (!factory_proxy) {
+ factory_proxy = dbus_g_proxy_new_for_name_owner (connection,
+ E_DATA_BOOK_FACTORY_SERVICE_NAME,
+ "/org/gnome/evolution/dataserver/addressbook/BookFactory",
+ "org.gnome.evolution.dataserver.addressbook.BookFactory",
+ error);
+ if (!factory_proxy) {
+ return FALSE;
+ }
+ g_object_add_weak_pointer (G_OBJECT (factory_proxy), (gpointer)&factory_proxy);
+ }
+
+ return TRUE;
+}
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
+static void
+writable_cb (DBusGProxy *proxy, gboolean writable, EBook *book)
+{
+ g_return_if_fail (E_IS_BOOK (book));
- CORBA_exception_free (&ev);
+ book->priv->writable = writable;
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::addContact");
- }
- else {
- g_warning (_("CORBA exception making \"%s\" call"),
- "Book::addContact");
- }
- return FALSE;
- }
+ g_signal_emit (G_OBJECT (book), e_book_signals [WRITABLE_STATUS], 0, writable);
+}
- CORBA_exception_free (&ev);
+static void
+connection_cb (DBusGProxy *proxy, gboolean connected, EBook *book)
+{
+ g_return_if_fail (E_IS_BOOK (book));
- if (sync) {
- /* wait for something to happen (both cancellation and a
- successful response will notity us via our cv */
- e_flag_wait (our_op->flag);
+ book->priv->connected = connected;
- status = our_op->status;
- e_contact_set (contact, E_CONTACT_UID, our_op->id);
- g_free (our_op->id);
+ g_signal_emit (G_OBJECT (book), e_book_signals [CONNECTION_STATUS], 0, connected);
+}
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
+static void
+auth_required_cb (DBusGProxy *proxy, EBook *book)
+{
+ g_return_if_fail (E_IS_BOOK (book));
- E_BOOK_CHECK_STATUS (status, error);
- }
- else {
- return TRUE;
- }
+ g_signal_emit (G_OBJECT (book), e_book_signals [AUTH_REQUIRED], 0);
}
/**
- * e_book_add_contact:
- * @book: an #EBook
- * @contact: an #EContact
- * @error: a #GError to set on failure
+ * e_book_get_addressbooks:
+ * @addressbook_sources: A pointer to a ESourceList* to set
+ * @error: A pointer to a GError* to set on error
*
- * Adds @contact to @book.
+ * Populate *addressbook_sources with the list of all sources which have been
+ * added to Evolution.
*
- * Return value: %TRUE if successful, %FALSE otherwise.
- **/
+ * Return value: %TRUE if @addressbook_sources was set, otherwise %FALSE.
+ */
gboolean
-e_book_add_contact (EBook *book,
- EContact *contact,
- GError **error)
+e_book_get_addressbooks (ESourceList **addressbook_sources, GError **error)
{
- d(printf ("e_book_add_contact\n"));
+ GConfClient *gconf;
+
+ e_return_error_if_fail (addressbook_sources, E_BOOK_ERROR_INVALID_ARG);
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (contact && E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG, FALSE);
+ gconf = gconf_client_get_default();
+ *addressbook_sources = e_source_list_new_for_gconf (gconf, "/apps/evolution/addressbook/sources");
+ g_object_unref (gconf);
- return do_add_contact (TRUE,
- book, contact, error,
- NULL, NULL);
+ return TRUE;
}
/**
- * e_book_async_add_contact:
- * @book: an #EBook
- * @contact: an #EContact
- * @cb: function to call when the operation finishes
- * @closure: data to pass to callback function
+ * e_book_new:
+ * @source: An #ESource pointer
+ * @error: A #GError pointer
*
- * Adds @contact to @book without blocking.
+ * Creates a new #EBook corresponding to the given source. There are
+ * only two operations that are valid on this book at this point:
+ * e_book_open(), and e_book_remove().
*
- * Return value: %TRUE if the operation was started, %FALSE otherwise.
- **/
-gboolean
-e_book_async_add_contact (EBook *book,
- EContact *contact,
- EBookIdCallback cb,
- gpointer closure)
+ * Return value: a new but unopened #EBook.
+ */
+EBook*
+e_book_new (ESource *source, GError **error)
{
- d(printf ("e_book_async_add_contact\n"));
-
- g_return_val_if_fail (book && E_IS_BOOK (book), FALSE);
- g_return_val_if_fail (contact && E_IS_CONTACT (contact), FALSE);
-
- return !do_add_contact (FALSE,
- book, contact, NULL,
- cb, closure);
+ GError *err = NULL;
+ EBook *book;
+ char *path;
+
+ e_return_error_if_fail (E_IS_SOURCE (source), E_BOOK_ERROR_INVALID_ARG);
+
+ if (!e_book_activate (&err)) {
+ g_warning (G_STRLOC ": cannot activate book: %s\n", err->message);
+ g_propagate_error (error, err);
+ return NULL;
+ }
+
+ book = g_object_new (E_TYPE_BOOK, NULL);
+
+ book->priv->source = g_object_ref (source);
+ book->priv->uri = e_source_get_uri (source);
+
+ if (!org_gnome_evolution_dataserver_addressbook_BookFactory_get_book (factory_proxy, book->priv->uri, &path, &err)) {
+ g_warning (G_STRLOC ": cannot get book from factory: %s", err ? err->message : "[no error]");
+ g_propagate_error (error, err);
+ g_object_unref (book);
+ return NULL;
+ }
+
+ book->priv->proxy = dbus_g_proxy_new_for_name_owner (connection,
+ E_DATA_BOOK_FACTORY_SERVICE_NAME, path,
+ "org.gnome.evolution.dataserver.addressbook.Book",
+ &err);
+ if (!book->priv->proxy) {
+ g_warning (G_STRLOC ": cannot get proxy for book %s: %s", path, err->message);
+ g_propagate_error (error, err);
+ g_free (path);
+ g_object_unref (book);
+ return NULL;
+ }
+ g_free (path);
+
+ g_object_weak_ref (G_OBJECT (book->priv->proxy), proxy_destroyed, book);
+
+ dbus_g_proxy_add_signal (book->priv->proxy, "writable", G_TYPE_BOOLEAN, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (book->priv->proxy, "writable", G_CALLBACK (writable_cb), book, NULL);
+ dbus_g_proxy_add_signal (book->priv->proxy, "connection", G_TYPE_BOOLEAN, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (book->priv->proxy, "connection", G_CALLBACK (connection_cb), book, NULL);
+ dbus_g_proxy_add_signal (book->priv->proxy, "auth_required", G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (book->priv->proxy, "auth_required", G_CALLBACK (auth_required_cb), book, NULL);
+
+ return book;
}
-static gboolean
-emit_async_add_contact_response (gpointer data)
+/**
+ * e_book_new_from_uri:
+ * @uri: the URI to load
+ * @error: A #GError pointer
+ *
+ * Creates a new #EBook corresponding to the given uri. See the
+ * documentation for e_book_new for further information.
+ *
+ * Return value: a new but unopened #EBook.
+ */
+EBook*
+e_book_new_from_uri (const char *uri, GError **error)
{
- EBookOp *op = data;
- EBook *book = op->book;
-
- if (op->cb.id)
- op->cb.id (book, op->status, op->id, op->closure);
-
- g_mutex_lock (book->priv->mutex);
-
- g_free (op->id);
-
- book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
-
- e_book_clear_op (book, op);
-
- g_mutex_unlock (book->priv->mutex);
- g_object_unref (book);
-
- return FALSE;
+ ESource *source;
+ EBook *book;
+
+ e_return_error_if_fail (uri, E_BOOK_ERROR_INVALID_ARG);
+
+ source = e_source_new_with_absolute_uri ("", uri);
+
+ book = e_book_new (source, error);
+
+ g_object_unref (source);
+
+ return book;
}
-static void
-e_book_response_add_contact (EBook *book,
- guint32 opid,
- EBookStatus status,
- char *id)
+/**
+ * e_book_new_system_addressbook:
+ * @uri: the URI to load
+ * @error: A #GError pointer
+ *
+ * Creates a new #EBook corresponding to the user's system
+ * addressbook. See the documentation for e_book_new for further
+ * information.
+ *
+ * Return value: a new but unopened #EBook.
+ */
+EBook*
+e_book_new_system_addressbook (GError **error)
{
- EBookOp *op;
+ ESourceList *sources;
+ GSList *g;
+ ESource *system_source = NULL;
+ EBook *book = NULL;
- d(printf ("e_book_response_add_contact\n"));
+ if (!e_book_get_addressbooks (&sources, error)) {
+ return FALSE;
+ }
- g_mutex_lock (book->priv->mutex);
+ 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);
- op = e_book_find_op (book, opid, G_STRFUNC);
+ if (e_source_get_property (source, "system")) {
+ system_source = source;
+ break;
+ }
+ }
- if (op == NULL) {
- g_mutex_unlock (book->priv->mutex);
- return;
+ if (system_source)
+ break;
}
- op->id = g_strdup (id);
- op->status = status;
-
- if (op->synchronous)
- e_flag_set (op->flag);
+ if (system_source) {
+ book = e_book_new (system_source, error);
+ }
else {
- op->book = g_object_ref (book);
+ char *filename;
+ char *uri;
+
+ filename = g_build_filename (g_get_home_dir(),
+ ".evolution/addressbook/local/system",
+ NULL);
+ uri = g_strdup_printf ("file://%s", filename);
- op->idle_id = g_idle_add (emit_async_add_contact_response, op);
- book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
+ g_free (filename);
+
+ book = e_book_new_from_uri (uri, error);
+
+ g_free (uri);
}
- g_mutex_unlock (book->priv->mutex);
-}
+ g_object_unref (sources);
-
+ return book;
+}
-static gboolean
-do_commit_contact (gboolean sync,
- EBook *book,
- EContact *contact,
- GError **error,
- EBookCallback cb,
- gpointer closure)
+/**
+ * e_book_new_default_addressbook:
+ * @uri: the URI to load
+ * @error: A #GError pointer
+ *
+ * Creates a new #EBook corresponding to the user's default
+ * addressbook. See the documentation for e_book_new for further
+ * information.
+ *
+ * Return value: a new but unopened #EBook.
+ */
+EBook*
+e_book_new_default_addressbook (GError **error)
{
- EBookOp *our_op;
- EBookStatus status;
- CORBA_Environment ev;
- char *vcard_str;
-
- g_mutex_lock (book->priv->mutex);
-
- if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
- g_mutex_unlock (book->priv->mutex);
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
- _("\"%s\" on book before \"%s\""),
- "e_book_commit_contact", "e_book_open");
- }
- else {
- g_warning (_("\"%s\" on book before \"%s\""),
- "e_book_commit_contact", "e_book_open");
- }
- return FALSE;
- }
+ ESourceList *sources;
+ GSList *g;
+ ESource *default_source = NULL;
+ EBook *book;
- if (sync && e_book_get_current_sync_op (book) != NULL) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
- _("book busy"));
+ if (!e_book_get_addressbooks (&sources, error)) {
return FALSE;
}
- vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
-
- our_op = e_book_new_op (book, sync);
-
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_init (&ev);
-
- our_op->cb.status = cb;
- our_op->closure = closure;
-
- /* will eventually end up calling _e_book_response_generic */
- GNOME_Evolution_Addressbook_Book_modifyContact (book->priv->corba_book, our_op->opid,
- (const GNOME_Evolution_Addressbook_VCard) vcard_str, &ev);
-
- g_free (vcard_str);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_free (&ev);
+ 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 (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::modifyContact");
- }
- else {
- g_warning (_("CORBA exception making \"%s\" call"),
- "Book::modifyContact");
+ if (e_source_get_property (source, "default")) {
+ default_source = source;
+ break;
+ }
}
- return FALSE;
+
+ if (default_source)
+ break;
}
- CORBA_exception_free (&ev);
+ if (default_source)
+ book = e_book_new (default_source, error);
+ else
+ book = e_book_new_system_addressbook (error);
- if (sync) {
- /* wait for something to happen (both cancellation and a
- successful response will notity us via our cv */
- e_flag_wait (our_op->flag);
+ g_object_unref (sources);
- status = our_op->status;
- g_free (our_op->id);
+ return book;
+}
- /* remove the op from the book's hash of operations */
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
+/**
+ * e_book_get_source:
+ * @book: an #EBook
+ *
+ * Get the #ESource that this book has loaded.
+ *
+ * Return value: The source.
+ */
+ESource*
+e_book_get_source (EBook *book)
+{
+ g_return_val_if_fail (E_IS_BOOK (book), NULL);
- E_BOOK_CHECK_STATUS (status, error);
- }
- else {
- return TRUE;
- }
+ return book->priv->source;
}
-
/**
- * e_book_commit_contact:
+ * e_book_open:
* @book: an #EBook
- * @contact: an #EContact
+ * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
* @error: a #GError to set on failure
*
- * Applies the changes made to @contact to the stored version in
- * @book.
+ * Opens the addressbook, making it ready for queries and other operations.
*
- * Return value: %TRUE if successful, %FALSE otherwise
- **/
+ * Return value: %TRUE if the book was successfully opened, %FALSE otherwise.
+ */
gboolean
-e_book_commit_contact (EBook *book,
- EContact *contact,
- GError **error)
+e_book_open (EBook *book, gboolean only_if_exists, GError **error)
+{
+ GError *err = NULL;
+ EBookStatus status;
+
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+ if (!org_gnome_evolution_dataserver_addressbook_Book_open (book->priv->proxy, only_if_exists, &err)) {
+ g_propagate_error (error, err);
+ return FALSE;
+ }
+
+ status = get_status_from_error (err);
+
+ if (status == E_BOOK_ERROR_OK) {
+ book->priv->loaded = TRUE;
+ return TRUE;
+ } else {
+ g_propagate_error (error, err);
+ return FALSE;
+ }
+}
+
+static void
+open_reply(DBusGProxy *proxy, GError *error, gpointer user_data)
{
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (contact && E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG, FALSE);
+ AsyncData *data = user_data;
+ EBookCallback cb = data->callback;
+ EDataBookStatus status;
- return do_commit_contact (TRUE,
- book, contact, error,
- NULL, NULL);
+ status = get_status_from_error (error);
+ data->book->priv->loaded = (status == E_BOOK_ERROR_OK);
+
+ if (cb)
+ cb (data->book, status, data->closure);
+
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
/**
- * e_book_async_commit_contact:
+ * e_book_async_open:
* @book: an #EBook
- * @contact: an #EContact
- * @cb: function to call when the operation finishes
+ * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
+ * @open_response: a function to call when the operation finishes
* @closure: data to pass to callback function
*
- * Applies the changes made to @contact to the stored version in
- * @book without blocking.
+ * Opens the addressbook, making it ready for queries and other operations.
+ * This function does not block.
*
- * Return value: %TRUE if the operation was started, %FALSE otherwise.
+ * Return value: %FALSE if successful, %TRUE otherwise.
**/
guint
-e_book_async_commit_contact (EBook *book,
- EContact *contact,
- EBookCallback cb,
- gpointer closure)
-{
- return !do_commit_contact (FALSE,
- book, contact, NULL,
- cb, closure);
-}
-
-static gboolean
-do_get_required_fields (gboolean sync,
- EBook *book,
- GList **fields,
- GError **error,
- EBookEListCallback cb,
- gpointer closure)
+e_book_async_open (EBook *book, gboolean only_if_exists, EBookCallback cb, gpointer closure)
{
- EBookOp *our_op;
- EBookStatus status;
- CORBA_Environment ev;
-
- g_mutex_lock (book->priv->mutex);
-
- if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
- g_mutex_unlock (book->priv->mutex);
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
- _("\"%s\" on book before \"%s\""),
- "e_book_get_required_fields", "e_book_open");
- }
- else {
- g_warning (_("\"%s\" on book before \"%s\""),
- "e_book_get_required_fields", "e_book_open");
- }
- return FALSE;
- }
-
- if (sync && e_book_get_current_sync_op (book) != NULL) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
- _("book busy"));
- return FALSE;
- }
-
- our_op = e_book_new_op (book, sync);
-
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_init (&ev);
-
- our_op->cb.elist = cb;
- our_op->closure = closure;
-
- /* will eventually end up calling
- _e_book_response_get_supported_fields */
- GNOME_Evolution_Addressbook_Book_getRequiredFields(book->priv->corba_book, our_op->opid, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_free (&ev);
-
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::getRequiredFields");
- }
- else {
- g_warning (_("CORBA exception making \"%s\" call"),
- "Book::getRequiredFields");
- }
-
- return FALSE;
- }
-
-
- CORBA_exception_free (&ev);
-
- if (sync) {
- /* wait for something to happen (both cancellation and a
- successful response will notify us via our cv */
- e_flag_wait (our_op->flag);
+ AsyncData *data;
- status = our_op->status;
- *fields = our_op->list;
+ e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
- E_BOOK_CHECK_STATUS (status, error);
- }
- else {
- return TRUE;
- }
+ org_gnome_evolution_dataserver_addressbook_Book_open_async (book->priv->proxy, only_if_exists, open_reply, data);
+ return 0;
}
-static gboolean
-do_get_supported_fields (gboolean sync,
- EBook *book,
- GList **fields,
- GError **error,
- EBookEListCallback cb,
- gpointer closure)
+/**
+ * e_book_remove:
+ * @book: an #EBook
+ * @error: a #GError to set on failure
+ *
+ * Removes the backing data for this #EBook. For example, with the file backend this
+ * deletes the database file. You cannot get it back!
+ *
+ * Return value: %TRUE on success, %FALSE on failure.
+ */
+gboolean
+e_book_remove (EBook *book, GError **error)
{
- EBookOp *our_op;
- EBookStatus status;
- CORBA_Environment ev;
-
- g_mutex_lock (book->priv->mutex);
-
- if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
- g_mutex_unlock (book->priv->mutex);
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
- _("\"%s\" on book before \"%s\""),
- "e_book_get_supported_fields", "e_book_open");
- }
- else {
- g_warning (_("\"%s\" on book before \"%s\""),
- "e_book_get_supported_fields", "e_book_open");
- }
- return FALSE;
- }
-
- if (sync && e_book_get_current_sync_op (book) != NULL) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
- _("book busy"));
- return FALSE;
- }
-
- our_op = e_book_new_op (book, sync);
-
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_init (&ev);
-
- our_op->cb.elist = cb;
- our_op->closure = closure;
+ GError *err = NULL;
- /* will eventually end up calling
- _e_book_response_get_supported_fields */
- GNOME_Evolution_Addressbook_Book_getSupportedFields(book->priv->corba_book, our_op->opid, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_free (&ev);
-
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::getSupportedFields");
- }
- else {
- g_warning (_("CORBA exception making \"%s\" call"),
- "Book::getSupportedFields");
- }
-
- return FALSE;
- }
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+ org_gnome_evolution_dataserver_addressbook_Book_remove (book->priv->proxy, &err);
+ return unwrap_gerror (err, error);
+}
+static void
+remove_reply(DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+ AsyncData *data = user_data;
+ EBookCallback cb = data->callback;
+ if (cb)
+ cb (data->book, get_status_from_error (error), data->closure);
- CORBA_exception_free (&ev);
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
+}
- if (sync) {
- /* wait for something to happen (both cancellation and a
- successful response will notify us via our cv */
- e_flag_wait (our_op->flag);
+/**
+ * e_book_async_remove:
+ * @book: an #EBook
+ * @cb: a function to call when the operation finishes
+ * @closure: data to pass to callback function
+ *
+ * Remove the backing data for this #EBook. For example, with the file backend this
+ * deletes the database file. You cannot get it back!
+ *
+ * Return value: %FALSE if successful, %TRUE otherwise.
+ **/
+guint
+e_book_async_remove (EBook *book, EBookCallback cb, gpointer closure)
+{
+ AsyncData *data;
- status = our_op->status;
- *fields = our_op->list;
+ e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
- E_BOOK_CHECK_STATUS (status, error);
- }
- else {
- return TRUE;
- }
+ org_gnome_evolution_dataserver_addressbook_Book_remove_async (book->priv->proxy, remove_reply, data);
+ return 0;
}
/**
@@ -814,16 +678,44 @@ do_get_supported_fields (gboolean sync,
* Return value: %TRUE if successful, %FALSE otherwise.
**/
gboolean
-e_book_get_required_fields (EBook *book,
- GList **fields,
- GError **error)
+e_book_get_required_fields (EBook *book, GList **fields, GError **error)
{
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (fields, E_BOOK_ERROR_INVALID_ARG, FALSE);
+ GError *err = NULL;
+ char **list = NULL;
+
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- return do_get_required_fields (TRUE,
- book, fields, error,
- NULL, NULL);
+ org_gnome_evolution_dataserver_addressbook_Book_get_required_fields (book->priv->proxy, &list, &err);
+ if (list) {
+ *fields = array_to_stringlist (list);
+ return TRUE;
+ } else {
+ return unwrap_gerror (err, error);
+ }
+}
+
+static void
+get_required_fields_reply(DBusGProxy *proxy, char **fields, GError *error, gpointer user_data)
+{
+ AsyncData *data = user_data;
+ EBookEListCallback cb = data->callback;
+ char **i = fields;
+ EList *efields = e_list_new (NULL,
+ (EListFreeFunc) g_free,
+ NULL);
+
+ while (*i != NULL) {
+ e_list_append (efields, (*i++));
+ }
+
+ if (cb)
+ cb (data->book, get_status_from_error (error), efields, data->closure);
+
+ g_object_unref (efields);
+ g_free (fields);
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
/**
@@ -838,15 +730,20 @@ e_book_get_required_fields (EBook *book,
* Return value: %TRUE if the operation was started, %FALSE otherwise.
**/
guint
-e_book_async_get_required_fields (EBook *book,
- EBookEListCallback cb,
- gpointer closure)
+e_book_async_get_required_fields (EBook *book, EBookEListCallback cb, gpointer closure)
{
- g_return_val_if_fail (E_IS_BOOK (book), FALSE);
+ AsyncData *data;
- return !do_get_required_fields (FALSE,
- book, NULL, NULL,
- cb, closure);
+ e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
+
+ org_gnome_evolution_dataserver_addressbook_Book_get_required_fields_async (book->priv->proxy, get_required_fields_reply, data);
+ return 0;
}
/**
@@ -863,16 +760,43 @@ e_book_async_get_required_fields (EBook *book,
* Return value: %TRUE if successful, %FALSE otherwise
**/
gboolean
-e_book_get_supported_fields (EBook *book,
- GList **fields,
- GError **error)
+e_book_get_supported_fields (EBook *book, GList **fields, GError **error)
+{
+ GError *err = NULL;
+ char **list = NULL;
+
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+ org_gnome_evolution_dataserver_addressbook_Book_get_supported_fields (book->priv->proxy, &list, &err);
+ if (list) {
+ *fields = array_to_stringlist (list);
+ return TRUE;
+ } else {
+ return unwrap_gerror (err, error);
+ }
+}
+
+static void
+get_supported_fields_reply(DBusGProxy *proxy, char **fields, GError *error, gpointer user_data)
{
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (fields, E_BOOK_ERROR_INVALID_ARG, FALSE);
+ AsyncData *data = user_data;
+ EBookEListCallback cb = data->callback;
+ char **i = fields;
+ EList *efields = e_list_new (NULL, (EListFreeFunc) g_free, NULL);
+
+ while (*i != NULL) {
+ e_list_append (efields, (*i++));
+ }
+
+ if (cb)
+ cb (data->book, get_status_from_error (error), efields, data->closure);
- return do_get_supported_fields (TRUE,
- book, fields, error,
- NULL, NULL);
+ g_object_unref (efields);
+ g_free (fields);
+
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
/**
@@ -888,213 +812,20 @@ e_book_get_supported_fields (EBook *book,
* Return value: %TRUE if successful, %FALSE otherwise.
**/
guint
-e_book_async_get_supported_fields (EBook *book,
- EBookEListCallback cb,
- gpointer closure)
-{
- g_return_val_if_fail (E_IS_BOOK (book), FALSE);
-
- return !do_get_supported_fields (FALSE,
- book, NULL, NULL,
- cb, closure);
-}
-
-static gboolean
-emit_async_elist_response (gpointer data)
-{
- EBookOp *op = data;
- EBook *book = op->book;
-
- if (op->cb.elist)
- op->cb.elist (book, op->status, op->elist, op->closure);
-
- g_mutex_lock (book->priv->mutex);
-
- g_object_unref (op->elist);
-
- book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
-
- e_book_clear_op (book, op);
-
- g_mutex_unlock (book->priv->mutex);
- g_object_unref (book);
-
- return FALSE;
-}
-
-static void
-e_book_response_get_required_fields (EBook *book,
- guint32 opid,
- EBookStatus status,
- GList *fields)
-
-{
- EBookOp *op;
-
- g_mutex_lock (book->priv->mutex);
-
- op = e_book_find_op (book, opid, G_STRFUNC);
-
- if (op == NULL) {
- g_mutex_unlock (book->priv->mutex);
- return;
- }
-
- op->status = status;
- if (op->synchronous) {
- op->list = fields;
- e_flag_set (op->flag);
- } else {
- GList *l;
- EList *efields = e_list_new ((EListCopyFunc) g_strdup,
- (EListFreeFunc) g_free,
- NULL);
-
- for (l = fields; l; l = l->next)
- e_list_append (efields, l->data);
-
- op->book = g_object_ref (book);
- op->elist = efields;
-
- op->idle_id = g_idle_add (emit_async_elist_response, op);
- book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
- }
-
- g_mutex_unlock (book->priv->mutex);
-}
-
-static void
-e_book_response_get_supported_fields (EBook *book,
- guint32 opid,
- EBookStatus status,
- GList *fields)
-{
- EBookOp *op;
-
- g_mutex_lock (book->priv->mutex);
-
- op = e_book_find_op (book, opid, G_STRFUNC);
-
- if (op == NULL) {
- g_mutex_unlock (book->priv->mutex);
- return;
- }
-
- op->status = status;
- if (op->synchronous) {
- op->list = fields;
- e_flag_set (op->flag);
- } else {
- GList *l;
- EList *efields = e_list_new ((EListCopyFunc) g_strdup,
- (EListFreeFunc) g_free,
- NULL);
-
- for (l = fields; l; l = l->next)
- e_list_append (efields, l->data);
-
- op->book = g_object_ref (book);
- op->elist = efields;
-
- op->idle_id = g_idle_add (emit_async_elist_response, op);
- book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
- }
-
- g_mutex_unlock (book->priv->mutex);
-}
-
-
-static gboolean
-do_get_supported_auth_methods (gboolean sync,
- EBook *book,
- GList **auth_methods,
- GError **error,
- EBookEListCallback cb,
- gpointer closure)
+e_book_async_get_supported_fields (EBook *book, EBookEListCallback cb, gpointer closure)
{
- EBookOp *our_op;
- EBookStatus status;
- CORBA_Environment ev;
-
- g_mutex_lock (book->priv->mutex);
-
- if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
- g_mutex_unlock (book->priv->mutex);
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
- _("\"%s\" on book before \"%s\""),
- "e_book_get_supported_auth_methods",
- "e_book_open");
- }
- else {
- g_warning (_("\"%s\" on book before \"%s\""),
- "e_book_get_supported_auth_methods",
- "e_book_open");
- }
- return FALSE;
- }
-
- if (sync && e_book_get_current_sync_op (book) != NULL) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
- _("book busy"));
- return FALSE;
- }
-
- our_op = e_book_new_op (book, sync);
-
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_init (&ev);
+ AsyncData *data;
- our_op->cb.elist = cb;
- our_op->closure = closure;
+ e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- /* will eventually end up calling
- e_book_response_get_supported_fields */
- GNOME_Evolution_Addressbook_Book_getSupportedAuthMethods(book->priv->corba_book, our_op->opid, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_free (&ev);
-
- if (error)
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::getSupportedAuthMethods");
- else
- g_warning (_("CORBA exception making \"%s\" call"),
- "Book::getSupportedAuthMethods");
- return FALSE;
- }
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
-
- CORBA_exception_free (&ev);
-
- if (sync) {
- /* wait for something to happen (both cancellation and a
- successful response will notity us via our cv */
- e_flag_wait (our_op->flag);
-
- status = our_op->status;
- *auth_methods = our_op->list;
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- E_BOOK_CHECK_STATUS (status, error);
- }
- else {
- return TRUE;
- }
+ org_gnome_evolution_dataserver_addressbook_Book_get_supported_fields_async (book->priv->proxy, get_supported_fields_reply, data);
+ return 0;
}
/**
@@ -1110,16 +841,45 @@ do_get_supported_auth_methods (gboolean sync,
* Return value: %TRUE if successful, %FALSE otherwise
**/
gboolean
-e_book_get_supported_auth_methods (EBook *book,
- GList **auth_methods,
- GError **error)
+e_book_get_supported_auth_methods (EBook *book, GList **auth_methods, GError **error)
+{
+ GError *err = NULL;
+ char **list = NULL;
+
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+ org_gnome_evolution_dataserver_addressbook_Book_get_supported_auth_methods (book->priv->proxy, &list, &err);
+ if (list) {
+ *auth_methods = array_to_stringlist (list);
+ return TRUE;
+ } else {
+ return unwrap_gerror (err, error);
+ }
+}
+
+static void
+get_supported_auth_methods_reply(DBusGProxy *proxy, char **methods, GError *error, gpointer user_data)
{
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (auth_methods, E_BOOK_ERROR_INVALID_ARG, FALSE);
+ AsyncData *data = user_data;
+ EBookEListCallback cb = data->callback;
+ char **i = methods;
+ EList *emethods = e_list_new (NULL,
+ (EListFreeFunc) g_free,
+ NULL);
+
+ while (*i != NULL) {
+ e_list_append (emethods, (*i++));
+ }
+
+ if (cb)
+ cb (data->book, get_status_from_error (error), emethods, data->closure);
- return do_get_supported_auth_methods (TRUE,
- book, auth_methods, error,
- NULL, NULL);
+ g_object_unref (emethods);
+ g_free (methods);
+
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
/**
@@ -1132,153 +892,21 @@ e_book_get_supported_auth_methods (EBook *book,
* This function does not block.
*
* Return value: %TRUE if successful, %FALSE otherwise.
- **/
-guint
-e_book_async_get_supported_auth_methods (EBook *book,
- EBookEListCallback cb,
- gpointer closure)
+ **/guint
+e_book_async_get_supported_auth_methods (EBook *book, EBookEListCallback cb, gpointer closure)
{
- g_return_val_if_fail (book && E_IS_BOOK (book), TRUE);
+ AsyncData *data;
- return !do_get_supported_auth_methods (FALSE,
- book, NULL, NULL,
- cb, closure);
-}
+ e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
-static void
-e_book_response_get_supported_auth_methods (EBook *book,
- guint32 opid,
- EBookStatus status,
- GList *auth_methods)
-{
- EBookOp *op;
-
- g_mutex_lock (book->priv->mutex);
-
- op = e_book_find_op (book, opid, G_STRFUNC);
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
- if (op == NULL) {
- g_mutex_unlock (book->priv->mutex);
- return;
- }
-
- op->status = status;
- if (op->synchronous) {
- op->list = auth_methods;
- e_flag_set (op->flag);
- } else {
- GList *l;
- EList *emethods = e_list_new ((EListCopyFunc) g_strdup,
- (EListFreeFunc) g_free,
- NULL);
-
- for (l = auth_methods; l; l = l->next)
- e_list_append (emethods, l->data);
-
- op->book = g_object_ref (book);
- op->elist = emethods;
-
- op->idle_id = g_idle_add (emit_async_elist_response, op);
- book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
- }
-
- g_mutex_unlock (book->priv->mutex);
-}
-
-
-
-static gboolean
-do_authenticate_user (gboolean sync,
- EBook *book,
- const char *user,
- const char *passwd,
- const char *auth_method,
- GError **error,
- EBookCallback cb,
- gpointer closure)
-{
- EBookOp *our_op;
- EBookStatus status;
- CORBA_Environment ev;
-
- g_mutex_lock (book->priv->mutex);
-
- if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
- g_mutex_unlock (book->priv->mutex);
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
- _("\"%s\" on book before \"%s\""),
- "e_book_authenticate_user", "e_book_open");
- }
- else {
- g_warning (_("\"%s\" on book before \"%s\""),
- "e_book_authenticate_user", "e_book_open");
- }
-
- return FALSE;
- }
-
- if (sync && e_book_get_current_sync_op (book) != NULL) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
- _("book busy"));
- return FALSE;
- }
-
- our_op = e_book_new_op (book, sync);
-
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_init (&ev);
-
- our_op->cb.status = cb;
- our_op->closure = closure;
-
- /* will eventually end up calling
- e_book_response_generic */
- GNOME_Evolution_Addressbook_Book_authenticateUser (book->priv->corba_book, our_op->opid,
- user, passwd,
- auth_method,
- &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_free (&ev);
-
- if (error)
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::authenticateUser");
- else
- g_warning (_("CORBA exception making \"%s\" call"),
- "Book::authenticateUser");
-
- return FALSE;
- }
-
- CORBA_exception_free (&ev);
-
- if (sync) {
- /* wait for something to happen (both cancellation and a
- successful response will notity us via our cv */
- e_flag_wait (our_op->flag);
-
- status = our_op->status;
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- E_BOOK_CHECK_STATUS (status, error);
- }
- else {
- return TRUE;
- }
+ org_gnome_evolution_dataserver_addressbook_Book_get_supported_auth_methods_async (book->priv->proxy, get_supported_auth_methods_reply, data);
+ return 0;
}
/**
@@ -1296,20 +924,28 @@ do_authenticate_user (gboolean sync,
* Return value: %TRUE if successful, %FALSE otherwise
**/
gboolean
-e_book_authenticate_user (EBook *book,
- const char *user,
- const char *passwd,
- const char *auth_method,
- GError **error)
+e_book_authenticate_user (EBook *book, const char *user, const char *passwd, const char *auth_method, GError **error)
+{
+ GError *err = NULL;
+
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+ org_gnome_evolution_dataserver_addressbook_Book_authenticate_user (book->priv->proxy, user, passwd, auth_method, &err);
+ return unwrap_gerror (err, error);
+}
+
+static void
+authenticate_user_reply(DBusGProxy *proxy, GError *error, gpointer user_data)
{
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (user, E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (passwd, E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (auth_method, E_BOOK_ERROR_INVALID_ARG, FALSE);
-
- return do_authenticate_user (TRUE,
- book, user, passwd, auth_method, error,
- NULL, NULL);
+ AsyncData *data = user_data;
+ EBookCallback cb = data->callback;
+
+ if (cb)
+ cb (data->book, get_status_from_error (error), data->closure);
+
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
/**
@@ -1329,114 +965,23 @@ e_book_authenticate_user (EBook *book,
* Return value: %FALSE if successful, %TRUE otherwise.
**/
guint
-e_book_async_authenticate_user (EBook *book,
- const char *user,
- const char *passwd,
- const char *auth_method,
- EBookCallback cb,
- gpointer closure)
+e_book_async_authenticate_user (EBook *book, const char *user, const char *passwd, const char *auth_method, EBookCallback cb, gpointer closure)
{
- g_return_val_if_fail (book && E_IS_BOOK (book), TRUE);
- g_return_val_if_fail (user, TRUE);
- g_return_val_if_fail (passwd, TRUE);
- g_return_val_if_fail (auth_method, TRUE);
-
- return !do_authenticate_user (FALSE,
- book, user, passwd, auth_method, NULL,
- cb, closure);
-}
+ AsyncData *data;
-
+ e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+ e_return_async_error_if_fail (user, E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_if_fail (passwd, E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_if_fail (auth_method, E_BOOK_ERROR_INVALID_ARG);
-static gboolean
-do_get_contact (gboolean sync,
- EBook *book,
- const char *id,
- EContact **contact,
- GError **error,
- EBookContactCallback cb,
- gpointer closure)
-{
- EBookOp *our_op;
- EBookStatus status;
- CORBA_Environment ev;
-
- g_mutex_lock (book->priv->mutex);
-
- if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
- g_mutex_unlock (book->priv->mutex);
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
- _("\"%s\" on book before \"%s\""),
- "e_book_get_contact", "e_book_open");
- }
- else {
- g_warning (_("\"%s\" on book before \"%s\""),
- "e_book_get_contact", "e_book_open");
- }
-
- return FALSE;
- }
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
- if (sync && e_book_get_current_sync_op (book) != NULL) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
- _("book busy"));
- return FALSE;
- }
-
- our_op = e_book_new_op (book, sync);
-
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_init (&ev);
-
- our_op->cb.contact = cb;
- our_op->closure = closure;
-
- /* will eventually end up calling e_book_response_generic */
- GNOME_Evolution_Addressbook_Book_getContact (book->priv->corba_book, our_op->opid,
- (const GNOME_Evolution_Addressbook_VCard) id, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_free (&ev);
-
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::getContact");
- }
- else {
- g_warning (_("CORBA exception making \"%s\" call"),
- "Book::getContact");
- }
- return FALSE;
- }
-
- CORBA_exception_free (&ev);
-
- if (sync) {
- /* wait for something to happen (both cancellation and a
- successful response will notity us via our cv */
- e_flag_wait (our_op->flag);
-
- status = our_op->status;
- *contact = our_op->contact;
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- E_BOOK_CHECK_STATUS (status, error);
- }
- else {
- return TRUE;
- }
+ org_gnome_evolution_dataserver_addressbook_Book_authenticate_user_async (book->priv->proxy, user, passwd, auth_method, authenticate_user_reply, data);
+ return 0;
}
/**
@@ -1452,680 +997,77 @@ do_get_contact (gboolean sync,
* Return value: %TRUE if successful, %FALSE otherwise
**/
gboolean
-e_book_get_contact (EBook *book,
- const char *id,
- EContact **contact,
- GError **error)
-{
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (id, E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (contact, E_BOOK_ERROR_INVALID_ARG, FALSE);
-
- return do_get_contact (TRUE,
- book, id, contact, error,
- NULL, NULL);
-}
-
-/**
- * e_book_async_get_contact:
- * @book: an #EBook
- * @id: a unique string ID specifying the contact
- * @cb: function to call when operation finishes
- * @closure: data to pass to callback function
- *
- * Retrieves a contact specified by @id from @book.
- *
- * Return value: %FALSE if successful, %TRUE otherwise
- **/
-guint
-e_book_async_get_contact (EBook *book,
- const char *id,
- EBookContactCallback cb,
- gpointer closure)
-{
- g_return_val_if_fail (book && E_IS_BOOK (book), TRUE);
- g_return_val_if_fail (id, TRUE);
-
- return !do_get_contact (FALSE,
- book, id, NULL, NULL,
- cb, closure);
-}
-
-static gboolean
-emit_async_get_contact_response (gpointer data)
+e_book_get_contact (EBook *book, const char *id, EContact **contact, GError **error)
{
- EBookOp *op = data;
- EBook *book = op->book;
-
- if (op->cb.contact)
- op->cb.contact (book, op->status, op->contact, op->closure);
-
- g_mutex_lock (book->priv->mutex);
-
- g_object_unref (op->contact);
-
- book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
+ GError *err = NULL;
+ char *vcard = NULL;
- e_book_clear_op (book, op);
-
- g_mutex_unlock (book->priv->mutex);
- g_object_unref (book);
-
- return FALSE;
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+ org_gnome_evolution_dataserver_addressbook_Book_get_contact (book->priv->proxy, id, &vcard, &err);
+ if (vcard) {
+ *contact = e_contact_new_from_vcard (vcard);
+ g_free (vcard);
+ }
+ return unwrap_gerror (err, error);
}
static void
-e_book_response_get_contact (EBook *book,
- guint32 opid,
- EBookStatus status,
- EContact *contact)
-{
- EBookOp *op;
-
- d(printf ("e_book_response_get_contact\n"));
-
- g_mutex_lock (book->priv->mutex);
-
- op = e_book_find_op (book, opid, G_STRFUNC);
-
- if (op == NULL) {
- g_mutex_unlock (book->priv->mutex);
- return;
- }
-
- op->status = status;
- op->contact = contact;
-
- if (op->synchronous)
- e_flag_set (op->flag);
- else {
- op->book = g_object_ref (book);
-
- op->idle_id = g_idle_add (emit_async_get_contact_response, op);
- book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
- }
-
- g_mutex_unlock (book->priv->mutex);
-}
-
-
-static gboolean
-do_remove_contacts (gboolean sync,
- EBook *book,
- GList *ids,
- GError **error,
- EBookCallback cb,
- gpointer closure)
+get_contact_reply(DBusGProxy *proxy, char *vcard, GError *error, gpointer user_data)
{
- GNOME_Evolution_Addressbook_ContactIdList idlist;
- CORBA_Environment ev;
- GList *iter;
- int num_ids, i;
- EBookOp *our_op;
- EBookStatus status;
-
- g_mutex_lock (book->priv->mutex);
-
- if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
- g_mutex_unlock (book->priv->mutex);
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
- _("\"%s\" on book before \"%s\""),
- "e_book_remove_contacts", "e_book_open");
- }
- else {
- g_warning (_("\"%s\" on book before \"%s\""),
- "e_book_remove_contacts", "e_book_open");
- }
- return FALSE;
- }
-
- if (sync && e_book_get_current_sync_op (book) != NULL) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
- _("book busy"));
- return FALSE;
- }
-
- our_op = e_book_new_op (book, sync);
-
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_init (&ev);
-
- num_ids = g_list_length (ids);
- idlist._buffer = CORBA_sequence_GNOME_Evolution_Addressbook_ContactId_allocbuf (num_ids);
- idlist._maximum = num_ids;
- idlist._length = num_ids;
-
- for (iter = ids, i = 0; iter; iter = iter->next)
- idlist._buffer[i++] = CORBA_string_dup (iter->data);
-
- our_op->cb.status = cb;
- our_op->closure = closure;
-
- /* will eventually end up calling e_book_response_generic */
- GNOME_Evolution_Addressbook_Book_removeContacts (book->priv->corba_book, our_op->opid, &idlist, &ev);
-
- CORBA_free(idlist._buffer);
+ AsyncData *data = user_data;
+ EBookContactCallback cb = data->callback;
+ EBookStatus status = get_status_from_error (error);
- if (ev._major != CORBA_NO_EXCEPTION) {
+ /* Protect against garbage return values on error */
+ if (error)
+ vcard = NULL;
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
+ if (cb) {
+ if (error == NULL) {
+ cb (data->book, status, e_contact_new_from_vcard (vcard), data->closure);
+ } else {
+ cb (data->book, status, NULL, data->closure);
+ }
+ } else {
+ g_warning (G_STRLOC ": cannot get contact: %s", error->message);
+ }
- CORBA_exception_free (&ev);
-
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::removeContacts");
- }
- else {
- g_warning (_("CORBA exception making \"%s\" call"),
- "Book::removeContacts");
- }
- return FALSE;
- }
-
- CORBA_exception_free (&ev);
-
- if (sync) {
- /* wait for something to happen (both cancellation and a
- successful response will notity us via our cv */
- e_flag_wait (our_op->flag);
-
- status = our_op->status;
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- E_BOOK_CHECK_STATUS (status, error);
- }
- else {
- return TRUE;
- }
+ if (error)
+ g_error_free (error);
+ g_free (vcard);
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
/**
- * e_book_remove_contact:
- * @book: an #EBook
- * @id: a string
- * @error: a #GError to set on failure
- *
- * Removes the contact with id @id from @book.
- *
- * Return value: %TRUE if successful, %FALSE otherwise
- **/
-gboolean
-e_book_remove_contact (EBook *book,
- const char *id,
- GError **error)
-{
- GList *list;
- gboolean rv;
-
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (id, E_BOOK_ERROR_INVALID_ARG, FALSE);
-
- list = g_list_append (NULL, (char*)id);
-
- rv = e_book_remove_contacts (book, list, error);
-
- g_list_free (list);
-
- return rv;
-}
-
-/**
- * e_book_remove_contacts:
- * @book: an #EBook
- * @ids: an #GList of const char *id's
- * @error: a #GError to set on failure
- *
- * Removes the contacts with ids from the list @ids from @book. This is
- * always more efficient than calling e_book_remove_contact_by_id if you
- * have more than one id to remove, as some backends can implement it
- * as a batch request.
- *
- * Return value: %TRUE if successful, %FALSE otherwise
- **/
-gboolean
-e_book_remove_contacts (EBook *book,
- GList *ids,
- GError **error)
-{
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (ids, E_BOOK_ERROR_INVALID_ARG, FALSE);
-
- return do_remove_contacts (TRUE,
- book, ids, error,
- NULL, NULL);
-}
-
-/**
- * e_book_async_remove_contact:
- * @book: an #EBook
- * @contact: an #EContact
- * @cb: a function to call when the operation finishes
- * @closure: data to pass to callback function
- *
- * Removes @contact from @book.
- *
- * Return value: %TRUE if successful, %FALSE otherwise
- **/
-guint
-e_book_async_remove_contact (EBook *book,
- EContact *contact,
- EBookCallback cb,
- gpointer closure)
-{
- const char *id;
-
- g_return_val_if_fail (E_IS_BOOK (book), TRUE);
- g_return_val_if_fail (E_IS_CONTACT (contact), TRUE);
-
- id = e_contact_get_const (contact, E_CONTACT_UID);
-
- return e_book_async_remove_contact_by_id (book, id, cb, closure);
-}
-
-/**
- * e_book_async_remove_contact_by_id:
- * @book: an #EBook
- * @id: a unique ID string specifying the contact
- * @cb: a function to call when the operation finishes
- * @closure: data to pass to callback function
- *
- * Removes the contact with id @id from @book.
- *
- * Return value: %TRUE if successful, %FALSE otherwise
- **/
-guint
-e_book_async_remove_contact_by_id (EBook *book,
- const char *id,
- EBookCallback cb,
- gpointer closure)
-{
- GList *list;
-
- g_return_val_if_fail (E_IS_BOOK (book), TRUE);
- g_return_val_if_fail (id != NULL, TRUE);
-
- list = g_list_append (NULL, g_strdup (id));
-
- return e_book_async_remove_contacts (book, list, cb, closure);
-}
-
-/**
- * e_book_async_remove_contacts:
- * @book: an #EBook
- * @ids: a #GList of const char *id's
- * @cb: a function to call when the operation finishes
- * @closure: data to pass to callback function
- *
- * Removes the contacts with ids from the list @ids from @book. This is
- * always more efficient than calling e_book_remove_contact_by_id() if you
- * have more than one id to remove, as some backends can implement it
- * as a batch request.
- *
- * Return value: %TRUE if successful, %FALSE otherwise
- **/
-guint
-e_book_async_remove_contacts (EBook *book,
- GList *ids,
- EBookCallback cb,
- gpointer closure)
-{
- g_return_val_if_fail (book && E_IS_BOOK (book), TRUE);
- g_return_val_if_fail (ids, TRUE);
-
- return !do_remove_contacts (FALSE,
- book, ids, NULL,
- cb, closure);
-}
-
-
-static gboolean
-do_get_book_view (gboolean sync,
- EBook *book,
- EBookQuery *query,
- GList *requested_fields,
- int max_results,
- EBookView **book_view,
- GError **error,
- EBookBookViewCallback cb,
- gpointer closure)
-{
- GNOME_Evolution_Addressbook_stringlist stringlist;
- CORBA_Environment ev;
- EBookOp *our_op;
- EBookStatus status;
- int num_fields, i;
- GList *iter;
- char *query_string;
-
- g_mutex_lock (book->priv->mutex);
-
- if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
- g_mutex_unlock (book->priv->mutex);
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
- _("\"%s\" on book before \"%s\""),
- "e_book_get_book_view", "e_book_open");
- }
- else {
- g_warning (_("\"%s\" on book before \"%s\""),
- "e_book_get_book_view", "e_book_open");
- }
- return FALSE;
- }
-
- if (sync && e_book_get_current_sync_op (book) != NULL) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
- _("book busy"));
- return FALSE;
- }
-
- our_op = e_book_new_op (book, sync);
-
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_init (&ev);
-
- our_op->listener = e_book_view_listener_new();
-
- num_fields = g_list_length (requested_fields);
-
- stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_fields);
- stringlist._maximum = num_fields;
- stringlist._length = num_fields;
-
- for (i = 0, iter = requested_fields; iter; iter = iter->next, i ++) {
- stringlist._buffer[i] = CORBA_string_dup ((char*)iter->data);
- }
-
- query_string = e_book_query_to_string (query);
-
- our_op->cb.book_view = cb;
- our_op->closure = closure;
-
- /* will eventually end up calling e_book_response_get_book_view */
- GNOME_Evolution_Addressbook_Book_getBookView (book->priv->corba_book,
- our_op->opid,
- bonobo_object_corba_objref(BONOBO_OBJECT(our_op->listener)),
- query_string,
- &stringlist, max_results, &ev);
-
- CORBA_free(stringlist._buffer);
- g_free (query_string);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_free (&ev);
-
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::authenticateUser");
- }
- else {
- g_warning (_("CORBA exception making \"%s\" call"),
- "Book::authenticateUser");
- }
-
- return FALSE;
- }
-
- CORBA_exception_free (&ev);
-
- if (sync) {
- /* wait for something to happen (both cancellation and a
- successful response will notity us via our cv */
- e_flag_wait (our_op->flag);
-
- status = our_op->status;
- *book_view = our_op->view;
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- E_BOOK_CHECK_STATUS (status, error);
- }
- else {
- return TRUE;
- }
-}
-
-/**
- * e_book_get_book_view:
- * @book: an #EBook
- * @query: an #EBookQuery
- * @requested_fields: a #GList containing the names of fields to return, or NULL for all
- * @max_results: the maximum number of contacts to show (or 0 for all)
- * @book_view: A #EBookView pointer, will be set to the view
- * @error: a #GError to set on failure
- *
- * Query @book with @query, creating a #EBookView in @book_view with the fields
- * specified by @requested_fields and limited at @max_results records. On an
- * error, @error is set and %FALSE returned.
- *
- * Return value: %TRUE if successful, %FALSE otherwise
- **/
-gboolean
-e_book_get_book_view (EBook *book,
- EBookQuery *query,
- GList *requested_fields,
- int max_results,
- EBookView **book_view,
- GError **error)
-{
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (query, E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (book_view, E_BOOK_ERROR_INVALID_ARG, FALSE);
-
- return do_get_book_view (TRUE,
- book, query, requested_fields, max_results, book_view, error,
- NULL, NULL);
-}
-
-/**
- * e_book_async_get_book_view:
+ * e_book_async_get_contact:
* @book: an #EBook
- * @query: an #EBookQuery
- * @requested_fields: a #GList containing the names of fields to return, or NULL for all
- * @max_results: the maximum number of contacts to show (or 0 for all)
- * @cb: a function to call when the operation finishes
+ * @id: a unique string ID specifying the contact
+ * @cb: function to call when operation finishes
* @closure: data to pass to callback function
*
- * Query @book with @query, creating a #EBookView with the fields
- * specified by @requested_fields and limited at @max_results records.
+ * Retrieves a contact specified by @id from @book.
*
* Return value: %FALSE if successful, %TRUE otherwise
**/
guint
-e_book_async_get_book_view (EBook *book,
- EBookQuery *query,
- GList *requested_fields,
- int max_results,
- EBookBookViewCallback cb,
- gpointer closure)
-{
- g_return_val_if_fail (book && E_IS_BOOK (book), TRUE);
- g_return_val_if_fail (query, TRUE);
-
- return !do_get_book_view (FALSE,
- book, query, requested_fields, max_results, NULL, NULL,
- cb, closure);
-}
-
-static gboolean
-emit_async_get_book_view_response (gpointer data)
+e_book_async_get_contact (EBook *book, const char *id, EBookContactCallback cb, gpointer closure)
{
- EBookOp *op = data;
- EBook *book = op->book;
-
- if (op->cb.book_view)
- op->cb.book_view (book, op->status, op->view, op->closure);
-
- g_mutex_lock (book->priv->mutex);
-
- g_object_unref (op->view);
-
- book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
-
- e_book_clear_op (book, op);
-
- g_mutex_unlock (book->priv->mutex);
- g_object_unref (book);
-
- return FALSE;
-}
-
-static void
-e_book_response_get_book_view (EBook *book,
- guint32 opid,
- EBookStatus status,
- GNOME_Evolution_Addressbook_BookView corba_book_view)
-{
-
- EBookOp *op;
+ AsyncData *data;
- d(printf ("e_book_response_get_book_view\n"));
+ e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+ e_return_async_error_val_if_fail (id, E_BOOK_ERROR_INVALID_ARG);
- g_mutex_lock (book->priv->mutex);
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
- op = e_book_find_op (book, opid, G_STRFUNC);
-
- if (op == NULL) {
- g_mutex_unlock (book->priv->mutex);
- return;
- }
-
- op->status = status;
- op->view = e_book_view_new (corba_book_view, op->listener);
- e_book_view_set_book (op->view, book);
-
- bonobo_object_unref(BONOBO_OBJECT(op->listener));
-
- if (op->synchronous)
- e_flag_set (op->flag);
- else {
- op->book = g_object_ref (book);
-
- op->idle_id = g_idle_add (emit_async_get_book_view_response, op);
- book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
- }
-
- g_mutex_unlock (book->priv->mutex);
-}
-
-static gboolean
-do_get_contacts (gboolean sync,
- EBook *book,
- EBookQuery *query,
- GList **contacts,
- GError **error,
- EBookListCallback cb,
- gpointer closure)
-{
- CORBA_Environment ev;
- EBookOp *our_op;
- EBookStatus status;
- char *query_string;
-
- g_mutex_lock (book->priv->mutex);
-
- if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
- g_mutex_unlock (book->priv->mutex);
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
- _("\"%s\" on book before \"%s\""),
- "e_book_get_contacts", "e_book_open");
- }
- else {
- g_warning (_("\"%s\" on book before \"%s\""),
- "e_book_get_contacts", "e_book_open");
- }
-
- return FALSE;
- }
-
- if (sync && e_book_get_current_sync_op (book) != NULL) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
- _("book busy"));
- return FALSE;
- }
-
- our_op = e_book_new_op (book, sync);
-
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_init (&ev);
-
- query_string = e_book_query_to_string (query);
-
- our_op->cb.list = cb;
- our_op->closure = closure;
-
- /* will eventually end up calling e_book_response_get_contacts */
- GNOME_Evolution_Addressbook_Book_getContactList (book->priv->corba_book, our_op->opid, query_string, &ev);
-
- g_free (query_string);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_free (&ev);
-
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::getContactList");
- }
- else {
- g_warning (_("CORBA exception making \"%s\" call"),
- "Book::getContactList");
- }
-
- return FALSE;
- }
-
- CORBA_exception_free (&ev);
-
- if (sync) {
- /* wait for something to happen (both cancellation and a
- successful response will notity us via our cv */
- e_flag_wait (our_op->flag);
-
- status = our_op->status;
- *contacts = our_op->list;
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- E_BOOK_CHECK_STATUS (status, error);
- }
- else {
- return TRUE;
- }
+ org_gnome_evolution_dataserver_addressbook_Book_get_contact_async (book->priv->proxy, id, get_contact_reply, data);
+ return 0;
}
/**
@@ -2141,18 +1083,52 @@ do_get_contacts (gboolean sync,
* Return value: %TRUE on success, %FALSE otherwise
**/
gboolean
-e_book_get_contacts (EBook *book,
- EBookQuery *query,
- GList **contacts,
- GError **error)
+e_book_get_contacts (EBook *book, EBookQuery *query, GList **contacts, GError **error)
+{
+ GError *err = NULL;
+ char **list = NULL;
+ char *sexp;
+
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+ sexp = e_book_query_to_string (query);
+ org_gnome_evolution_dataserver_addressbook_Book_get_contact_list (book->priv->proxy, sexp, &list, &err);
+ g_free (sexp);
+ if (!err) {
+ GList *l = NULL;
+ char **i = list;
+ while (*i != NULL) {
+ l = g_list_prepend (l, e_contact_new_from_vcard (*i++));
+ }
+ *contacts = g_list_reverse (l);
+ g_strfreev (list);
+ return TRUE;
+ } else {
+ return unwrap_gerror (err, error);
+ }
+}
+
+static void
+get_contacts_reply(DBusGProxy *proxy, char **vcards, GError *error, gpointer user_data)
{
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (query, E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (contacts, E_BOOK_ERROR_INVALID_ARG, FALSE);
+ AsyncData *data = user_data;
+ GList *list = NULL;
+ EBookListCallback cb = data->callback;
+ if (vcards) {
+ char **i = vcards;
+ while (*i != NULL) {
+ list = g_list_prepend (list, e_contact_new_from_vcard (*i++));
+ }
+ }
+ list = g_list_reverse (list);
- return do_get_contacts (TRUE,
- book, query, contacts, error,
- NULL, NULL);
+ if (cb)
+ cb (data->book, get_status_from_error (error), list, data->closure);
+ g_strfreev (vcards);
+
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
/**
@@ -2167,168 +1143,54 @@ e_book_get_contacts (EBook *book,
* Return value: %FALSE on success, %TRUE otherwise
**/
guint
-e_book_async_get_contacts (EBook *book,
- EBookQuery *query,
- EBookListCallback cb,
- gpointer closure)
+e_book_async_get_contacts (EBook *book, EBookQuery *query, EBookListCallback cb, gpointer closure)
{
- g_return_val_if_fail (book && E_IS_BOOK (book), TRUE);
- g_return_val_if_fail (query, TRUE);
+ AsyncData *data;
+ char *sexp;
- return !do_get_contacts (FALSE,
- book, query, NULL, NULL,
- cb, closure);
-}
-
-static gboolean
-emit_async_get_contacts_response (gpointer data)
-{
- EBookOp *op = data;
- EBook *book = op->book;
+ e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+ e_return_async_error_val_if_fail (query, E_BOOK_ERROR_INVALID_ARG);
- if (op->cb.list)
- op->cb.list (book, op->status, op->list, op->closure);
+ sexp = e_book_query_to_string (query);
- g_mutex_lock (book->priv->mutex);
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
- g_list_foreach (op->list, (GFunc)g_object_unref, NULL);
- g_list_free (op->list);
-
- book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
-
- e_book_clear_op (book, op);
-
- g_mutex_unlock (book->priv->mutex);
- g_object_unref (book);
-
- return FALSE;
+ org_gnome_evolution_dataserver_addressbook_Book_get_contact_list_async (book->priv->proxy, sexp, get_contacts_reply, data);
+ g_free (sexp);
+ return 0;
}
-
-static void
-e_book_response_get_contacts (EBook *book,
- guint32 opid,
- EBookStatus status,
- GList *contact_list)
+static GList *
+parse_changes_array (GPtrArray *array)
{
+ GList *l = NULL;
+ int i;
+
+ if (array == NULL)
+ return NULL;
- EBookOp *op;
+ for (i = 0; i < array->len; i++) {
+ EBookChange *change;
+ GValueArray *vals;
- g_mutex_lock (book->priv->mutex);
+ vals = g_ptr_array_index (array, i);
- op = e_book_find_op (book, opid, G_STRFUNC);
+ change = g_slice_new (EBookChange);
+ change->change_type = g_value_get_uint (g_value_array_get_nth (vals, 0));
+ change->contact = e_contact_new_from_vcard
+ (g_value_get_string (g_value_array_get_nth (vals, 1)));
- if (op == NULL) {
- g_mutex_unlock (book->priv->mutex);
- return;
- }
-
- op->list = g_list_copy (contact_list);
- g_list_foreach (op->list, (GFunc)g_object_ref, NULL);
- op->status = status;
-
- if (op->synchronous)
- e_flag_set (op->flag);
- else {
- op->book = g_object_ref (book);
- op->idle_id = g_idle_add (emit_async_get_contacts_response, op);
- book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
- }
+ l = g_list_prepend (l, change);
+ }
+
+ g_ptr_array_foreach (array, (GFunc)g_value_array_free, NULL);
+ g_ptr_array_free (array, TRUE);
- g_mutex_unlock (book->priv->mutex);
-}
-
-
-static gboolean
-do_get_changes (gboolean sync,
- EBook *book,
- char *changeid,
- GList **changes,
- GError **error,
- EBookListCallback cb,
- gpointer closure)
-{
- CORBA_Environment ev;
- EBookOp *our_op;
- EBookStatus status;
-
- g_mutex_lock (book->priv->mutex);
-
- if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
- g_mutex_unlock (book->priv->mutex);
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
- _("\"%s\" on book before \"%s\""),
- "e_book_get_changes", "e_book_open");
- }
- else {
- g_warning (_("\"%s\" on book before \"%s\""),
- "e_book_get_changes", "e_book_open");
- }
- return FALSE;
- }
-
- if (sync && e_book_get_current_sync_op (book) != NULL) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
- _("book busy"));
- return FALSE;
- }
-
- our_op = e_book_new_op (book, sync);
-
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_init (&ev);
-
- our_op->cb.list = cb;
- our_op->closure = closure;
-
- /* will eventually end up calling e_book_response_get_changes */
- GNOME_Evolution_Addressbook_Book_getChanges (book->priv->corba_book, our_op->opid, changeid, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_free (&ev);
-
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::getChanges");
- }
- else {
- g_warning (_("CORBA exception making \"%s\" call"),
- "Book::getChanges");
- }
-
- return FALSE;
- }
-
- CORBA_exception_free (&ev);
-
- if (sync) {
- /* wait for something to happen (both cancellation and a
- successful response will notity us via our cv */
- e_flag_wait (our_op->flag);
-
- status = our_op->status;
- *changes = our_op->list;
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- E_BOOK_CHECK_STATUS (status, error);
- }
- else {
- return TRUE;
- }
+ return g_list_reverse (l);
}
/**
@@ -2344,18 +1206,38 @@ do_get_changes (gboolean sync,
* Return value: TRUE on success, FALSE otherwise
*/
gboolean
-e_book_get_changes (EBook *book,
- char *changeid,
- GList **changes,
- GError **error)
+e_book_get_changes (EBook *book, char *changeid, GList **changes, GError **error)
{
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (changeid, E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (changes, E_BOOK_ERROR_INVALID_ARG, FALSE);
+ GError *err = NULL;
+ GPtrArray *array = NULL;
+
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+ org_gnome_evolution_dataserver_addressbook_Book_get_changes (book->priv->proxy, changeid, &array, &err);
+ if (!err) {
+ *changes = parse_changes_array (array);
+ return TRUE;
+ } else {
+ return unwrap_gerror (err, error);
+ }
+}
+
+static void
+get_changes_reply (DBusGProxy *proxy, GPtrArray *changes, GError *error, gpointer user_data)
+{
+ AsyncData *data = user_data;
+ EBookListCallback cb = data->callback;
+ GList *list = NULL;
+
+ if (changes)
+ list = parse_changes_array (changes);
+
+ if (cb)
+ cb (data->book, get_status_from_error (error), list, data->closure);
- return do_get_changes (TRUE,
- book, changeid, changes, error,
- NULL, NULL);
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
/**
@@ -2371,74 +1253,20 @@ e_book_get_changes (EBook *book,
* Return value: TRUE on success, FALSE otherwise
*/
guint
-e_book_async_get_changes (EBook *book,
- char *changeid,
- EBookListCallback cb,
- gpointer closure)
-{
- g_return_val_if_fail (book && E_IS_BOOK (book), TRUE);
- g_return_val_if_fail (changeid, TRUE);
-
- return !do_get_changes (FALSE,
- book, changeid, NULL, NULL,
- cb, closure);
-}
-
-static gboolean
-emit_async_get_changes_response (gpointer data)
-{
- EBookOp *op = data;
- EBook *book = op->book;
-
- if (op->cb.list)
- op->cb.list (book, op->status, op->list, op->closure);
-
- g_mutex_lock (book->priv->mutex);
-
- e_book_free_change_list (op->list);
-
- book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
-
- e_book_clear_op (book, op);
-
- g_mutex_unlock (book->priv->mutex);
- g_object_unref (book);
-
- return FALSE;
-}
-
-static void
-e_book_response_get_changes (EBook *book,
- guint32 opid,
- EBookStatus status,
- GList *change_list)
+e_book_async_get_changes (EBook *book, char *changeid, EBookListCallback cb, gpointer closure)
{
+ AsyncData *data;
- EBookOp *op;
-
- g_mutex_lock (book->priv->mutex);
-
- op = e_book_find_op (book, opid, G_STRFUNC);
-
- if (op == NULL) {
- g_mutex_unlock (book->priv->mutex);
- return;
- }
+ e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- op->status = status;
- op->list = change_list;
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
- if (op->synchronous)
- e_flag_set (op->flag);
- else {
- op->book = g_object_ref (book);
- op->idle_id = g_idle_add (emit_async_get_changes_response, op);
- book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
- }
-
- g_mutex_unlock (book->priv->mutex);
+ org_gnome_evolution_dataserver_addressbook_Book_get_changes_async (book->priv->proxy, changeid, get_changes_reply, data);
+ return 0;
}
/**
@@ -2455,1053 +1283,491 @@ e_book_free_change_list (GList *change_list)
EBookChange *change = l->data;
g_object_unref (change->contact);
- g_free (change);
+ g_slice_free (EBookChange, change);
}
g_list_free (change_list);
}
-
-
-static gboolean
-emit_async_generic_response (gpointer data)
+/**
+ * e_book_add_contact:
+ * @book: an #EBook
+ * @contact: an #EContact
+ * @error: a #GError to set on failure
+ *
+ * Adds @contact to @book.
+ *
+ * Return value: %TRUE if successful, %FALSE otherwise.
+ **/
+gboolean
+e_book_add_contact (EBook *book, EContact *contact, GError **error)
{
- EBookOp *op = data;
- EBook *book = op->book;
-
- if (op->cb.status)
- op->cb.status (book, op->status, op->closure);
-
- g_mutex_lock (book->priv->mutex);
-
- book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
+ GError *err = NULL;
+ char *vcard, *uid = NULL;
- e_book_clear_op (book, op);
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+ e_return_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
- g_mutex_unlock (book->priv->mutex);
- g_object_unref (book);
-
- return FALSE;
+ vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+ org_gnome_evolution_dataserver_addressbook_Book_add_contact (book->priv->proxy, vcard, &uid, &err);
+ g_free (vcard);
+ if (uid) {
+ e_contact_set (contact, E_CONTACT_UID, uid);
+ g_free (uid);
+ }
+ return unwrap_gerror (err, error);
}
static void
-e_book_response_generic (EBook *book,
- guint32 opid,
- EBookStatus status)
+add_contact_reply (DBusGProxy *proxy, char *uid, GError *error, gpointer user_data)
{
- EBookOp *op;
- d(printf("e_book_response_generic\n"));
- g_mutex_lock (book->priv->mutex);
-
- op = e_book_find_op (book, opid, G_STRFUNC);
-
- if (op == NULL) {
- g_mutex_unlock (book->priv->mutex);
- return;
- }
-
- op->status = status;
- if (op->synchronous)
- e_flag_set (op->flag);
- else {
- op->book = g_object_ref (book);
- op->idle_id = g_idle_add (emit_async_generic_response, op);
- book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
- }
-
- g_mutex_unlock (book->priv->mutex);
-}
-
-static gboolean
-do_cancel (EBook *book, GError **error, EBookOp *op, const char *func_name)
-{
- EBookStatus status;
- gboolean rv;
- CORBA_Environment ev;
-
- if (op == NULL) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_COULD_NOT_CANCEL,
- _("%s: there is no current operation"), func_name);
- return FALSE;
- }
-
- status = GNOME_Evolution_Addressbook_Book_cancelOperation(book->priv->corba_book, &ev);
+ AsyncData *data = user_data;
+ EBookIdCallback cb = data->callback;
- if (ev._major != CORBA_NO_EXCEPTION) {
+ /* If there is an error returned the GLib bindings currently return garbage
+ for the OUT values. This is bad. */
+ if (error)
+ uid = NULL;
- CORBA_exception_free (&ev);
-
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::cancelOperation");
- e_flag_set (op->flag);
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, op);
- g_mutex_unlock (book->priv->mutex);
- return FALSE;
- }
-
- CORBA_exception_free (&ev);
-
- if (status == E_BOOK_ERROR_OK) {
- op->status = E_BOOK_ERROR_CANCELLED;
- rv = TRUE;
- }
- else {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_COULD_NOT_CANCEL,
- _("%s: could not cancel"), func_name);
- rv = FALSE;
- }
- /* Always trigger the operation, we cannot put it back to queue, because
- the result could come just few ticks before, in the other thread. */
- e_flag_set (op->flag);
+ if (cb)
+ cb (data->book, get_status_from_error (error), uid, data->closure);
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, op);
- g_mutex_unlock (book->priv->mutex);
+ if (uid)
+ g_free (uid);
- return rv;
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
/**
- * e_book_cancel:
+ * e_book_async_add_contact:
* @book: an #EBook
- * @error: a #GError to set on failure
+ * @contact: an #EContact
+ * @cb: function to call when the operation finishes
+ * @closure: data to pass to callback function
*
- * Used to cancel an already running operation on @book. This
- * function makes a synchronous CORBA to the backend telling it to
- * cancel the operation. If the operation wasn't cancellable (either
- * transiently or permanently) or had already comopleted on the server
- * side, this function will return E_BOOK_STATUS_COULD_NOT_CANCEL, and
- * the operation will continue uncancelled. If the operation could be
- * cancelled, this function will return E_BOOK_ERROR_OK, and the
- * blocked e_book function corresponding to current operation will
- * return with a status of E_BOOK_STATUS_CANCELLED.
+ * Adds @contact to @book without blocking.
*
- * Return value: %TRUE on success, %FALSE otherwise
+ * Return value: %TRUE if the operation was started, %FALSE otherwise.
**/
gboolean
-e_book_cancel (EBook *book,
- GError **error)
+e_book_async_add_contact (EBook *book, EContact *contact, EBookIdCallback cb, gpointer closure)
{
- EBookOp *op;
-
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
-
- g_mutex_lock (book->priv->mutex);
- op = e_book_get_current_sync_op (book);
- if (op) {
- if (op->opstate != STATE_WAITING) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_COULD_NOT_CANCEL,
- _("%s: could not cancel"), G_STRFUNC);
- return FALSE;
- }
+ char *vcard;
+ AsyncData *data;
- op->opstate = STATE_CANCELLING;
- }
- g_mutex_unlock (book->priv->mutex);
+ e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+ e_return_async_error_val_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
- return do_cancel (book, error, op, "e_book_cancel");
+ vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
+
+ org_gnome_evolution_dataserver_addressbook_Book_add_contact_async (book->priv->proxy, vcard, add_contact_reply, data);
+ g_free (vcard);
+ return 0;
}
/**
- * e_book_cancel_async_op:
- * Similar to above e_book_cancel function, only cancels last, still running,
- * asynchronous operation.
+ * e_book_commit_contact:
+ * @book: an #EBook
+ * @contact: an #EContact
+ * @error: a #GError to set on failure
+ *
+ * Applies the changes made to @contact to the stored version in
+ * @book.
+ *
+ * Return value: %TRUE if successful, %FALSE otherwise
**/
gboolean
-e_book_cancel_async_op (EBook *book, GError **error)
+e_book_commit_contact (EBook *book, EContact *contact, GError **error)
{
- EBookOp *op;
- guint32 opid;
-
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
-
- g_mutex_lock (book->priv->mutex);
-
- /* find nearest unfinished async op to cancel */
- op = NULL;
- for (opid = book->priv->current_op_id; opid > 0 && !op; opid--) {
- op = e_book_get_op (book, opid);
-
- if (op && op->synchronous)
- op = NULL;
- }
-
- if (op) {
- if (op->opstate != STATE_WAITING) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_COULD_NOT_CANCEL,
- _("%s: could not cancel"), G_STRFUNC);
- return FALSE;
- }
-
- op->opstate = STATE_CANCELLING;
- }
+ GError *err = NULL;
+ char *vcard;
- g_mutex_unlock (book->priv->mutex);
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+ e_return_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
- return do_cancel (book, error, op, "e_book_cancel_async_op");
+ vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+ org_gnome_evolution_dataserver_addressbook_Book_modify_contact (book->priv->proxy, vcard, &err);
+ g_free (vcard);
+ return unwrap_gerror (err, error);
}
-
-
-static gboolean
-do_open (gboolean sync,
- EBook *book,
- gboolean only_if_exists,
- GError **error,
- EBookCallback cb,
- gpointer closure)
+static void
+modify_contact_reply (DBusGProxy *proxy, GError *error, gpointer user_data)
{
- CORBA_Environment ev;
- EBookOp *our_op;
- EBookStatus status;
-
- g_mutex_lock (book->priv->mutex);
-
- if (book->priv->load_state != E_BOOK_SOURCE_NOT_LOADED) {
- g_mutex_unlock (book->priv->mutex);
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_ALREADY_LOADED,
- _("\"%s\" on book after \"%s\""),
- "e_book_open", "e_book_open");
- }
- else {
- g_warning (_("\"%s\" on book after \"%s\""),
- "e_book_open", "e_book_open");
- }
-
- return FALSE;
- }
-
- if (sync && e_book_get_current_sync_op (book) != NULL) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
- _("book busy"));
- return FALSE;
- }
-
- our_op = e_book_new_op (book, sync);
+ AsyncData *data = user_data;
+ EBookCallback cb = data->callback;
- g_mutex_unlock (book->priv->mutex);
+ if (cb)
+ cb (data->book, get_status_from_error (error), data->closure);
- CORBA_exception_init (&ev);
-
- our_op->cb.status = cb;
- our_op->closure = closure;
-
- /* will eventually end up calling e_book_response_remove */
- GNOME_Evolution_Addressbook_Book_open (book->priv->corba_book, our_op->opid, only_if_exists, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_free (&ev);
-
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::open");
- }
- else {
- g_warning (_("CORBA exception making \"%s\" call"),
- "Book::open");
- }
-
- return FALSE;
- }
-
- CORBA_exception_free (&ev);
-
- if (sync) {
- /* wait for something to happen (both cancellation and a
- successful response will notity us via our cv */
- e_flag_wait (our_op->flag);
-
- status = our_op->status;
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- if (status == E_BOOK_ERROR_CANCELLED) {
- /* Cancelled */
- book->priv->load_state = E_BOOK_SOURCE_NOT_LOADED;
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CANCELLED,
- _("%s: canceled"), "e_book_open");
- return FALSE;
- }
- else if (status == E_BOOK_ERROR_OK) {
- book->priv->load_state = E_BOOK_SOURCE_LOADED;
- return TRUE;
- }
- else {
- E_BOOK_CHECK_STATUS (status, error);
- }
- }
- else {
- return TRUE;
- }
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
/**
- * e_book_open:
+ * e_book_async_commit_contact:
* @book: an #EBook
- * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
- * @error: a #GError to set on failure
+ * @contact: an #EContact
+ * @cb: function to call when the operation finishes
+ * @closure: data to pass to callback function
*
- * Opens the addressbook, making it ready for queries and other operations.
+ * Applies the changes made to @contact to the stored version in
+ * @book without blocking.
*
- * Return value: %TRUE if the book was successfully opened, %FALSE otherwise.
- */
-gboolean
-e_book_open (EBook *book,
- gboolean only_if_exists,
- GError **error)
+ * Return value: %TRUE if the operation was started, %FALSE otherwise.
+ **/
+guint
+e_book_async_commit_contact (EBook *book, EContact *contact, EBookCallback cb, gpointer closure)
{
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
+ char *vcard;
+ AsyncData *data;
+
+ e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+ e_return_async_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
- return do_open (TRUE,
- book, only_if_exists, error,
- NULL, NULL);
+ vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
+
+ org_gnome_evolution_dataserver_addressbook_Book_modify_contact_async (book->priv->proxy, vcard, modify_contact_reply, data);
+ g_free (vcard);
+ return 0;
}
/**
- * e_book_async_open:
+ * e_book_remove_contact:
* @book: an #EBook
- * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
- * @open_response: a function to call when the operation finishes
- * @closure: data to pass to callback function
+ * @id: a string
+ * @error: a #GError to set on failure
*
- * Opens the addressbook, making it ready for queries and other operations.
- * This function does not block.
+ * Removes the contact with id @id from @book.
*
- * Return value: %FALSE if successful, %TRUE otherwise.
+ * Return value: %TRUE if successful, %FALSE otherwise
**/
-guint
-e_book_async_open (EBook *book,
- gboolean only_if_exists,
- EBookCallback open_response,
- gpointer closure)
-{
- g_return_val_if_fail (book && E_IS_BOOK (book), FALSE);
-
- return !do_open (FALSE,
- book, only_if_exists, NULL,
- open_response, closure);
-}
-
-static gboolean
-emit_async_open_response (gpointer data)
+gboolean
+e_book_remove_contact (EBook *book, const char *id, GError **error)
{
- EBookOp *op = data;
- EBook *book = op->book;
-
- d(printf ("in async_open_response\n"));
-
- g_mutex_lock (book->priv->mutex);
-
- if (op->status == E_BOOK_ERROR_OK)
- book->priv->load_state = E_BOOK_SOURCE_LOADED;
- else
- book->priv->load_state = E_BOOK_SOURCE_NOT_LOADED;
-
- g_mutex_unlock (book->priv->mutex);
+ GError *err = NULL;
+ const char *l[2];
- if (op->cb.status)
- op->cb.status (book, op->status, op->closure);
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+ e_return_error_if_fail (id, E_BOOK_ERROR_INVALID_ARG);
- g_mutex_lock (book->priv->mutex);
+ l[0] = id;
+ l[1] = NULL;
- book->priv->pending_idles = g_list_remove (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
-
- e_book_clear_op (book, op);
-
- g_mutex_unlock (book->priv->mutex);
- g_object_unref (book);
-
- return FALSE;
+ org_gnome_evolution_dataserver_addressbook_Book_remove_contacts (book->priv->proxy, l, &err);
+ return unwrap_gerror (err, error);
}
static void
-e_book_response_open (EBook *book,
- guint32 opid,
- EBookStatus status)
+remove_contact_reply (DBusGProxy *proxy, GError *error, gpointer user_data)
{
- EBookOp *op;
-
- d(printf ("in e_book_response_open\n"));
+ AsyncData *data = user_data;
+ EBookCallback cb = data->callback;
- g_mutex_lock (book->priv->mutex);
-
- op = e_book_find_op (book, opid, G_STRFUNC);
-
- if (op == NULL) {
- g_mutex_unlock (book->priv->mutex);
- return;
- }
+ if (cb)
+ cb (data->book, get_status_from_error (error), data->closure);
- op->status = status;
- if (op->synchronous)
- e_flag_set (op->flag);
- else {
- op->book = g_object_ref (book);
- op->idle_id = g_idle_add (emit_async_open_response, op);
- book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
- }
-
- g_mutex_unlock (book->priv->mutex);
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
-
-static gboolean
-do_remove (gboolean sync,
- EBook *book,
- GError **error,
- EBookCallback cb,
- gpointer closure)
+/**
+ * e_book_async_remove_contact:
+ * @book: an #EBook
+ * @contact: an #EContact
+ * @cb: a function to call when the operation finishes
+ * @closure: data to pass to callback function
+ *
+ * Removes @contact from @book.
+ *
+ * Return value: %TRUE if successful, %FALSE otherwise
+ **/guint
+e_book_async_remove_contact (EBook *book, EContact *contact, EBookCallback cb, gpointer closure)
{
- CORBA_Environment ev;
- EBookOp *our_op;
- EBookStatus status;
-
- g_mutex_lock (book->priv->mutex);
-
- if (sync && e_book_get_current_sync_op (book) != NULL) {
- g_mutex_unlock (book->priv->mutex);
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_BUSY,
- _("book busy"));
- return FALSE;
- }
-
- our_op = e_book_new_op (book, sync);
-
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_init (&ev);
-
- our_op->cb.status = cb;
- our_op->closure = closure;
-
- /* will eventually end up calling e_book_response_remove */
- GNOME_Evolution_Addressbook_Book_remove (book->priv->corba_book, our_op->opid, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
-
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- CORBA_exception_free (&ev);
-
- if (error) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::remove");
- }
- else {
- g_warning (_("CORBA exception making \"%s\" call"),
- "Book::remove");
- }
-
- return FALSE;
- }
+ AsyncData *data;
+ const char *l[2];
- CORBA_exception_free (&ev);
+ e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+ e_return_async_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
- if (sync) {
- /* wait for something to happen (both cancellation and a
- successful response will notity us via our cv */
- e_flag_wait (our_op->flag);
+ l[0] = e_contact_get_const (contact, E_CONTACT_UID);
+ l[1] = NULL;
- status = our_op->status;
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
- g_mutex_lock (book->priv->mutex);
- e_book_clear_op (book, our_op);
- g_mutex_unlock (book->priv->mutex);
-
- E_BOOK_CHECK_STATUS (status, error);
- }
- else {
- return TRUE;
- }
+ org_gnome_evolution_dataserver_addressbook_Book_remove_contacts_async (book->priv->proxy, l, remove_contact_reply, data);
+ return 0;
}
-/**
- * e_book_remove:
- * @book: an #EBook
- * @error: a #GError to set on failure
- *
- * Removes the backing data for this #EBook. For example, with the file backend this
- * deletes the database file. You cannot get it back!
- *
- * Return value: %TRUE on success, %FALSE on failure.
- */
-gboolean
-e_book_remove (EBook *book,
- GError **error)
+static void
+remove_contact_by_id_reply (DBusGProxy *proxy, GError *error, gpointer user_data)
{
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
+ AsyncData *data = user_data;
+ EBookCallback cb = data->callback;
- return do_remove (TRUE,
- book, error,
- NULL, NULL);
+ if (cb)
+ cb (data->book, get_status_from_error (error), data->closure);
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
/**
- * e_book_async_remove:
+ * e_book_async_remove_contact_by_id:
* @book: an #EBook
+ * @id: a unique ID string specifying the contact
* @cb: a function to call when the operation finishes
* @closure: data to pass to callback function
*
- * Remove the backing data for this #EBook. For example, with the file backend this
- * deletes the database file. You cannot get it back!
+ * Removes the contact with id @id from @book.
*
- * Return value: %FALSE if successful, %TRUE otherwise.
+ * Return value: %TRUE if successful, %FALSE otherwise
**/
guint
-e_book_async_remove (EBook *book,
- EBookCallback cb,
- gpointer closure)
-{
- g_return_val_if_fail (book && E_IS_BOOK (book), TRUE);
-
- return !do_remove (FALSE,
- book, NULL,
- cb, closure);
-
-}
-
-static void
-e_book_response_remove (EBook *book,
- guint32 opid,
- EBookStatus status)
-{
- EBookOp *op;
-
- d(printf ("e_book_response_remove\n"));
-
- g_mutex_lock (book->priv->mutex);
-
- op = e_book_find_op (book, opid, G_STRFUNC);
-
- if (op == NULL) {
- g_mutex_unlock (book->priv->mutex);
- return;
- }
-
- op->status = status;
- if (op->synchronous)
- e_flag_set (op->flag);
- else {
- op->book = g_object_ref (book);
- op->idle_id = g_idle_add (emit_async_generic_response, op);
- book->priv->pending_idles = g_list_prepend (book->priv->pending_idles,
- GINT_TO_POINTER (op->idle_id));
- }
-
- g_mutex_unlock (book->priv->mutex);
-}
-
-static gboolean
-e_book_idle_writable (gpointer data)
-{
- EBook *book = data;
- gboolean writable;
-
- g_mutex_lock (book->priv->mutex);
- writable = book->priv->writable;
- book->priv->writable_idle_id = 0;
- g_mutex_unlock (book->priv->mutex);
-
- g_signal_emit (G_OBJECT (book), e_book_signals [WRITABLE_STATUS], 0, writable);
-
- g_object_unref (book);
-
- return FALSE;
-}
-
-static gboolean
-e_book_idle_connection (gpointer data)
-{
- EBook *book = data;
- gboolean connected;
-
- if (!book->priv)
- return FALSE;
-
- g_mutex_lock (book->priv->mutex);
- connected = book->priv->connected;
- book->priv->connection_idle_id = 0;
- g_mutex_unlock (book->priv->mutex);
-
- g_signal_emit (G_OBJECT (book), e_book_signals [CONNECTION_STATUS], 0, connected);
-
- g_object_unref (book);
-
- return FALSE;
-}
-
-static gboolean
-e_book_idle_auth_required (gpointer data)
+e_book_async_remove_contact_by_id (EBook *book, const char *id, EBookCallback cb, gpointer closure)
{
- EBook *book = data;
- gboolean connected;
-
- if (!book->priv)
- return FALSE;
-
- g_mutex_lock (book->priv->mutex);
- connected = book->priv->connected;
- book->priv->auth_idle_id = 0;
- g_mutex_unlock (book->priv->mutex);
-
- g_signal_emit (G_OBJECT (book), e_book_signals [AUTH_REQUIRED], 0);
+ AsyncData *data;
+ const char *l[2];
- g_object_unref (book);
+ e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+ e_return_async_error_if_fail (id, E_BOOK_ERROR_INVALID_ARG);
- return FALSE;
+ l[0] = id;
+ l[1] = NULL;
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
+ org_gnome_evolution_dataserver_addressbook_Book_remove_contacts_async (book->priv->proxy, l, remove_contact_by_id_reply, data);
+ return 0;
}
-static void
-e_book_handle_response (EBookListener *listener, EBookListenerResponse *resp, EBook *book)
-{
- EContact *contact;
-
- switch (resp->op) {
- case CreateContactResponse:
- e_book_response_add_contact (book, resp->opid, resp->status, resp->id);
- break;
- case RemoveContactResponse:
- case ModifyContactResponse:
- case AuthenticationResponse:
- e_book_response_generic (book, resp->opid, resp->status);
- break;
- case GetContactResponse:
- contact = e_contact_new_from_vcard (resp->vcard);
- e_book_response_get_contact (book, resp->opid, resp->status, contact);
- break;
- case GetContactListResponse:
- e_book_response_get_contacts (book, resp->opid, resp->status, resp->list);
- break;
- case GetBookViewResponse:
- e_book_response_get_book_view(book, resp->opid, resp->status, resp->book_view);
- break;
- case GetChangesResponse:
- e_book_response_get_changes(book, resp->opid, resp->status, resp->list);
- break;
- case OpenBookResponse:
- e_book_response_open (book, resp->opid, resp->status);
- break;
- case RemoveBookResponse:
- e_book_response_remove (book, resp->opid, resp->status);
- break;
- case GetSupportedFieldsResponse:
- e_book_response_get_supported_fields (book, resp->opid, resp->status, resp->list);
- break;
- case GetRequiredFieldsResponse:
- e_book_response_get_required_fields (book, resp->opid, resp->status, resp->list);
- break;
- case GetSupportedAuthMethodsResponse:
- e_book_response_get_supported_auth_methods (book, resp->opid, resp->status, resp->list);
- break;
- case WritableStatusEvent:
- book->priv->writable = resp->writable;
-
- g_mutex_lock (book->priv->mutex);
- if (book->priv->writable_idle_id == 0) {
- g_object_ref (book);
- book->priv->writable_idle_id = g_idle_add (e_book_idle_writable, book);
- }
- g_mutex_unlock (book->priv->mutex);
-
- break;
- case LinkStatusEvent:
- book->priv->connected = resp->connected;
- g_mutex_lock (book->priv->mutex);
- if (book->priv->connection_idle_id == 0) {
- g_object_ref (book);
- book->priv->connection_idle_id = g_idle_add (e_book_idle_connection, book);
- }
- g_mutex_unlock (book->priv->mutex);
- break;
- case AuthRequiredEvent:
- g_mutex_lock (book->priv->mutex);
- if (book->priv->auth_idle_id == 0) {
- g_object_ref (book);
- book->priv->auth_idle_id = g_idle_add (e_book_idle_auth_required, book);
- }
- g_mutex_unlock (book->priv->mutex);
- break;
-
- default:
- g_error ("EBook: Unknown response code %d!\n",
- resp->op);
- }
-}
-
-
-
/**
- * e_book_unload_uri:
+ * e_book_remove_contacts:
* @book: an #EBook
- * @error: an #GError to set on failure
+ * @ids: an #GList of const char *id's
+ * @error: a #GError to set on failure
*
- * Unload the URI that this book had previously loaded.
+ * Removes the contacts with ids from the list @ids from @book. This is
+ * always more efficient than calling e_book_remove_contact_by_id if you
+ * have more than one id to remove, as some backends can implement it
+ * as a batch request.
*
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-static gboolean
-e_book_unload_uri (EBook *book,
- GError **error)
+ * Return value: %TRUE if successful, %FALSE otherwise
+ **/
+gboolean
+e_book_remove_contacts (EBook *book, GList *ids, GError **error)
{
- CORBA_Environment ev;
-
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (book->priv->load_state != E_BOOK_SOURCE_NOT_LOADED, E_BOOK_ERROR_SOURCE_NOT_LOADED, FALSE);
-
- if (book->priv->load_state == E_BOOK_SOURCE_LOADED) {
- /* Release the remote GNOME_Evolution_Addressbook_Book in the PAS. */
- CORBA_exception_init (&ev);
-
- bonobo_object_release_unref (book->priv->corba_book, &ev);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_book_unload_uri: Exception releasing "
- "remote book interface!\n");
- }
-
- CORBA_exception_free (&ev);
+ GError *err = NULL;
+ char **l;
- book->priv->corba_book = CORBA_OBJECT_NIL;
- e_book_listener_stop (book->priv->listener);
- bonobo_object_unref (BONOBO_OBJECT (book->priv->listener));
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+ e_return_error_if_fail (ids, E_BOOK_ERROR_INVALID_ARG);
- book->priv->listener = NULL;
- book->priv->load_state = E_BOOK_SOURCE_NOT_LOADED;
- g_free (book->priv->cap);
- book->priv->cap = NULL;
- book->priv->cap_queried = FALSE;
- book->priv->writable = FALSE;
- }
- else if (book->priv->load_state == E_BOOK_SOURCE_LOADING) {
- e_book_cancel (book, error);
- }
+ l = flatten_stringlist (ids);
- return TRUE;
+ org_gnome_evolution_dataserver_addressbook_Book_remove_contacts (book->priv->proxy, (const char **) l, &err);
+ g_free (l);
+ return unwrap_gerror (err, error);
}
-
-
-
-/* Set a flag for operation from the operation hash table */
static void
-find_key_value (gpointer key, gpointer value, gpointer data)
+remove_contacts_reply (DBusGProxy *proxy, GError *error, gpointer user_data)
{
- EBookOp *op;
+ AsyncData *data = user_data;
+ EBookCallback cb = data->callback;
- op = value;
+ if (cb)
+ cb (data->book, get_status_from_error (error), data->closure);
- if (op == NULL) {
- g_warning ("find_key_value: Cannot find operation ");
- return;
- }
-
- op->status = E_BOOK_ERROR_SOURCE_NOT_LOADED;
- if (op->synchronous)
- e_flag_set (op->flag);
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
/**
- * e_book_load_uri:
- */
-
-static void
-backend_died_cb (EComponentListener *cl, gpointer user_data)
-{
- EBook *book = (EBook *)user_data;
-
- d(printf ("backend_died_cb\n"));
-
- g_mutex_lock (book->priv->mutex);
- g_hash_table_foreach (book->priv->id_to_op, find_key_value, NULL);
- g_mutex_unlock (book->priv->mutex);
-
- book->priv->load_state = E_BOOK_SOURCE_NOT_LOADED;
- g_signal_emit (book, e_book_signals [BACKEND_DIED], 0);
-}
-
-static GList *
-activate_factories_for_uri (EBook *book, const char *uri)
-{
- CORBA_Environment ev;
- Bonobo_ServerInfoList *info_list = NULL;
- int i;
- char *query;
- GList *factories = NULL;
-
- query = "repo_ids.has ('IDL:GNOME/Evolution/DataServer/BookFactory:" API_VERSION "')";
-
- CORBA_exception_init (&ev);
-
- info_list = bonobo_activation_query (query, NULL, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- char *exc_text = bonobo_exception_get_text (&ev);
- g_warning ("Cannot perform bonobo-activation query for book factories: %s", exc_text);
- g_free (exc_text);
- CORBA_exception_free (&ev);
- goto done;
- return NULL;
- }
-
- if (info_list->_length == 0) {
- g_warning ("Can't find installed BookFactories");
- CORBA_exception_free (&ev);
- goto done;
- }
-
- CORBA_exception_free (&ev);
-
- for (i = 0; i < info_list->_length; i ++) {
- const Bonobo_ServerInfo *info;
- GNOME_Evolution_Addressbook_BookFactory factory;
-
- info = info_list->_buffer + i;
-
- factory = bonobo_activation_activate_from_id (info->iid, 0, NULL, NULL);
-
- if (factory == CORBA_OBJECT_NIL)
- g_warning ("e_book_construct: Could not obtain a handle "
- "to the Personal Addressbook Server with IID `%s'\n", info->iid);
- else
- factories = g_list_append (factories, factory);
- }
-
- done:
- if (info_list)
- CORBA_free (info_list);
-
- return factories;
-}
-
-/* XXX hm, should this function hold a lock on book->priv->mutex? It
- doesn't seem to require it, but there are unlocked writes to
- book->priv->load_state, which other functions read.. */
-static gboolean
-fetch_corba_book (EBook *book,
- ESource *source,
- GError **error)
+ * e_book_async_remove_contacts:
+ * @book: an #EBook
+ * @ids: a #GList of const char *id's
+ * @cb: a function to call when the operation finishes
+ * @closure: data to pass to callback function
+ *
+ * Removes the contacts with ids from the list @ids from @book. This is
+ * always more efficient than calling e_book_remove_contact_by_id() if you
+ * have more than one id to remove, as some backends can implement it
+ * as a batch request.
+ *
+ * Return value: %TRUE if successful, %FALSE otherwise
+ **/
+guint
+e_book_async_remove_contacts (EBook *book, GList *id_list, EBookCallback cb, gpointer closure)
{
- GNOME_Evolution_Addressbook_Book corba_book = CORBA_OBJECT_NIL;
- gchar *uri;
- gchar *source_xml;
- GList *factories;
- GList *l;
- gboolean rv = FALSE;
-
- uri = e_source_get_uri (source);
- if (!uri) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_OTHER_ERROR,
- _("%s: Invalid source."), "e_book_load_uri");
- return FALSE;
- }
-
- /* try to find a list of factories that can handle the protocol */
- factories = activate_factories_for_uri (book, uri);
- if (!factories) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_PROTOCOL_NOT_SUPPORTED,
- _("%s: no factories available for URI `%s'"), "e_book_load_uri", uri);
- return FALSE;
- }
-
-
- /*
- * Create our local BookListener interface.
- */
- book->priv->listener = e_book_listener_new ();
- if (book->priv->listener == NULL) {
- g_warning ("e_book_load_uri: Could not create EBookListener!\n");
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_OTHER_ERROR,
- _("%s: Could not create EBookListener"), "e_book_load_uri");
- return FALSE;
- }
- book->priv->listener_signal = g_signal_connect_object (book->priv->listener, "response",
- G_CALLBACK (e_book_handle_response),
- book, 0);
-
- g_free (book->priv->uri);
- book->priv->uri = uri;
-
- g_object_ref (source);
- if (book->priv->source)
- g_object_unref (book->priv->source);
- book->priv->source = source;
+ AsyncData *data;
+ char **l;
- source_xml = e_source_to_standalone_xml (source);
+ e_return_async_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
- for (l = factories; l; l = l->next) {
- GNOME_Evolution_Addressbook_BookFactory factory = l->data;
- CORBA_Environment ev;
+ if (id_list == NULL) {
+ if (cb)
+ cb (book, E_BOOK_ERROR_OK, closure);
+ return 0;
+ }
- CORBA_exception_init (&ev);
+ l = flatten_stringlist (id_list);
- corba_book = GNOME_Evolution_Addressbook_BookFactory_getBook (factory, source_xml,
- bonobo_object_corba_objref (BONOBO_OBJECT (book->priv->listener)),
- &ev);
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
- if (ev._major != CORBA_NO_EXCEPTION) {
- CORBA_exception_free (&ev);
- continue;
- }
- else if (corba_book != CORBA_OBJECT_NIL) {
- rv = TRUE;
- break;
- }
- }
-
- g_free (source_xml);
-
- /* free up the factories */
- for (l = factories; l; l = l->next)
- CORBA_Object_release ((CORBA_Object)l->data, NULL);
-
- g_list_free (factories);
-
- if (rv == TRUE) {
- book->priv->corba_book = corba_book;
- book->priv->comp_listener = e_component_listener_new (book->priv->corba_book);
- book->priv->died_signal = g_signal_connect (book->priv->comp_listener,
- "component_died",
- G_CALLBACK (backend_died_cb), book);
- }
- else {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_PROTOCOL_NOT_SUPPORTED,
- _("%s: no factories available for URI `%s'"), "e_book_new", uri);
- }
-
- return rv;
+ org_gnome_evolution_dataserver_addressbook_Book_remove_contacts_async (book->priv->proxy, (const char **) l, remove_contacts_reply, data);
+ g_free (l);
+ return 0;
}
/**
- * e_book_get_uri:
+ * e_book_get_book_view:
* @book: an #EBook
+ * @query: an #EBookQuery
+ * @requested_fields: a #GList containing the names of fields to return, or NULL for all
+ * @max_results: the maximum number of contacts to show (or 0 for all)
+ * @book_view: A #EBookView pointer, will be set to the view
+ * @error: a #GError to set on failure
*
- * Get the URI that this book has loaded. This string should not be freed.
+ * Query @book with @query, creating a #EBookView in @book_view with the fields
+ * specified by @requested_fields and limited at @max_results records. On an
+ * error, @error is set and %FALSE returned.
*
- * Return value: The URI.
- */
-const char *
-e_book_get_uri (EBook *book)
-{
- g_return_val_if_fail (book && E_IS_BOOK (book), NULL);
-
- return book->priv->uri;
+ * Return value: %TRUE if successful, %FALSE otherwise
+ **/
+gboolean
+e_book_get_book_view (EBook *book, EBookQuery *query, GList *requested_fields, int max_results, EBookView **book_view, GError **error)
+{
+ GError *err = NULL;
+ DBusGProxy *view_proxy;
+ char *sexp, *view_path;
+ gboolean ret = TRUE;
+
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+ sexp = e_book_query_to_string (query);
+
+ if (!org_gnome_evolution_dataserver_addressbook_Book_get_book_view (book->priv->proxy, sexp, max_results, &view_path, &err)) {
+ *book_view = NULL;
+ g_free (sexp);
+ return unwrap_gerror (err, error);
+ }
+ view_proxy = dbus_g_proxy_new_for_name_owner (connection,
+ E_DATA_BOOK_FACTORY_SERVICE_NAME, view_path,
+ "org.gnome.evolution.dataserver.addressbook.BookView", error);
+
+ if (view_proxy) {
+ *book_view = _e_book_view_new (book, view_proxy);
+ } else {
+ *book_view = NULL;
+ g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
+ "Cannot get connection to view");
+ ret = FALSE;
+ }
+
+ g_free (view_path);
+ g_free (sexp);
+
+ return ret;
}
-/**
- * e_book_get_source:
- * @book: an #EBook
- *
- * Get the #ESource that this book has loaded.
- *
- * Return value: The source.
- */
-ESource *
-e_book_get_source (EBook *book)
-{
- g_return_val_if_fail (book && E_IS_BOOK (book), NULL);
-
- return book->priv->source;
+static void
+get_book_view_reply (DBusGProxy *proxy, char *view_path, GError *error, gpointer user_data)
+{
+ AsyncData *data = user_data;
+ GError *err = NULL;
+ EBookView *view = NULL;
+ EBookBookViewCallback cb = data->callback;
+ DBusGProxy *view_proxy;
+ EBookStatus status;
+
+ if (view_path) {
+ view_proxy = dbus_g_proxy_new_for_name_owner (connection, E_DATA_BOOK_FACTORY_SERVICE_NAME, view_path,
+ "org.gnome.evolution.dataserver.addressbook.BookView", &err);
+ if (view_proxy) {
+ view = _e_book_view_new (data->book, view_proxy);
+ status = E_BOOK_ERROR_OK;
+ } else {
+ g_warning (G_STRLOC ": cannot get connection to view: %s", err->message);
+ g_error_free (err);
+ status = E_BOOK_ERROR_CORBA_EXCEPTION;
+ }
+ } else {
+ status = get_status_from_error (error);
+ }
+
+ if (cb)
+ cb (data->book, status, view, data->closure);
+
+ g_object_unref (data->book);
+ g_slice_free (AsyncData, data);
}
/**
- * e_book_get_static_capabilities:
+ * e_book_async_get_book_view:
* @book: an #EBook
- * @error: an #GError to set on failure
+ * @query: an #EBookQuery
+ * @requested_fields: a #GList containing the names of fields to return, or NULL for all
+ * @max_results: the maximum number of contacts to show (or 0 for all)
+ * @cb: a function to call when the operation finishes
+ * @closure: data to pass to callback function
*
- * Get the list of capabilities which the backend for this address book
- * supports. This string should not be freed.
+ * Query @book with @query, creating a #EBookView with the fields
+ * specified by @requested_fields and limited at @max_results records.
*
- * Return value: The capabilities list
- */
-const char *
-e_book_get_static_capabilities (EBook *book,
- GError **error)
+ * Return value: %FALSE if successful, %TRUE otherwise
+ **/
+guint
+e_book_async_get_book_view (EBook *book, EBookQuery *query, GList *requested_fields, int max_results, EBookBookViewCallback cb, gpointer closure)
{
- g_return_val_if_fail (book && E_IS_BOOK (book), NULL);
-
- if (!book->priv->cap_queried) {
- CORBA_Environment ev;
- char *temp;
-
- CORBA_exception_init (&ev);
+ AsyncData *data;
+ char *sexp;
- if (book->priv->load_state != E_BOOK_SOURCE_LOADED) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_SOURCE_NOT_LOADED,
- _("\"%s\" on book before \"%s\""),
- "e_book_get_static_capabilities", "e_book_open");
- return g_strdup ("");
- }
-
- temp = GNOME_Evolution_Addressbook_Book_getStaticCapabilities(book->priv->corba_book, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CORBA_EXCEPTION,
- _("CORBA exception making \"%s\" call"),
- "Book::getStaticCapabilities");
- CORBA_exception_free (&ev);
- return g_strdup ("");
- }
-
- book->priv->cap = g_strdup(temp);
- book->priv->cap_queried = TRUE;
-
- CORBA_free(temp);
-
- CORBA_exception_free (&ev);
- }
-
- return book->priv->cap;
-}
-
-/**
- * e_book_check_static_capability:
- * @book: an #EBook
- * @cap: A capability string
- *
- * Check to see if the backend for this address book supports the capability
- * @cap.
- *
- * Return value: %TRUE if the backend supports @cap, %FALSE otherwise.
- */
-gboolean
-e_book_check_static_capability (EBook *book,
- const char *cap)
-{
- const char *caps;
+ e_return_async_error_val_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_async_error_val_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+ e_return_async_error_val_if_fail (query, E_BOOK_ERROR_INVALID_ARG);
- g_return_val_if_fail (book && E_IS_BOOK (book), FALSE);
+ data = g_slice_new0 (AsyncData);
+ data->book = g_object_ref (book);
+ data->callback = cb;
+ data->closure = closure;
- caps = e_book_get_static_capabilities (book, NULL);
+ sexp = e_book_query_to_string (query);
- /* XXX this is an inexact test but it works for our use */
- if (caps && strstr (caps, cap))
- return TRUE;
+ org_gnome_evolution_dataserver_addressbook_Book_get_book_view_async (book->priv->proxy, sexp, max_results, get_book_view_reply, data);
- return FALSE;
+ g_free (sexp);
+ return 0;
}
/**
@@ -3515,28 +1781,24 @@ e_book_check_static_capability (EBook *book,
gboolean
e_book_is_opened (EBook *book)
{
- g_return_val_if_fail (E_IS_BOOK (book), FALSE);
+ g_return_val_if_fail (E_IS_BOOK (book), FALSE);
- if (book->priv->load_state != E_BOOK_SOURCE_LOADED)
- return FALSE;
-
- return TRUE;
+ return book->priv->loaded;
}
/**
* e_book_is_writable:
* @book: an #EBook
- *
+ *
* Check if this book is writable.
- *
+ *
* Return value: %TRUE if this book is writable, otherwise %FALSE.
*/
gboolean
e_book_is_writable (EBook *book)
{
- g_return_val_if_fail (book && E_IS_BOOK (book), FALSE);
-
- return book->priv->writable;
+ g_return_val_if_fail (E_IS_BOOK (book), FALSE);
+ return book->priv->writable;
}
/**
@@ -3547,13 +1809,84 @@ e_book_is_writable (EBook *book)
*
* Return value: %TRUE if this book is connected, otherwise %FALSE.
**/
-gboolean
+gboolean
e_book_is_online (EBook *book)
{
- g_return_val_if_fail (book && E_IS_BOOK (book), FALSE);
+ g_return_val_if_fail (E_IS_BOOK (book), FALSE);
+
+ return book->priv->connected;
+}
+
+/**
+ * e_book_cancel:
+ * @book: an #EBook
+ * @error: a #GError to set on failure
+ *
+ * Used to cancel an already running operation on @book. This
+ * function makes a synchronous CORBA to the backend telling it to
+ * cancel the operation. If the operation wasn't cancellable (either
+ * transiently or permanently) or had already comopleted on the server
+ * side, this function will return E_BOOK_STATUS_COULD_NOT_CANCEL, and
+ * the operation will continue uncancelled. If the operation could be
+ * cancelled, this function will return E_BOOK_ERROR_OK, and the
+ * blocked e_book function corresponding to current operation will
+ * return with a status of E_BOOK_STATUS_CANCELLED.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise
+ **/
+gboolean
+e_book_cancel (EBook *book, GError **error)
+{
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+ return org_gnome_evolution_dataserver_addressbook_Book_cancel_operation (book->priv->proxy, error);
+}
+
+/**
+ * e_book_get_uri:
+ * @book: an #EBook
+ *
+ * Get the URI that this book has loaded. This string should not be freed.
+ *
+ * Return value: The URI.
+ */
+const char *
+e_book_get_uri (EBook *book)
+{
+ g_return_val_if_fail (E_IS_BOOK (book), NULL);
- return book->priv->connected;
+ return book->priv->uri;
+}
+
+/**
+ * e_book_get_static_capabilities:
+ * @book: an #EBook
+ * @error: an #GError to set on failure
+ *
+ * Get the list of capabilities which the backend for this address book
+ * supports. This string should not be freed.
+ *
+ * Return value: The capabilities list
+ */
+const char *
+e_book_get_static_capabilities (EBook *book, GError **error)
+{
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->proxy, E_BOOK_ERROR_REPOSITORY_OFFLINE);
+
+ if (!book->priv->cap_queried) {
+ char *cap = NULL;
+
+ if (!org_gnome_evolution_dataserver_addressbook_Book_get_static_capabilities (book->priv->proxy, &cap, error)) {
+ return NULL;
+ }
+ book->priv->cap = cap;
+ book->priv->cap_queried = TRUE;
+ }
+
+ return book->priv->cap;
}
#define SELF_UID_KEY "/apps/evolution/addressbook/self/self_uid"
@@ -3572,25 +1905,18 @@ e_book_is_online (EBook *book)
gboolean
e_book_get_self (EContact **contact, EBook **book, GError **error)
{
- GError *e = NULL;
GConfClient *gconf;
gboolean status;
char *uid;
- *book = e_book_new_system_addressbook (&e);
+ *book = e_book_new_system_addressbook (error);
if (!*book) {
- if (error)
- g_propagate_error (error, e);
return FALSE;
}
- status = e_book_open (*book, FALSE, &e);
+ status = e_book_open (*book, FALSE, error);
if (status == FALSE) {
- g_object_unref (*book);
- *book = NULL;
- if (error)
- g_propagate_error (error, e);
return FALSE;
}
@@ -3602,21 +1928,16 @@ e_book_get_self (EContact **contact, EBook **book, GError **error)
g_object_unref (*book);
*book = NULL;
g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_NO_SELF_CONTACT,
- _("%s: there was no self contact UID stored in gconf"), "e_book_get_self");
+ _("%s: there was no self contact uid stored in gconf"), "e_book_get_self");
return FALSE;
}
- if (!e_book_get_contact (*book, uid, contact, &e)) {
+ if (!e_book_get_contact (*book, uid, contact, error)) {
g_object_unref (*book);
*book = NULL;
- g_free (uid);
- if (error)
- g_propagate_error (error, e);
return FALSE;
}
- g_free (uid);
-
return TRUE;
}
@@ -3636,8 +1957,8 @@ e_book_set_self (EBook *book, EContact *contact, GError **error)
{
GConfClient *gconf;
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (contact && E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG, FALSE);
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (E_IS_CONTACT (contact), E_BOOK_ERROR_INVALID_ARG);
gconf = gconf_client_get_default();
gconf_client_set_string (gconf, SELF_UID_KEY, e_contact_get_const (contact, E_CONTACT_UID), NULL);
@@ -3676,29 +1997,27 @@ e_book_is_self (EContact *contact)
return rv;
}
-
-
/**
* e_book_set_default_addressbook:
* @book: An #EBook pointer
* @error: A #GError pointer
- *
+ *
* sets the #ESource of the #EBook as the "default" addressbook. This is the source
* that will be loaded in the e_book_get_default_addressbook call.
- *
+ *
* Return value: %TRUE if the setting was stored in libebook's ESourceList, otherwise %FALSE.
*/
gboolean
e_book_set_default_addressbook (EBook *book, GError **error)
{
- ESource *source;
-
- e_return_error_if_fail (book && E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG, FALSE);
- e_return_error_if_fail (book->priv->load_state == E_BOOK_SOURCE_NOT_LOADED, E_BOOK_ERROR_SOURCE_ALREADY_LOADED, FALSE);
-
- source = e_book_get_source (book);
-
- return e_book_set_default_source (source, error);
+ ESource *source;
+
+ e_return_error_if_fail (E_IS_BOOK (book), E_BOOK_ERROR_INVALID_ARG);
+ e_return_error_if_fail (book->priv->loaded == FALSE, E_BOOK_ERROR_SOURCE_ALREADY_LOADED);
+
+ source = e_book_get_source (book);
+
+ return e_book_set_default_source (source, error);
}
@@ -3706,10 +2025,10 @@ e_book_set_default_addressbook (EBook *book, GError **error)
* e_book_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_get_default_addressbook call.
- *
+ *
* Return value: %TRUE if the setting was stored in libebook's ESourceList, otherwise %FALSE.
*/
gboolean
@@ -3717,16 +2036,13 @@ e_book_set_default_source (ESource *source, GError **error)
{
ESourceList *sources;
const char *uid;
- GError *err = NULL;
GSList *g;
- e_return_error_if_fail (source && E_IS_SOURCE (source), E_BOOK_ERROR_INVALID_ARG, FALSE);
+ e_return_error_if_fail (source && E_IS_SOURCE (source), E_BOOK_ERROR_INVALID_ARG);
uid = e_source_peek_uid (source);
- if (!e_book_get_addressbooks (&sources, &err)) {
- if (error)
- g_propagate_error (error, err);
+ if (!e_book_get_addressbooks (&sources, error)) {
return FALSE;
}
@@ -3753,9 +2069,7 @@ e_book_set_default_source (ESource *source, GError **error)
/* set the "default" property on the source */
e_source_set_property (source, "default", "true");
- if (!e_source_list_sync (sources, &err)) {
- if (error)
- g_propagate_error (error, err);
+ if (!e_source_list_sync (sources, error)) {
return FALSE;
}
@@ -3763,413 +2077,123 @@ e_book_set_default_source (ESource *source, GError **error)
}
/**
- * e_book_get_addressbooks:
- * @addressbook_sources: A pointer to a ESourceList* to set
- * @error: A pointer to a GError* to set on error
+ * e_book_check_static_capability:
+ * @book: an #EBook
+ * @cap: A capability string
*
- * Populate *addressbook_sources with the list of all sources which have been
- * added to Evolution.
+ * Check to see if the backend for this address book supports the capability
+ * @cap.
*
- * Return value: %TRUE if @addressbook_sources was set, otherwise %FALSE.
+ * Return value: %TRUE if the backend supports @cap, %FALSE otherwise.
*/
gboolean
-e_book_get_addressbooks (ESourceList **addressbook_sources, GError **error)
-{
- GConfClient *gconf;
-
- e_return_error_if_fail (addressbook_sources, E_BOOK_ERROR_INVALID_ARG, FALSE);
-
- gconf = gconf_client_get_default();
- *addressbook_sources = e_source_list_new_for_gconf (gconf, "/apps/evolution/addressbook/sources");
- g_object_unref (gconf);
-
- return TRUE;
-}
-
-
-static void*
-startup_mainloop (void *arg)
-{
- GMainLoop *loop = g_main_loop_new (_ebook_context, FALSE);
- g_main_loop_run (loop);
- return NULL;
-}
-
-/* one-time start up for libebook */
-static void
-e_book_activate(void)
-{
- static GStaticMutex e_book_lock = G_STATIC_MUTEX_INIT;
- static gboolean activated = FALSE;
-
- g_static_mutex_lock (&e_book_lock);
- if (!activated) {
- GThread *ebook_mainloop_thread;
- activated = TRUE;
-
- _ebook_context = g_main_context_new ();
-
- if (!bonobo_is_initialized ())
- bonobo_init (NULL, NULL);
-
- ebook_mainloop_thread = g_thread_create(startup_mainloop, NULL, FALSE, NULL);
- }
- g_static_mutex_unlock (&e_book_lock);
-}
-
-
-/**
- * e_book_new:
- * @source: An #ESource pointer
- * @error: A #GError pointer
- *
- * Creates a new #EBook corresponding to the given source. There are
- * only two operations that are valid on this book at this point:
- * e_book_open(), and e_book_remove().
- *
- * Return value: a new but unopened #EBook.
- */
-EBook*
-e_book_new (ESource *source, GError **error)
+e_book_check_static_capability (EBook *book, const char *cap)
{
- EBook *book;
-
- e_return_error_if_fail (source && E_IS_SOURCE (source), E_BOOK_ERROR_INVALID_ARG, NULL);
+ const char *caps;
- e_book_activate ();
+ g_return_val_if_fail (E_IS_BOOK (book), FALSE);
- book = g_object_new (E_TYPE_BOOK, NULL);
+ caps = e_book_get_static_capabilities (book, NULL);
- book->priv->source = g_object_ref (source);
+ /* XXX this is an inexact test but it works for our use */
+ if (caps && strstr (caps, cap))
+ return TRUE;
- if (!fetch_corba_book (book, source, error)) {
- g_object_unref (book);
- return NULL;
- }
-
- return book;
+ return FALSE;
}
/**
- * e_book_new_from_uri:
- * @uri: the URI to load
- * @error: A #GError pointer
- *
- * Creates a new #EBook corresponding to the given uri. See the
- * documentation for e_book_new for further information.
- *
- * Return value: a new but unopened #EBook.
+ * 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.
*/
-EBook*
-e_book_new_from_uri (const char *uri, GError **error)
-{
- ESourceGroup *group;
- ESource *source;
- EBook *book;
-
- e_return_error_if_fail (uri, E_BOOK_ERROR_INVALID_ARG, NULL);
-
- group = e_source_group_new ("", uri);
- source = e_source_new ("", "");
- e_source_set_group (source, group);
- e_source_set_relative_uri (source, NULL);
-
- book = e_book_new (source, error);
-
- g_object_unref (source);
- g_object_unref (group);
-
- return book;
+static gboolean
+unwrap_gerror (GError *error, GError **client_error)
+{
+ if (error == NULL)
+ return TRUE;
+
+ if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) {
+ GError *new;
+ gint code;
+ if (client_error) {
+ code = get_status_from_error (error);
+ new = g_error_new_literal (E_BOOK_ERROR, code, error->message);
+ *client_error = new;
+ }
+ g_error_free (error);
+ } else {
+ if (client_error)
+ *client_error = error;
+ }
+ return FALSE;
}
/**
- * e_book_new_system_addressbook:
- * @error: A #GError pointer
- *
- * Creates a new #EBook corresponding to the user's system
- * addressbook. See the documentation for e_book_new for further
- * information.
- *
- * Return value: a new but unopened #EBook.
+ * If the GError is a remote error, extract the EBookStatus embedded inside.
+ * Otherwise return CORBA_EXCEPTION (I know this is DBus...).
*/
-EBook*
-e_book_new_system_addressbook (GError **error)
-{
- ESourceList *sources;
- GSList *g;
- GError *err = NULL;
- ESource *system_source = NULL;
- EBook *book;
-
- if (!e_book_get_addressbooks (&sources, &err)) {
- if (error)
- g_propagate_error (error, err);
- return 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 (e_source_get_property (source, "system")) {
- system_source = source;
- break;
- }
- }
-
- if (system_source)
- break;
- }
-
- if (system_source) {
- book = e_book_new (system_source, &err);
- }
- else {
- char *filename;
- char *uri;
-
- filename = g_build_filename (g_get_home_dir(),
- ".evolution/addressbook/local/system",
- NULL);
- uri = g_filename_to_uri (filename, NULL, NULL);
-
- g_free (filename);
-
- book = e_book_new_from_uri (uri, error);
-
- g_free (uri);
- }
-
- if (!book) {
- if (error)
- g_propagate_error (error, err);
- }
-
- g_object_unref (sources);
-
- return book;
+static EBookStatus
+get_status_from_error (GError *error)
+{
+ if G_LIKELY (error == NULL)
+ return E_BOOK_ERROR_OK;
+ if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) {
+ const char *name;
+ name = dbus_g_error_get_name (error);
+ if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.contactnotfound") == 0) {
+ return E_BOOK_ERROR_CONTACT_NOT_FOUND;
+ } else if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.invalidquery") == 0) {
+ return E_BOOK_ERROR_INVALID_ARG;
+ } else if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.cancelled") == 0) {
+ return E_BOOK_ERROR_CANCELLED;
+ } else if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.permissiondenied") == 0) {
+ return E_BOOK_ERROR_PERMISSION_DENIED;
+ } else if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.nospace") == 0) {
+ return E_BOOK_ERROR_NO_SPACE;
+ } else if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.repositoryoffline") == 0) {
+ return E_BOOK_ERROR_REPOSITORY_OFFLINE;
+ } else if (strcmp (name, "org.gnome.evolution.dataserver.addressbook.Book.othererror") == 0) {
+ return E_BOOK_ERROR_OTHER_ERROR;
+ } else {
+ g_warning (G_STRLOC ": unmatched error name %s", name);
+ return E_BOOK_ERROR_OTHER_ERROR;
+ }
+ } else {
+ /* In this case the error was caused by DBus. Dump the message to the
+ console as otherwise we have no idea what the problem is. */
+ g_warning ("DBus error: %s", error->message);
+ return E_BOOK_ERROR_CORBA_EXCEPTION;
+ }
}
/**
- * e_book_new_default_addressbook:
- * @error: A #GError pointer
- *
- * Creates a new #EBook corresponding to the user's default
- * addressbook. See the documentation for e_book_new for further
- * information.
- *
- * Return value: a new but unopened #EBook.
+ * Turn a GList of strings into an array of strings.
*/
-EBook*
-e_book_new_default_addressbook (GError **error)
-{
- ESourceList *sources;
- GSList *g;
- GError *err = NULL;
- ESource *default_source = NULL;
- EBook *book;
-
- if (!e_book_get_addressbooks (&sources, &err)) {
- if (error)
- g_propagate_error (error, err);
- return 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 (e_source_get_property (source, "default")) {
- default_source = source;
- break;
- }
- }
-
- if (default_source)
- break;
- }
-
- if (default_source)
- book = e_book_new (default_source, &err);
- else
- book = e_book_new_system_addressbook (&err);
-
- if (!book) {
- if (error)
- g_propagate_error (error, err);
- }
-
- g_object_unref (sources);
-
- return book;
-}
-
-static void
-kill_remaining_ops (gpointer key, gpointer value, gpointer user_data)
-{
- EBookOp *op = value;
- EBook *book = user_data;
-
- if (!op)
- return;
-
- find_key_value (key, value, NULL);
- e_book_clear_op (book, op);
-}
-
-static void
-e_book_init (EBook *book)
-{
- book->priv = g_new0 (EBookPrivate, 1);
- book->priv->load_state = E_BOOK_SOURCE_NOT_LOADED;
- book->priv->uri = NULL;
- book->priv->source = NULL;
- book->priv->mutex = g_mutex_new ();
- book->priv->id_to_op = g_hash_table_new (g_int_hash, g_int_equal);
- book->priv->current_op_id = 1;
-}
-
-static void
-e_book_dispose (GObject *object)
-{
- EBook *book = E_BOOK (object);
-
- if (book->priv) {
- if (book->priv->comp_listener) {
- g_signal_handler_disconnect (book->priv->comp_listener, book->priv->died_signal);
- g_object_unref (book->priv->comp_listener);
- book->priv->comp_listener = NULL;
- }
-
- if (book->priv->load_state == E_BOOK_SOURCE_LOADED)
- e_book_unload_uri (book, NULL);
-
- if (book->priv->corba_book) {
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
- bonobo_object_release_unref (book->priv->corba_book, &ev);
- if (ev._major != CORBA_NO_EXCEPTION)
- g_warning ("%s: Exception releasing remote book interface!\n", G_STRFUNC);
- CORBA_exception_free (&ev);
- }
-
- if (book->priv->listener) {
- e_book_listener_stop (book->priv->listener);
-
- /* GLib bug compatibility */
- if (g_signal_handler_is_connected (book->priv->listener, book->priv->listener_signal))
- g_signal_handler_disconnect (book->priv->listener, book->priv->listener_signal);
- bonobo_object_unref (book->priv->listener);
- book->priv->listener = NULL;
- }
-
- g_free (book->priv->cap);
-
- g_free (book->priv->uri);
-
- if (book->priv->source)
- g_object_unref (book->priv->source);
-
- g_mutex_lock (book->priv->mutex);
- g_hash_table_foreach (book->priv->id_to_op, kill_remaining_ops, book);
- g_hash_table_destroy (book->priv->id_to_op);
- g_mutex_unlock (book->priv->mutex);
-
- g_mutex_free (book->priv->mutex);
-
- if (book->priv->connection_idle_id)
- g_source_remove (book->priv->connection_idle_id);
-
- if (book->priv->auth_idle_id)
- g_source_remove (book->priv->auth_idle_id);
-
- if (book->priv->writable_idle_id)
- g_source_remove (book->priv->writable_idle_id);
-
- g_free (book->priv);
- book->priv = NULL;
- }
-
- if (G_OBJECT_CLASS (parent_class)->dispose)
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-e_book_class_init (EBookClass *klass)
+static char **
+flatten_stringlist (GList *list)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- parent_class = g_type_class_ref (G_TYPE_OBJECT);
-
- e_book_signals [WRITABLE_STATUS] =
- g_signal_new ("writable_status",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookClass, writable_status),
- NULL, NULL,
- g_cclosure_marshal_VOID__BOOLEAN,
- G_TYPE_NONE, 1,
- G_TYPE_BOOLEAN);
-
- e_book_signals [CONNECTION_STATUS] =
- g_signal_new ("connection_status",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookClass, connection_status),
- NULL, NULL,
- g_cclosure_marshal_VOID__BOOLEAN,
- G_TYPE_NONE, 1,
- G_TYPE_BOOLEAN);
-
- e_book_signals [AUTH_REQUIRED] =
- g_signal_new ("auth_required",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookClass, auth_required),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- e_book_signals [BACKEND_DIED] =
- g_signal_new ("backend_died",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EBookClass, backend_died),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- object_class->dispose = e_book_dispose;
+ char **array = g_new0 (char *, g_list_length (list) + 1);
+ GList *l = list;
+ int i = 0;
+ while (l != NULL) {
+ array[i++] = l->data;
+ l = l->next;
+ }
+ return array;
}
/**
- * e_book_get_type:
+ * Turn an array of strings into a GList.
*/
-GType
-e_book_get_type (void)
-{
- static GType type = 0;
-
- if (! type) {
- GTypeInfo info = {
- sizeof (EBookClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) e_book_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (EBook),
- 0, /* n_preallocs */
- (GInstanceInitFunc) e_book_init
- };
-
- type = g_type_register_static (G_TYPE_OBJECT, "EBook", &info, 0);
- }
-
- return type;
+static GList *
+array_to_stringlist (char **list)
+{
+ GList *l = NULL;
+ char **i = list;
+ while (*i != NULL) {
+ l = g_list_prepend (l, (*i++));
+ }
+ g_free (list);
+ return g_list_reverse(l);
}
diff --git a/addressbook/libebook/e-book.h b/addressbook/libebook/e-book.h
index 8234572..d963dda 100644
--- a/addressbook/libebook/e-book.h
+++ b/addressbook/libebook/e-book.h
@@ -1,11 +1,23 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * The Evolution addressbook client object.
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
*
- * Author:
- * Chris Toshok (toshok 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.
*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Ross Burton <ross linux intel com>
*/
#ifndef __E_BOOK_H__
@@ -241,9 +253,6 @@ gboolean e_book_is_online (EBook *book);
gboolean e_book_cancel (EBook *book,
GError **error);
-gboolean e_book_cancel_async_op (EBook *book,
- GError **error);
-
/* Identity */
gboolean e_book_get_self (EContact **contact, EBook **book, GError **error);
gboolean e_book_set_self (EBook *book, EContact *contact, GError **error);
diff --git a/addressbook/libebook/e-error.h b/addressbook/libebook/e-error.h
new file mode 100644
index 0000000..5d137f0
--- /dev/null
+++ b/addressbook/libebook/e-error.h
@@ -0,0 +1,40 @@
+#define e_return_error_if_fail(expr,error_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__, \
+ __PRETTY_FUNCTION__, \
+ #expr); \
+ g_set_error (error, E_BOOK_ERROR, (error_code), \
+ "file %s: line %d (%s): assertion `%s' failed", \
+ __FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, \
+ #expr); \
+ return FALSE; \
+ }; }G_STMT_END
+
+
+#define e_return_async_error_if_fail(expr, error) 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__, __PRETTY_FUNCTION__, #expr); \
+ cb (book, error, closure); \
+ return 0; \
+ } \
+ } G_STMT_END \
+
+#define e_return_async_error_val_if_fail(expr, error) 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__, __PRETTY_FUNCTION__, #expr); \
+ cb (book, error, NULL, closure); \
+ return 0; \
+ } \
+ } G_STMT_END \
+
diff --git a/addressbook/libebook/libebook.pc.in b/addressbook/libebook/libebook.pc.in
index 49a497a..3d098d5 100644
--- a/addressbook/libebook/libebook.pc.in
+++ b/addressbook/libebook/libebook.pc.in
@@ -5,14 +5,11 @@ includedir= includedir@
datarootdir= datarootdir@
datadir= datadir@
-idldir= idldir@
-IDL_INCLUDES=-I${idldir} @IDL_INCLUDES@
-
privincludedir= privincludedir@
Name: libebook
Description: Client library for evolution address books
Version: @VERSION@
-Requires: libbonobo-2.0 >= @LIBBONOBO_REQUIRED@ libedataserver-1.2
+Requires: libedataserver-1.2 dbus-glib-1
Libs: -L${libdir} -lebook-1.2
Cflags: -I${privincludedir}
diff --git a/addressbook/libedata-book/Makefile.am b/addressbook/libedata-book/Makefile.am
index 2865c39..45f0cb3 100644
--- a/addressbook/libedata-book/Makefile.am
+++ b/addressbook/libedata-book/Makefile.am
@@ -1,62 +1,52 @@
INCLUDES = \
-DG_LOG_DOMAIN=\"libedata-book\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
-I$(top_srcdir) \
-I$(top_builddir) \
-I$(top_srcdir)/addressbook \
-I$(top_builddir)/addressbook \
- $(DB_CFLAGS) \
- $(EVOLUTION_ADDRESSBOOK_CFLAGS)
+ $(EVOLUTION_ADDRESSBOOK_CFLAGS) \
+ -DDBUS_API_SUBJECT_TO_CHANGE
-# The corba stubs and skels
-CORBA_GENERATED_C = \
- Evolution-DataServer-Addressbook-common.c \
- Evolution-DataServer-Addressbook-skels.c \
- Evolution-DataServer-Addressbook-stubs.c
-CORBA_GENERATED_H = \
- Evolution-DataServer-Addressbook.h
-
-CORBA_GENERATED = $(CORBA_GENERATED_C) $(CORBA_GENERATED_H)
+# The library
+lib_LTLIBRARIES = libedata-book-1.2.la
-idls = \
- $(srcdir)/../idl/Evolution-DataServer-Addressbook.idl
+DBUS_GENERATED_H = e-data-book-glue.h e-data-book-factory-glue.h e-data-book-view-glue.h
-idl_flags = $(IDL_INCLUDES)
+include glib-gen.mak
+glib_enum_headers=e-data-book-types.h
+glib_enum_define=E_DATA_BOOK
+glib_enum_prefix=e_data_book
-$(CORBA_GENERATED_H): $(idls)
- $(ORBIT_IDL) $(idl_flags) $(srcdir)/../idl/Evolution-DataServer-Addressbook.idl
-$(CORBA_GENERATED_C): $(CORBA_GENERATED_H)
-
-# The library
-lib_LTLIBRARIES = libedata-book-1.2.la
+ENUM_GENERATED = e-data-book-enumtypes.h e-data-book-enumtypes.c
libedata_book_1_2_la_SOURCES = \
- $(CORBA_GENERATED_C) \
+ $(DBUS_GENERATED_H) \
e-book-backend-factory.c \
e-book-backend-sexp.c \
e-book-backend-summary.c \
e-book-backend-cache.c \
- e-book-backend-db-cache.c \
- e-book-backend-sync.c \
e-book-backend.c \
- e-data-book-factory.c \
e-data-book-view.c \
e-data-book.c \
- ximian-vcard.h
+ ximian-vcard.h \
+ e-book-backend-sync.c \
+ opid.c opid.h \
+ $(ENUM_GENERATED)
libedata_book_1_2_la_LIBADD = \
- $(top_builddir)/addressbook/libebook/libebook-1.2.la \
- $(top_builddir)/libedataserver/libedataserver-1.2.la \
- $(top_builddir)/libebackend/libebackend-1.2.la \
- $(DB_LIBS) \
- $(EVOLUTION_ADDRESSBOOK_LIBS)
+ $(EVOLUTION_ADDRESSBOOK_LIBS) \
+ $(top_builddir)/addressbook/libebook/libebook-$(API_VERSION).la \
+ $(top_builddir)/libedataserver/libedataserver-$(API_VERSION).la \
+ $(top_builddir)/libebackend/libebackend-$(API_VERSION).la
+
+libedata_book_1_2_la_LDFLAGS = \
+ -version-info $(LIBEDATABOOK_CURRENT):$(LIBEDATABOOK_REVISION):$(LIBEDATABOOK_AGE)
-libedata_book_1_2_la_LDFLAGS = \
- -version-info $(LIBEDATABOOK_CURRENT):$(LIBEDATABOOK_REVISION):$(LIBEDATABOOK_AGE) $(NO_UNDEFINED)
libedata_bookincludedir = $(privincludedir)/libedata-book
libedata_bookinclude_HEADERS = \
- $(CORBA_GENERATED_H) \
e-book-backend-factory.h \
e-book-backend-sexp.h \
e-book-backend-summary.h \
@@ -66,8 +56,7 @@ libedata_bookinclude_HEADERS = \
e-data-book-types.h \
e-data-book-view.h \
e-data-book.h \
- e-book-backend-cache.h \
- e-book-backend-db-cache.h
+ e-book-backend-cache.h
%-$(API_VERSION).pc: %.pc
cp $< $@
@@ -75,12 +64,37 @@ libedata_bookinclude_HEADERS = \
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libedata-book-$(API_VERSION).pc
-BUILT_SOURCES = $(CORBA_GENERATED)
-CLEANFILES = $(BUILT_SOURCES)
+service_in_files = org.gnome.evolution.dataserver.AddressBook.service.in
+servicedir = $(datadir)/dbus-1/services
+service_DATA = $(service_in_files:.service.in=.service)
+ EVO_SUBST_SERVICE_RULE@
+
+BUILT_SOURCES = $(DBUS_GENERATED_H)
+CLEANFILES = $(BUILT_SOURCES) $(service_DATA)
DISTCLEANFILES = $(pkgconfig_DATA)
EXTRA_DIST = \
- $(pkgconfig_DATA:-$(API_VERSION).pc=.pc.in)
+ e-data-book-factory.xml \
+ e-data-book-view.xml \
+ e-data-book.xml \
+ $(pkgconfig_DATA:-$(API_VERSION).pc=.pc.in) \
+ $(service_in_files)
dist-hook:
cd $(distdir); rm -f $(BUILT_SOURCES)
+
+%-glue.h: %.xml
+ dbus-binding-tool --mode=glib-server --output=$@ --prefix=$(subst -,_,$*) $^
+
+%-bindings.h: %.xml
+ dbus-binding-tool --mode=glib-client --output=$@ --prefix=$(subst -,_,$*) $^
+
+
+DBUS_BINDINGS = e-data-book-factory-bindings.h e-data-book-bindings.h e-data-book-view-bindings.h
+BUILT_SOURCES += $(DBUS_BINDINGS) $(ENUM_GENERATED)
+
+factorydir = $(libexecdir)
+factory_PROGRAMS = e-addressbook-factory
+
+e_addressbook_factory_SOURCES = e-data-book-factory.c e-data-book-factory.h
+e_addressbook_factory_LDADD = libedata-book-1.2.la
diff --git a/addressbook/libedata-book/e-book-backend-sync.h b/addressbook/libedata-book/e-book-backend-sync.h
index 6e59aa9..f44eaaa 100644
--- a/addressbook/libedata-book/e-book-backend-sync.h
+++ b/addressbook/libedata-book/e-book-backend-sync.h
@@ -6,7 +6,6 @@
#define __E_BOOK_BACKEND_SYNC_H__
#include <glib.h>
-#include <libedata-book/Evolution-DataServer-Addressbook.h>
#include <libedata-book/e-data-book-types.h>
#include <libedata-book/e-book-backend.h>
diff --git a/addressbook/libedata-book/e-book-backend.c b/addressbook/libedata-book/e-book-backend.c
index fa79ca3..d33d13b 100644
--- a/addressbook/libedata-book/e-book-backend.c
+++ b/addressbook/libedata-book/e-book-backend.c
@@ -9,6 +9,7 @@
#include <config.h>
#include "e-data-book-view.h"
+#include "e-data-book.h"
#include "e-book-backend.h"
struct _EBookBackendPrivate {
@@ -571,12 +572,7 @@ e_book_backend_add_client (EBookBackend *backend,
g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), FALSE);
g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
- bonobo_object_set_immortal (BONOBO_OBJECT (book), TRUE);
-
g_object_weak_ref (G_OBJECT (book), book_destroy_cb, backend);
-
- ORBit_small_listen_for_broken (e_data_book_get_listener (book), G_CALLBACK (listener_died_cb), book);
-
g_mutex_lock (backend->priv->clients_mutex);
backend->priv->clients = g_list_prepend (backend->priv->clients, book);
g_mutex_unlock (backend->priv->clients_mutex);
@@ -629,29 +625,7 @@ e_book_backend_remove_client (EBookBackend *backend,
gboolean
e_book_backend_has_out_of_proc_clients (EBookBackend *backend)
{
- GList *l;
-
- g_mutex_lock (backend->priv->clients_mutex);
-
- if (!backend->priv->clients) {
- g_mutex_unlock (backend->priv->clients_mutex);
-
- return FALSE;
- }
-
- for (l = backend->priv->clients; l; l = l->next) {
- if (ORBit_small_get_connection_status (e_data_book_get_listener (l->data)) != ORBIT_CONNECTION_IN_PROC) {
- g_mutex_unlock (backend->priv->clients_mutex);
-
- return TRUE;
- }
- }
-
- g_mutex_unlock (backend->priv->clients_mutex);
-
- /* If we get here, all remaining clients are in proc */
-
- return FALSE;
+ return TRUE;
}
/**
@@ -815,12 +789,12 @@ e_book_backend_sync (EBookBackend *backend)
*
* Return value: A new #GNOME_Evolution_Addressbook_BookChangeItem.
**/
-GNOME_Evolution_Addressbook_BookChangeItem*
+EDataBookChange *
e_book_backend_change_add_new (const char *vcard)
{
- GNOME_Evolution_Addressbook_BookChangeItem* new_change = GNOME_Evolution_Addressbook_BookChangeItem__alloc();
+ EDataBookChange *new_change = g_new (EDataBookChange, 1);
- new_change->changeType= GNOME_Evolution_Addressbook_ContactAdded;
+ new_change->change_type = E_DATA_BOOK_BACKEND_CHANGE_ADDED;
new_change->vcard = g_strdup (vcard);
return new_change;
@@ -835,12 +809,12 @@ e_book_backend_change_add_new (const char *vcard)
*
* Return value: A new #GNOME_Evolution_Addressbook_BookChangeItem.
**/
-GNOME_Evolution_Addressbook_BookChangeItem*
+EDataBookChange *
e_book_backend_change_modify_new (const char *vcard)
{
- GNOME_Evolution_Addressbook_BookChangeItem* new_change = GNOME_Evolution_Addressbook_BookChangeItem__alloc();
+ EDataBookChange *new_change = g_new (EDataBookChange, 1);
- new_change->changeType= GNOME_Evolution_Addressbook_ContactModified;
+ new_change->change_type = E_DATA_BOOK_BACKEND_CHANGE_MODIFIED;
new_change->vcard = g_strdup (vcard);
return new_change;
@@ -855,12 +829,12 @@ e_book_backend_change_modify_new (const char *vcard)
*
* Return value: A new #GNOME_Evolution_Addressbook_BookChangeItem.
**/
-GNOME_Evolution_Addressbook_BookChangeItem*
+EDataBookChange *
e_book_backend_change_delete_new (const char *vcard)
{
- GNOME_Evolution_Addressbook_BookChangeItem* new_change = GNOME_Evolution_Addressbook_BookChangeItem__alloc();
+ EDataBookChange *new_change = g_new (EDataBookChange, 1);
- new_change->changeType= GNOME_Evolution_Addressbook_ContactDeleted;
+ new_change->change_type = E_DATA_BOOK_BACKEND_CHANGE_DELETED;
new_change->vcard = g_strdup (vcard);
return new_change;
@@ -1042,6 +1016,7 @@ e_book_backend_init (EBookBackend *backend)
priv = g_new0 (EBookBackendPrivate, 1);
priv->clients = NULL;
+ priv->source = NULL;
priv->views = e_list_new((EListCopyFunc) NULL, (EListFreeFunc) NULL, NULL);
priv->open_mutex = g_mutex_new ();
priv->clients_mutex = g_mutex_new ();
@@ -1065,7 +1040,10 @@ e_book_backend_dispose (GObject *object)
backend->priv->views = NULL;
}
- g_object_unref (backend->priv->source);
+ if (backend->priv->source) {
+ g_object_unref (backend->priv->source);
+ backend->priv->source = NULL;
+ }
g_mutex_free (backend->priv->open_mutex);
g_mutex_free (backend->priv->clients_mutex);
diff --git a/addressbook/libedata-book/e-book-backend.h b/addressbook/libedata-book/e-book-backend.h
index fa57cc4..e812b94 100644
--- a/addressbook/libedata-book/e-book-backend.h
+++ b/addressbook/libedata-book/e-book-backend.h
@@ -25,9 +25,10 @@
#include <glib.h>
#include <glib-object.h>
#include <libebook/e-contact.h>
-#include <libedata-book/Evolution-DataServer-Addressbook.h>
-#include <libedata-book/e-data-book-types.h>
-#include <libedata-book/e-data-book.h>
+#include "e-data-book-types.h"
+#include "e-data-book.h"
+#include <libedataserver/e-list.h>
+#include <libedataserver/e-source.h>
G_BEGIN_DECLS
diff --git a/addressbook/libedata-book/e-data-book-factory.c b/addressbook/libedata-book/e-data-book-factory.c
index 961acfb..6e8a037 100644
--- a/addressbook/libedata-book/e-data-book-factory.c
+++ b/addressbook/libedata-book/e-data-book-factory.c
@@ -1,576 +1,375 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
*
- * Author:
- * Nat Friedman (nat 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.
*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Ross Burton <ross linux intel com>
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
-
+#include <stdlib.h>
#include <string.h>
-
-#include <bonobo-activation/bonobo-activation.h>
-#include <bonobo/bonobo-main.h>
-#include <bonobo/bonobo-arg.h>
-#include "libebackend/e-data-server-module.h"
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <dbus/dbus-protocol.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <dbus/dbus-glib-bindings.h>
+#include <libebackend/e-data-server-module.h>
+#include "e-book-backend-factory.h"
#include "e-data-book-factory.h"
+#include "e-data-book.h"
+#include "e-book-backend.h"
+#include "e-book-backend-factory.h"
-#include <backends/groupwise/e-book-backend-groupwise.h>
+static void impl_BookFactory_getBook(EDataBookFactory *factory, const char *IN_uri, DBusGMethodInvocation *context);
+#include "e-data-book-factory-glue.h"
-#define DEFAULT_E_DATA_BOOK_FACTORY_OAF_ID "OAFIID:GNOME_Evolution_DataServer_BookFactory:" BASE_VERSION
+static gchar *nm_dbus_escape_object_path (const gchar *utf8_string);
-static BonoboObjectClass *e_data_book_factory_parent_class;
+static GMainLoop *loop;
+static EDataBookFactory *factory;
+DBusGConnection *connection;
-typedef struct {
- char *uri;
- GNOME_Evolution_Addressbook_BookListener listener;
-} EDataBookFactoryQueuedRequest;
+/* Convenience macro to test and set a GError/return on failure */
+#define g_set_error_val_if_fail(test, returnval, error, domain, code) G_STMT_START{ \
+ if G_LIKELY (test) {} else { \
+ g_set_error (error, domain, code, #test); \
+ g_warning(#test " failed"); \
+ return (returnval); \
+ } \
+}G_STMT_END
-struct _EDataBookFactoryPrivate {
- GMutex *map_mutex;
+/* Generate the GObject boilerplate */
+G_DEFINE_TYPE(EDataBookFactory, e_data_book_factory, G_TYPE_OBJECT);
- GHashTable *backends;
- GHashTable *active_server_map;
+#define E_DATA_BOOK_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_DATA_BOOK_FACTORY, EDataBookFactoryPrivate))
- /* OAFIID of the factory */
- char *iid;
+struct _EDataBookFactoryPrivate {
+ /* TODO: as the factory is not threaded these locks could be removed */
+ GMutex *backend_lock;
+ GHashTable *backends;
- /* Whether the factory has been registered with OAF yet */
- guint registered : 1;
+ GMutex *books_lock;
+ /* A hash of object paths for book URIs to EDataBooks */
+ GHashTable *books;
- int mode;
-};
+ GMutex *connections_lock;
+ /* This is a hash of client addresses to GList* of EDataBooks */
+ GHashTable *connections;
-/* Signal IDs */
-enum {
- LAST_BOOK_GONE,
- LAST_SIGNAL
+ guint exit_timeout;
};
-static guint factory_signals[LAST_SIGNAL];
-
-static char *
-e_data_book_factory_canonicalize_uri (const char *uri)
-{
- /* FIXME: What do I do here? */
-
- return g_strdup (uri);
-}
-
-static char *
-e_data_book_factory_extract_proto_from_uri (const char *uri)
-{
- char *proto;
- char *p;
-
- p = strchr (uri, ':');
-
- if (p == NULL)
- return NULL;
-
- proto = g_malloc0 (p - uri + 1);
-
- strncpy (proto, uri, p - uri);
-
- return proto;
-}
-
-/**
- * e_data_book_factory_register_backend:
- * @factory: an #EDataBookFactory
- * @backend_factory: an #EBookBackendFactory
- *
- * Registers @backend_factory with @factory.
- **/
-void
-e_data_book_factory_register_backend (EDataBookFactory *book_factory,
- EBookBackendFactory *backend_factory)
+/* Create the EDataBookFactory error quark */
+GQuark
+e_data_book_factory_error_quark (void)
{
- const char *proto;
-
- g_return_if_fail (E_IS_DATA_BOOK_FACTORY (book_factory));
- g_return_if_fail (E_IS_BOOK_BACKEND_FACTORY (backend_factory));
-
- proto = E_BOOK_BACKEND_FACTORY_GET_CLASS (backend_factory)->get_protocol (backend_factory);
-
- if (g_hash_table_lookup (book_factory->priv->backends, proto) != NULL) {
- g_warning ("e_data_book_factory_register_backend: "
- "Proto \"%s\" already registered!\n", proto);
- }
-
- g_hash_table_insert (book_factory->priv->backends,
- g_strdup (proto), backend_factory);
+ static GQuark quark = 0;
+ if (!quark)
+ quark = g_quark_from_static_string ("e_data_book_factory_error");
+ return quark;
}
static void
-out_of_proc_check (gpointer key, gpointer value, gpointer data)
+e_data_book_factory_register_backend (EDataBookFactory *book_factory, EBookBackendFactory *backend_factory)
{
- gboolean *out_of_proc = data;
-
- if ((*out_of_proc))
- return;
-
- *out_of_proc = e_book_backend_has_out_of_proc_clients (value);
+ const char *proto;
+
+ g_return_if_fail (E_IS_DATA_BOOK_FACTORY (book_factory));
+ g_return_if_fail (E_IS_BOOK_BACKEND_FACTORY (backend_factory));
+
+ proto = E_BOOK_BACKEND_FACTORY_GET_CLASS (backend_factory)->get_protocol (backend_factory);
+
+ if (g_hash_table_lookup (book_factory->priv->backends, proto) != NULL) {
+ g_warning ("e_data_book_factory_register_backend: Proto \"%s\" already registered!\n", proto);
+ }
+
+ g_hash_table_insert (book_factory->priv->backends, g_strdup (proto), backend_factory);
}
-/**
- * e_data_book_factory_get_n_backends:
- * @factory: An addressbook factory.
- *
- * Queries the number of running addressbook backends in an addressbook factory.
- *
- * Return value: Number of running backends.
- **/
-int
-e_data_book_factory_get_n_backends (EDataBookFactory *factory)
-{
- int n_backends;
- gboolean out_of_proc = FALSE;
-
- g_return_val_if_fail (factory != NULL, -1);
- g_return_val_if_fail (E_IS_DATA_BOOK_FACTORY (factory), -1);
-
- g_mutex_lock (factory->priv->map_mutex);
- g_hash_table_foreach (factory->priv->active_server_map, out_of_proc_check, &out_of_proc);
-
- if (!out_of_proc)
- n_backends = 0;
- else
- n_backends = g_hash_table_size (factory->priv->active_server_map);
- g_mutex_unlock (factory->priv->map_mutex);
-
- return n_backends;
-}
-
-/**
- * e_data_book_factory_register_backends:
- * @book_factory: an #EDataBookFactory
- *
- * Register the backends supported by the Evolution Data Server,
- * with @book_factory.
- **/
-void
+static void
e_data_book_factory_register_backends (EDataBookFactory *book_factory)
{
- GList *factories, *f;
-
- factories = e_data_server_get_extensions_for_type (E_TYPE_BOOK_BACKEND_FACTORY);
- for (f = factories; f; f = f->next) {
- EBookBackendFactory *backend_factory = f->data;
-
- e_data_book_factory_register_backend (book_factory, g_object_ref (backend_factory));
- }
-
- e_data_server_extension_list_free (factories);
+ GList *factories, *f;
+ factories = e_data_server_get_extensions_for_type (E_TYPE_BOOK_BACKEND_FACTORY);
+ for (f = factories; f; f = f->next) {
+ EBookBackendFactory *backend_factory = f->data;
+ e_data_book_factory_register_backend (book_factory, g_object_ref (backend_factory));
+ }
+ e_data_server_extension_list_free (factories);
+ e_data_server_module_remove_unused ();
}
+/* Class init */
static void
-dump_active_server_map_entry (gpointer key, gpointer value, gpointer data)
+e_data_book_factory_class_init (EDataBookFactoryClass *e_data_book_factory_class)
{
- char *uri;
- EBookBackend *backend;
-
- uri = key;
- backend = E_BOOK_BACKEND (value);
-
- g_message (" %s: %p", uri, backend);
-}
-
-/**
- * e_data_book_factory_dump_active_backends:
- * @factory: an #EDataBookFactory
- *
- * Dump the list of active backends registered with @factory
- * to stdout. This is a debugging function.
- **/
-void
-e_data_book_factory_dump_active_backends (EDataBookFactory *factory)
-{
- g_message ("Active PAS backends");
-
- g_mutex_lock (factory->priv->map_mutex);
- g_hash_table_foreach (factory->priv->active_server_map,
- dump_active_server_map_entry,
- NULL);
- g_mutex_unlock (factory->priv->map_mutex);
+ g_type_class_add_private (e_data_book_factory_class, sizeof (EDataBookFactoryPrivate));
+ dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (e_data_book_factory_class), &dbus_glib_e_data_book_factory_object_info);
}
-/* Callback used when a backend loses its last connected client */
+/* Instance init */
static void
-backend_last_client_gone_cb (EBookBackend *backend, gpointer data)
+e_data_book_factory_init (EDataBookFactory *factory)
{
- EDataBookFactory *factory;
- ESource *source;
- gchar *uri;
+ factory->priv = E_DATA_BOOK_FACTORY_GET_PRIVATE (factory);
- factory = E_DATA_BOOK_FACTORY (data);
+ factory->priv->backend_lock = g_mutex_new ();
+ factory->priv->backends = g_hash_table_new (g_str_hash, g_str_equal);
- /* Remove the backend from the active server map */
+ factory->priv->books_lock = g_mutex_new ();
+ factory->priv->books = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- source = e_book_backend_get_source (backend);
- if (source)
- uri = e_source_get_uri (source);
- else
- uri = NULL;
+ factory->priv->connections_lock = g_mutex_new ();
+ factory->priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- if (uri) {
- g_mutex_lock (factory->priv->map_mutex);
- g_hash_table_remove (factory->priv->active_server_map, uri);
- g_mutex_unlock (factory->priv->map_mutex);
- }
-
- if (g_hash_table_size (factory->priv->active_server_map) == 0) {
- /* Notify upstream if there are no more backends */
- g_signal_emit (G_OBJECT (factory), factory_signals[LAST_BOOK_GONE], 0);
- }
-
- g_free (uri);
+ e_data_server_module_init ();
+ e_data_book_factory_register_backends (factory);
}
-
+/* TODO: write dispose to kill hash */
+static char *
+e_data_book_factory_extract_proto_from_uri (const char *uri)
+{
+ char *proto, *p;
+ p = strchr (uri, ':');
+ if (p == NULL)
+ return NULL;
+ proto = g_malloc0 (p - uri + 1);
+ strncpy (proto, uri, p - uri);
+ return proto;
+}
static EBookBackendFactory*
e_data_book_factory_lookup_backend_factory (EDataBookFactory *factory,
const char *uri)
{
- EBookBackendFactory *backend_factory;
- char *proto;
- char *canonical_uri;
-
- g_assert (factory != NULL);
- g_assert (E_IS_DATA_BOOK_FACTORY (factory));
- g_assert (uri != NULL);
-
- canonical_uri = e_data_book_factory_canonicalize_uri (uri);
- if (canonical_uri == NULL)
- return NULL;
-
- proto = e_data_book_factory_extract_proto_from_uri (canonical_uri);
- if (proto == NULL) {
- g_free (canonical_uri);
- return NULL;
- }
-
- backend_factory = g_hash_table_lookup (factory->priv->backends, proto);
-
- g_free (proto);
- g_free (canonical_uri);
-
- return backend_factory;
+ EBookBackendFactory *backend_factory;
+ char *proto;
+
+ g_return_val_if_fail (E_IS_DATA_BOOK_FACTORY (factory), NULL);
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ proto = e_data_book_factory_extract_proto_from_uri (uri);
+ if (proto == NULL) {
+ g_warning ("Cannot extract protocol from URI %s", uri);
+ return NULL;
+ }
+
+ backend_factory = g_hash_table_lookup (factory->priv->backends, proto);
+ g_free (proto);
+ return backend_factory;
}
-static EBookBackend *
-e_data_book_factory_launch_backend (EDataBookFactory *book_factory,
- EBookBackendFactory *backend_factory,
- GNOME_Evolution_Addressbook_BookListener listener,
- const char *uri)
+static char *
+make_path_name (const char* uri)
{
- EBookBackend *backend;
-
- backend = e_book_backend_factory_new_backend (backend_factory);
- if (!backend)
- return NULL;
-
- g_hash_table_insert (book_factory->priv->active_server_map,
- g_strdup (uri),
- backend);
-
- g_signal_connect (backend, "last_client_gone",
- G_CALLBACK (backend_last_client_gone_cb),
- book_factory);
-
- return backend;
+ char *s, *path;
+ s = nm_dbus_escape_object_path (uri);
+ path = g_strdup_printf ("/org/gnome/evolution/dataserver/addressbook/%s", s);
+ g_free (s);
+ return path;
}
-static GNOME_Evolution_Addressbook_Book
-impl_GNOME_Evolution_Addressbook_BookFactory_getBook (PortableServer_Servant servant,
- const CORBA_char *source_xml,
- const GNOME_Evolution_Addressbook_BookListener listener,
- CORBA_Environment *ev)
+static void my_remove (char *key, GObject *dead)
{
- EDataBookFactory *factory = E_DATA_BOOK_FACTORY (bonobo_object (servant));
- GNOME_Evolution_Addressbook_Book corba_book;
- EBookBackend *backend;
- EDataBook *book = NULL;
- ESource *source;
- gchar *uri;
-
- printf ("impl_GNOME_Evolution_Addressbook_BookFactory_getBook\n");
-
- source = e_source_new_from_standalone_xml (source_xml);
- if (!source) {
- CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
- ex_GNOME_Evolution_Addressbook_BookFactory_ProtocolNotSupported,
- NULL);
- return CORBA_OBJECT_NIL;
- }
-
- uri = e_source_get_uri (source);
- if (!uri) {
- g_object_unref (source);
- CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
- ex_GNOME_Evolution_Addressbook_BookFactory_ProtocolNotSupported,
- NULL);
- return CORBA_OBJECT_NIL;
- }
- printf (" + %s\n", uri);
-
- /* Look up the backend and create one if needed */
- g_mutex_lock (factory->priv->map_mutex);
-
- backend = g_hash_table_lookup (factory->priv->active_server_map, uri);
-
- if (!backend) {
- EBookBackendFactory* backend_factory;
-
- backend_factory = e_data_book_factory_lookup_backend_factory (factory, uri);
+ g_mutex_lock (factory->priv->books_lock);
+ g_hash_table_remove (factory->priv->books, key);
+ g_mutex_unlock (factory->priv->books_lock);
- if (backend_factory == NULL) {
- CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
- ex_GNOME_Evolution_Addressbook_BookFactory_ProtocolNotSupported,
- NULL);
+ g_free (key);
- g_mutex_unlock (factory->priv->map_mutex);
-
- g_free (uri);
- return CORBA_OBJECT_NIL;
- }
-
- backend = e_data_book_factory_launch_backend (factory, backend_factory, listener, uri);
- }
-
- g_free (uri);
-
- if (backend) {
- g_mutex_unlock (factory->priv->map_mutex);
-
- book = e_data_book_new (backend, source, listener);
-
- e_book_backend_add_client (backend, book);
- e_book_backend_set_mode (backend, factory->priv->mode);
- corba_book = bonobo_object_corba_objref (BONOBO_OBJECT (book));
- }
- else {
- /* probably need a more descriptive exception here */
- CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
- ex_GNOME_Evolution_Addressbook_BookFactory_ProtocolNotSupported,
- NULL);
- g_mutex_unlock (factory->priv->map_mutex);
-
- corba_book = CORBA_OBJECT_NIL;
- }
-
- g_object_unref (source);
- if (book)
- printf (" => %p\n", book);
- return corba_book;
+ /* If there are no open books, start a timer to quit */
+ if (factory->priv->exit_timeout == 0 && g_hash_table_size (factory->priv->books) == 0) {
+ factory->priv->exit_timeout = g_timeout_add (10000, (GSourceFunc)g_main_loop_quit, loop);
+ }
}
static void
-e_data_book_factory_construct (EDataBookFactory *factory)
-{
- /* nothing to do here.. */
-}
-
-/**
- * e_data_book_factory_new:
- *
- * Create a new #EDataBookFactory.
- *
- * Return value: A new #EDataBookFactory.
- **/
-EDataBookFactory *
-e_data_book_factory_new (void)
+book_closed_cb (EDataBook *book, const char *client)
{
- static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
- static PortableServer_POA poa = NULL;
- EDataBookFactory *factory;
-
- g_static_mutex_lock (&mutex);
- if (poa == NULL)
- poa = bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL);
- g_static_mutex_unlock (&mutex);
-
- factory = g_object_new (E_TYPE_DATA_BOOK_FACTORY, "poa", poa, NULL);
-
- e_data_book_factory_construct (factory);
+ GList *list;
- return factory;
+ list = g_hash_table_lookup (factory->priv->connections, client);
+ list = g_list_remove (list, book);
+ g_hash_table_insert (factory->priv->connections, g_strdup (client), list);
}
-/**
- * e_data_book_factory_activate:
- * @factory: an #EDataBookFactory
- * @iid: the OAF ID of the factory to activate
- *
- * Activates the factory specified by @iid, using Bonobo.
- *
- * Return value: %TRUE for success, %FALSE otherwise.
- **/
-gboolean
-e_data_book_factory_activate (EDataBookFactory *factory, const char *iid)
+static void
+impl_BookFactory_getBook(EDataBookFactory *factory, const char *IN_uri, DBusGMethodInvocation *context)
{
- EDataBookFactoryPrivate *priv;
- Bonobo_RegistrationResult result;
- char *tmp_iid;
-
- g_return_val_if_fail (factory != NULL, FALSE);
- g_return_val_if_fail (E_IS_DATA_BOOK_FACTORY (factory), FALSE);
-
- priv = factory->priv;
-
- g_return_val_if_fail (!priv->registered, FALSE);
-
- /* if iid is NULL, use the default factory OAFIID */
- if (iid)
- tmp_iid = g_strdup (iid);
- else
- tmp_iid = g_strdup (DEFAULT_E_DATA_BOOK_FACTORY_OAF_ID);
-
- result = bonobo_activation_active_server_register (tmp_iid, bonobo_object_corba_objref (BONOBO_OBJECT (factory)));
-
- switch (result) {
- case Bonobo_ACTIVATION_REG_SUCCESS:
- priv->registered = TRUE;
- priv->iid = tmp_iid;
- return TRUE;
- case Bonobo_ACTIVATION_REG_NOT_LISTED:
- g_message ("Error registering the PAS factory: not listed");
- break;
- case Bonobo_ACTIVATION_REG_ALREADY_ACTIVE:
- g_message ("Error registering the PAS factory: already active");
- break;
- case Bonobo_ACTIVATION_REG_ERROR:
- default:
- g_message ("Error registering the PAS factory: generic error");
- break;
- }
-
- g_free (tmp_iid);
- return FALSE;
+ EDataBook *book;
+ EDataBookFactoryPrivate *priv = factory->priv;
+ ESource *source;
+ char *path, *sender;
+ GList *list;
+
+ if (IN_uri == NULL || IN_uri[0] == '\0') {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_NO_SUCH_BOOK, _("Empty URI")));
+ return;
+ }
+
+ /* Remove a pending exit */
+ if (priv->exit_timeout) {
+ g_source_remove (priv->exit_timeout);
+ priv->exit_timeout = 0;
+ }
+
+ g_mutex_lock (priv->books_lock);
+
+ source = e_source_new_with_absolute_uri ("", IN_uri);
+ path = make_path_name (IN_uri);
+ book = g_hash_table_lookup (priv->books, path);
+ if (book == NULL) {
+ EBookBackend *backend = NULL;
+ backend = e_book_backend_factory_new_backend (e_data_book_factory_lookup_backend_factory (factory, IN_uri));
+ book = e_data_book_new (backend, source, book_closed_cb);
+ e_book_backend_set_mode (backend, 2); /* TODO: very odd */
+ g_hash_table_insert (priv->books, g_strdup(path), book);
+ dbus_g_connection_register_g_object (connection, path, G_OBJECT (book));
+ g_object_weak_ref (G_OBJECT (book), (GWeakNotify)my_remove, g_strdup (path));
+ g_object_unref (backend); /* The book takes a reference to the backend */
+ } else {
+ g_object_ref (book);
+ }
+ g_object_unref (source);
+
+ /* Update the hash of open connections */
+ g_mutex_lock (priv->connections_lock);
+ sender = dbus_g_method_get_sender (context);
+ list = g_hash_table_lookup (priv->connections, sender);
+ list = g_list_prepend (list, book);
+ g_hash_table_insert (priv->connections, sender, list);
+ g_mutex_unlock (priv->connections_lock);
+
+ g_mutex_unlock (priv->books_lock);
+
+ dbus_g_method_return (context, path);
}
+
static void
-set_backend_online_status (gpointer key, gpointer value, gpointer data)
+name_owner_changed (DBusGProxy *proxy,
+ const char *name,
+ const char *prev_owner,
+ const char *new_owner,
+ EDataBookFactory *factory)
{
- EBookBackend *backend;
-
- backend = E_BOOK_BACKEND (value);
- e_book_backend_set_mode (backend, GPOINTER_TO_INT (data));
+ if (strcmp (new_owner, "") == 0 && strcmp (name, prev_owner) == 0) {
+ char *key;
+ GList *list = NULL;
+ g_mutex_lock (factory->priv->connections_lock);
+ if (g_hash_table_lookup_extended (factory->priv->connections, prev_owner, (gpointer)&key, (gpointer)&list)) {
+ g_list_foreach (list, (GFunc)g_object_unref, NULL);
+ g_list_free (list);
+ g_hash_table_remove (factory->priv->connections, prev_owner);
+ }
+ g_mutex_unlock (factory->priv->connections_lock);
+ }
}
-/**
- * e_data_book_factory_set_backend_mode:
- * @factory: an #EDataBookFactory
- * @mode: a connection status
- *
- * Sets all the backends associated with @factory to be either online
- * or offline. @mode should be passed as 1 for offline, or 2 for
- * online.
- **/
-void
-e_data_book_factory_set_backend_mode (EDataBookFactory *factory, int mode)
+/* Convenience function to print an error and exit */
+static void
+die (const char *prefix, GError *error)
{
- EDataBookFactoryPrivate *priv = factory->priv;
-
+ g_error("%s: %s", prefix, error->message);
+ g_error_free (error);
+ exit(1);
+}
- g_mutex_lock (priv->map_mutex);
- priv->mode = mode;
- g_hash_table_foreach (priv->active_server_map, set_backend_online_status, GINT_TO_POINTER (priv->mode));
- g_mutex_unlock (priv->map_mutex);
+#define E_DATA_BOOK_FACTORY_SERVICE_NAME "org.gnome.evolution.dataserver.AddressBook"
-}
-static void
-e_data_book_factory_init (EDataBookFactory *factory)
+int
+main (int argc, char **argv)
{
- GHashTable *active_server_map;
- GHashTable *backends;
+ GError *error = NULL;
+ DBusGProxy *bus_proxy;
+ guint32 request_name_ret;
- active_server_map = g_hash_table_new_full (
- g_str_hash, g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) g_object_unref);
+ g_type_init ();
+ if (!g_thread_supported ()) g_thread_init (NULL);
+ dbus_g_thread_init ();
- backends = g_hash_table_new_full (
- g_str_hash, g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) NULL);
+ loop = g_main_loop_new (NULL, FALSE);
- factory->priv = g_new0 (EDataBookFactoryPrivate, 1);
+ /* Obtain a connection to the session bus */
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (connection == NULL)
+ die ("Failed to open connection to bus", error);
- factory->priv->map_mutex = g_mutex_new();
- factory->priv->active_server_map = active_server_map;
- factory->priv->backends = backends;
- factory->priv->registered = FALSE;
-}
+ bus_proxy = dbus_g_proxy_new_for_name (connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
-static void
-e_data_book_factory_dispose (GObject *object)
-{
- EDataBookFactory *factory = E_DATA_BOOK_FACTORY (object);
- EDataBookFactoryPrivate *priv = factory->priv;
+ if (!org_freedesktop_DBus_request_name (bus_proxy, E_DATA_BOOK_FACTORY_SERVICE_NAME,
+ 0, &request_name_ret, &error))
+ die ("Failed to get name", error);
- g_hash_table_remove_all (priv->active_server_map);
- g_hash_table_remove_all (priv->backends);
+ if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ g_error ("Got result code %u from requesting name", request_name_ret);
+ exit (1);
+ }
- if (priv->registered) {
- bonobo_activation_active_server_unregister (
- priv->iid, bonobo_object_corba_objref (
- BONOBO_OBJECT (factory)));
- priv->registered = FALSE;
- }
+ factory = g_object_new (E_TYPE_DATA_BOOK_FACTORY, NULL);
+ dbus_g_connection_register_g_object (connection,
+ "/org/gnome/evolution/dataserver/addressbook/BookFactory",
+ G_OBJECT (factory));
- if (G_OBJECT_CLASS (e_data_book_factory_parent_class)->dispose)
- G_OBJECT_CLASS (e_data_book_factory_parent_class)->dispose (object);
-}
+ dbus_g_proxy_add_signal (bus_proxy, "NameOwnerChanged",
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (bus_proxy, "NameOwnerChanged", G_CALLBACK (name_owner_changed), factory, NULL);
-static void
-e_data_book_factory_finalize (GObject *object)
-{
- EDataBookFactory *factory = E_DATA_BOOK_FACTORY (object);
- EDataBookFactoryPrivate *priv = factory->priv;
+ g_main_loop_run (loop);
- g_mutex_free (priv->map_mutex);
- g_hash_table_destroy (priv->active_server_map);
- g_hash_table_destroy (priv->backends);
- g_free (priv->iid);
- g_free (priv);
+ dbus_g_connection_unref (connection);
- if (G_OBJECT_CLASS (e_data_book_factory_parent_class)->finalize)
- G_OBJECT_CLASS (e_data_book_factory_parent_class)->finalize (object);
+ return 0;
}
-static void
-e_data_book_factory_class_init (EDataBookFactoryClass *klass)
+/* Stolen from http://cvs.gnome.org/viewcvs/NetworkManager/utils/nm-utils.c */
+static gchar *nm_dbus_escape_object_path (const gchar *utf8_string)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- POA_GNOME_Evolution_Addressbook_BookFactory__epv *epv;
+ const gchar *p;
+ GString *string;
- e_data_book_factory_parent_class = g_type_class_peek_parent (klass);
+ g_return_val_if_fail (utf8_string != NULL, NULL);
+ g_return_val_if_fail (g_utf8_validate (utf8_string, -1, NULL), NULL);
- object_class->dispose = e_data_book_factory_dispose;
- object_class->finalize = e_data_book_factory_finalize;
+ string = g_string_sized_new ((strlen (utf8_string) + 1) * 2);
- factory_signals[LAST_BOOK_GONE] =
- g_signal_new ("last_book_gone",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (EDataBookFactoryClass, last_book_gone),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ for (p = utf8_string; *p != '\0'; p = g_utf8_next_char (p))
+ {
+ gunichar character;
+ character = g_utf8_get_char (p);
- epv = &klass->epv;
+ if (((character >= ((gunichar) 'a')) &&
+ (character <= ((gunichar) 'z'))) ||
+ ((character >= ((gunichar) 'A')) &&
+ (character <= ((gunichar) 'Z'))) ||
+ ((character >= ((gunichar) '0')) &&
+ (character <= ((gunichar) '9'))))
+ {
+ g_string_append_c (string, (gchar) character);
+ continue;
+ }
- epv->getBook = impl_GNOME_Evolution_Addressbook_BookFactory_getBook;
-}
+ g_string_append_printf (string, "_%x_", character);
+ }
-BONOBO_TYPE_FUNC_FULL (
- EDataBookFactory,
- GNOME_Evolution_Addressbook_BookFactory,
- BONOBO_TYPE_OBJECT,
- e_data_book_factory);
+ return g_string_free (string, FALSE);
+}
diff --git a/addressbook/libedata-book/e-data-book-factory.h b/addressbook/libedata-book/e-data-book-factory.h
index 1724cab..a3134c4 100644
--- a/addressbook/libedata-book/e-data-book-factory.h
+++ b/addressbook/libedata-book/e-data-book-factory.h
@@ -1,56 +1,59 @@
+/* -*- 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 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 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.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Ross Burton <ross linux intel com>
*/
-#include <bonobo/bonobo-object.h>
-#include <libedata-book/Evolution-DataServer-Addressbook.h>
-#include <libedata-book/e-book-backend.h>
-#include <libedata-book/e-book-backend-factory.h>
-
#ifndef __E_DATA_BOOK_FACTORY_H__
#define __E_DATA_BOOK_FACTORY_H__
-G_BEGIN_DECLS
-
-#define E_TYPE_DATA_BOOK_FACTORY (e_data_book_factory_get_type ())
-#define E_DATA_BOOK_FACTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_DATA_BOOK_FACTORY, EDataBookFactory))
-#define E_DATA_BOOK_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), E_TYPE_DATA_BOOK_FACTORY, EDataBookFactoryClass))
-#define E_IS_DATA_BOOK_FACTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_DATA_BOOK_FACTORY))
-#define E_IS_DATA_BOOK_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_DATA_BOOK_FACTORY))
-#define E_DATA_BOOK_FACTORY_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_DATA_BOOK_FACTORY, EDataBookFactoryClass))
+#include <glib-object.h>
+typedef struct EDataBookFactory EDataBookFactory;
+typedef struct EDataBookFactoryClass EDataBookFactoryClass;
typedef struct _EDataBookFactoryPrivate EDataBookFactoryPrivate;
-typedef struct {
- BonoboObject parent_object;
- EDataBookFactoryPrivate *priv;
-} EDataBookFactory;
-
-typedef struct {
- BonoboObjectClass parent_class;
-
- POA_GNOME_Evolution_Addressbook_BookFactory__epv epv;
-
- /* Notification signals */
- void (* last_book_gone) (EDataBookFactory *factory);
-} EDataBookFactoryClass;
-
-EDataBookFactory *e_data_book_factory_new (void);
-
-void e_data_book_factory_register_backend (EDataBookFactory *factory,
- EBookBackendFactory *backend_factory);
-
-int e_data_book_factory_get_n_backends (EDataBookFactory *factory);
+struct EDataBookFactory
+{
+ GObject parent;
+ EDataBookFactoryPrivate *priv;
+};
-void e_data_book_factory_register_backends (EDataBookFactory *factory);
+struct EDataBookFactoryClass
+{
+ GObjectClass parent;
+};
-void e_data_book_factory_dump_active_backends (EDataBookFactory *factory);
+#define E_TYPE_DATA_BOOK_FACTORY (e_data_book_factory_get_type ())
+#define E_DATA_BOOK_FACTORY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), E_TYPE_DATA_BOOK_FACTORY, EDataBookFactory))
+#define E_DATA_BOOK_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_DATA_BOOK_FACTORY, EDataBookFactoryClass))
+#define E_IS_DATA_BOOK_FACTORY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), E_TYPE_DATA_BOOK_FACTORY))
+#define E_IS_DATA_BOOK_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_DATA_BOOK_FACTORY))
+#define E_DATA_BOOK_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_DATA_BOOK_FACTORY, EDataBookFactoryClass))
-gboolean e_data_book_factory_activate (EDataBookFactory *factory, const char *iid);
-void e_data_book_factory_set_backend_mode (EDataBookFactory *factory, int mode);
+typedef enum
+{
+ E_DATA_BOOK_FACTORY_ERROR_GENERIC
+} EDataBookFactoryError;
-GType e_data_book_factory_get_type (void);
+GQuark e_data_book_factory_error_quark (void);
+#define E_DATA_BOOK_FACTORY_ERROR e_data_book_factory_error_quark ()
-G_END_DECLS
+GType e_data_book_factory_get_type (void);
-#endif /* ! __E_DATA_BOOK_FACTORY_H__ */
+#endif /* __E_DATA_BOOK_FACTORY_H__ */
diff --git a/addressbook/libedata-book/e-data-book-types.h b/addressbook/libedata-book/e-data-book-types.h
index 30ced26..8e98ec9 100644
--- a/addressbook/libedata-book/e-data-book-types.h
+++ b/addressbook/libedata-book/e-data-book-types.h
@@ -1,13 +1,25 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * Blanket header containing the typedefs for object types used in the
- * PAS stuff, so we can disentangle the #includes.
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
*
- * Author: Chris Toshok <toshok 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.
*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Chris Toshok <toshok ximian com>
+ * Author: Ross Burton <ross linux intel com>
*/
-
#ifndef __E_DATA_BOOK_TYPES_H__
#define __E_DATA_BOOK_TYPES_H__
@@ -31,6 +43,83 @@ typedef struct _EBookBackendSyncClass EBookBackendSyncClass;
typedef struct _EDataBook EDataBook;
typedef struct _EDataBookClass EDataBookClass;
+typedef enum {
+ E_DATA_BOOK_STATUS_SUCCESS,
+ E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
+ E_DATA_BOOK_STATUS_PERMISSION_DENIED,
+ E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND,
+ E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS,
+ E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED,
+ E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED,
+ E_DATA_BOOK_STATUS_UNSUPPORTED_FIELD,
+ E_DATA_BOOK_STATUS_UNSUPPORTED_AUTHENTICATION_METHOD,
+ E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE,
+ E_DATA_BOOK_STATUS_NO_SUCH_BOOK,
+ E_DATA_BOOK_STATUS_BOOK_REMOVED,
+ E_DATA_BOOK_STATUS_OFFLINE_UNAVAILABLE,
+ E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED,
+ E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED,
+ E_DATA_BOOK_STATUS_INVALID_QUERY,
+ E_DATA_BOOK_STATUS_QUERY_REFUSED,
+ E_DATA_BOOK_STATUS_COULD_NOT_CANCEL,
+ E_DATA_BOOK_STATUS_OTHER_ERROR,
+ E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION,
+ E_DATA_BOOK_STATUS_NO_SPACE,
+} EDataBookStatus;
+
+/* Some hacks so the backends compile without change */
+#define GNOME_Evolution_Addressbook_CallStatus EDataBookStatus
+#define GNOME_Evolution_Addressbook_BookMode EDataBookMode
+
+#define GNOME_Evolution_Addressbook_Success E_DATA_BOOK_STATUS_SUCCESS
+#define GNOME_Evolution_Addressbook_RepositoryOffline E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE
+#define GNOME_Evolution_Addressbook_PermissionDenied E_DATA_BOOK_STATUS_PERMISSION_DENIED
+#define GNOME_Evolution_Addressbook_ContactNotFound E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND
+#define GNOME_Evolution_Addressbook_ContactIdAlreadyExists E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS
+#define GNOME_Evolution_Addressbook_AuthenticationFailed E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED
+#define GNOME_Evolution_Addressbook_AuthenticationRequired E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED
+#define GNOME_Evolution_Addressbook_UnsupportedField E_DATA_BOOK_STATUS_UNSUPPORTED_FIELD
+#define GNOME_Evolution_Addressbook_UnsupportedAuthenticationMethod E_DATA_BOOK_STATUS_UNSUPPORTED_AUTHENTICATION_METHOD
+#define GNOME_Evolution_Addressbook_TLSNotAvailable E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE
+#define GNOME_Evolution_Addressbook_NoSuchBook E_DATA_BOOK_STATUS_NO_SUCH_BOOK
+#define GNOME_Evolution_Addressbook_BookRemoved E_DATA_BOOK_STATUS_BOOK_REMOVED
+#define GNOME_Evolution_Addressbook_OfflineUnavailable E_DATA_BOOK_STATUS_BOOK_REMOVED
+#define GNOME_Evolution_Addressbook_SearchSizeLimitExceeded E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED
+#define GNOME_Evolution_Addressbook_SearchTimeLimitExceeded E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED
+#define GNOME_Evolution_Addressbook_InvalidQuery E_DATA_BOOK_STATUS_INVALID_QUERY
+#define GNOME_Evolution_Addressbook_QueryRefused E_DATA_BOOK_STATUS_QUERY_REFUSED
+#define GNOME_Evolution_Addressbook_CouldNotCancel E_DATA_BOOK_STATUS_COULD_NOT_CANCEL
+#define GNOME_Evolution_Addressbook_OtherError E_DATA_BOOK_STATUS_OTHER_ERROR
+#define GNOME_Evolution_Addressbook_InvalidServerVersion E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION
+#define GNOME_Evolution_Addressbook_NoSpace E_DATA_BOOK_STATUS_NO_SPACE
+
+typedef enum {
+ E_DATA_BOOK_MODE_LOCAL,
+ E_DATA_BOOK_MODE_REMOTE,
+ E_DATA_BOOK_MODE_ANY,
+} EDataBookMode;
+
+#define GNOME_Evolution_Addressbook_MODE_LOCAL E_DATA_BOOK_MODE_LOCAL
+#define GNOME_Evolution_Addressbook_MODE_REMOTE E_DATA_BOOK_MODE_REMOTE
+#define GNOME_Evolution_Addressbook_MODE_ANY E_DATA_BOOK_MODE_ANY
+
+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;
+ char *vcard;
+} EDataBookChange;
+
+/* Transition typedef */
+typedef EDataBookChange GNOME_Evolution_Addressbook_BookChangeItem;
+
+#define GNOME_Evolution_Addressbook_ContactAdded E_DATA_BOOK_BACKEND_CHANGE_ADDED
+#define GNOME_Evolution_Addressbook_ContactDeleted E_DATA_BOOK_BACKEND_CHANGE_DELETED
+#define GNOME_Evolution_Addressbook_ContactModified E_DATA_BOOK_BACKEND_CHANGE_MODIFIED
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 6b89f0f..2199a63 100644
--- a/addressbook/libedata-book/e-data-book-view.c
+++ b/addressbook/libedata-book/e-data-book-view.c
@@ -1,669 +1,557 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * pas-book-view.c
- *
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * 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 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.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Ross Burton <ross linux intel com>
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
-
#include <string.h>
-#include <glib.h>
-#include <bonobo/bonobo-main.h>
-#include "e-book-backend.h"
-#include "e-book-backend-sexp.h"
+#include <dbus/dbus.h>
+#include <libebook/e-contact.h>
#include "e-data-book-view.h"
-#define d(x)
-
-static BonoboObjectClass *e_data_book_view_parent_class;
-
-struct _EDataBookViewPrivate {
- GNOME_Evolution_Addressbook_BookViewListener listener;
-
-#define DEFAULT_INITIAL_THRESHOLD 20
-#define DEFAULT_THRESHOLD_MAX 3000
-
- GMutex *mutex;
-
- GMutex *pending_mutex;
+extern DBusGConnection *connection;
- CORBA_sequence_GNOME_Evolution_Addressbook_VCard adds;
- int next_threshold;
- int threshold_max;
- int threshold_min;
+static gboolean impl_BookView_start (EDataBookView *view, GError **error);
+static gboolean impl_BookView_stop (EDataBookView *view, GError **error);
+static gboolean impl_BookView_dispose (EDataBookView *view, GError **eror);
- CORBA_sequence_GNOME_Evolution_Addressbook_VCard changes;
- CORBA_sequence_GNOME_Evolution_Addressbook_ContactId removes;
+#include "e-data-book-view-glue.h"
- EBookBackend *backend;
- char *card_query;
- EBookBackendSExp *card_sexp;
- GHashTable *ids;
+static void reset_array (GArray *array);
- int max_results;
-};
+G_DEFINE_TYPE (EDataBookView, e_data_book_view, G_TYPE_OBJECT);
+#define E_DATA_BOOK_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_DATA_BOOK_VIEW, EDataBookViewPrivate))
-static void
-view_listener_died_cb (gpointer cnx, gpointer user_data)
-{
- EDataBookView *book_view = E_DATA_BOOK_VIEW (user_data);
+#define THRESHOLD 32
- if (book_view) {
- e_book_backend_stop_book_view (e_data_book_view_get_backend (book_view), book_view);
- bonobo_object_unref (book_view);
- }
-}
+struct _EDataBookViewPrivate {
+ EDataBook *book;
+ EBookBackend *backend;
-static void
-send_pending_adds (EDataBookView *book_view, gboolean reset)
-{
- CORBA_Environment ev;
- CORBA_sequence_GNOME_Evolution_Addressbook_VCard *adds;
+ char* card_query;
+ EBookBackendSExp *card_sexp;
+ int max_results;
- adds = &book_view->priv->adds;
- if (adds->_length == 0)
- return;
+ gboolean running;
+ GMutex *pending_mutex;
- CORBA_exception_init (&ev);
+ GArray *adds;
+ GArray *changes;
+ GArray *removes;
- GNOME_Evolution_Addressbook_BookViewListener_notifyContactsAdded (
- book_view->priv->listener, adds, &ev);
+ GHashTable *ids;
+ guint idle_id;
+};
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("send_pending_adds: Exception signaling BookViewListener!\n");
- }
+enum {
+ CONTACTS_ADDED,
+ CONTACTS_CHANGED,
+ CONTACTS_REMOVED,
+ STATUS_MESSAGE,
+ COMPLETE,
+ LAST_SIGNAL
+};
- CORBA_exception_free (&ev);
+static guint signals[LAST_SIGNAL] = { 0 };
- CORBA_free (adds->_buffer);
- adds->_buffer = NULL;
- adds->_maximum = 0;
- adds->_length = 0;
+static void e_data_book_view_dispose (GObject *object);
+static void e_data_book_view_finalize (GObject *object);
- if (reset)
- book_view->priv->next_threshold = book_view->priv->threshold_min;
+static void
+e_data_book_view_class_init (EDataBookViewClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = e_data_book_view_dispose;
+ object_class->finalize = e_data_book_view_finalize;
+
+ signals[CONTACTS_ADDED] =
+ g_signal_new ("contacts-added",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1, G_TYPE_STRV);
+
+ signals[CONTACTS_CHANGED] =
+ g_signal_new ("contacts-changed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1, G_TYPE_STRV);
+
+ signals[CONTACTS_REMOVED] =
+ g_signal_new ("contacts-removed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1, G_TYPE_STRV);
+
+ signals[STATUS_MESSAGE] =
+ g_signal_new ("status-message",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
+ signals[COMPLETE] =
+ g_signal_new ("complete",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+
+ g_type_class_add_private (klass, sizeof (EDataBookViewPrivate));
+
+ dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), &dbus_glib_e_data_book_view_object_info);
}
static void
-send_pending_changes (EDataBookView *book_view)
+e_data_book_view_init (EDataBookView *book_view)
{
- CORBA_Environment ev;
- CORBA_sequence_GNOME_Evolution_Addressbook_VCard *changes;
+ EDataBookViewPrivate *priv = E_DATA_BOOK_VIEW_GET_PRIVATE (book_view);
+ book_view->priv = priv;
- changes = &book_view->priv->changes;
- if (changes->_length == 0)
- return;
+ priv->running = FALSE;
+ priv->pending_mutex = g_mutex_new ();
- CORBA_exception_init (&ev);
+ priv->adds = g_array_sized_new (TRUE, TRUE, sizeof (char*), THRESHOLD);
+ priv->changes = g_array_sized_new (TRUE, TRUE, sizeof (char*), THRESHOLD);
+ priv->removes = g_array_sized_new (TRUE, TRUE, sizeof (char*), THRESHOLD);
- GNOME_Evolution_Addressbook_BookViewListener_notifyContactsChanged (
- book_view->priv->listener, changes, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("send_pending_changes: Exception signaling BookViewListener!\n");
- }
-
- CORBA_exception_free (&ev);
-
- CORBA_free (changes->_buffer);
- changes->_buffer = NULL;
- changes->_maximum = 0;
- changes->_length = 0;
+ priv->ids = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
}
static void
-send_pending_removes (EDataBookView *book_view)
+book_destroyed_cb (gpointer data, GObject *dead)
{
- CORBA_Environment ev;
- CORBA_sequence_GNOME_Evolution_Addressbook_VCard *removes;
-
- removes = &book_view->priv->removes;
- if (removes->_length == 0)
- return;
+ EDataBookView *view = E_DATA_BOOK_VIEW (data);
+ EDataBookViewPrivate *priv = view->priv;
+
+ /* The book has just died, so unset the pointer so we don't try and remove a
+ dead weak reference. */
+ view->priv->book = NULL;
+
+ /* If the view is running stop it here. */
+ if (priv->running) {
+ e_book_backend_stop_book_view (priv->backend, view);
+ priv->running = FALSE;
+ }
+}
- CORBA_exception_init (&ev);
+/**
+ * e_data_book_view_new:
+ * @book: The #EDataBook to search
+ * @path: The object path that this book view should have
+ * @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 char *path, const char *card_query, EBookBackendSExp *card_sexp, int max_results)
+{
+ EDataBookView *view;
+ EDataBookViewPrivate *priv;
- GNOME_Evolution_Addressbook_BookViewListener_notifyContactsRemoved (
- book_view->priv->listener, removes, &ev);
+ view = g_object_new (E_TYPE_DATA_BOOK_VIEW, NULL);
+ priv = view->priv;
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("send_pending_removes: Exception signaling BookViewListener!\n");
- }
+ priv->book = book;
+ /* Attach a weak reference to the book, so if it dies the book view is destroyed too */
+ g_object_weak_ref (G_OBJECT (priv->book), book_destroyed_cb, view);
+ priv->backend = g_object_ref (e_data_book_get_backend (book));
+ priv->card_query = g_strdup (card_query);
+ priv->card_sexp = card_sexp;
+ priv->max_results = max_results;
- CORBA_exception_free (&ev);
+ dbus_g_connection_register_g_object (connection, path, G_OBJECT (view));
- CORBA_free (removes->_buffer);
- removes->_buffer = NULL;
- removes->_maximum = 0;
- removes->_length = 0;
+ return view;
}
-#define MAKE_REALLOC(type) \
-static void \
-CORBA_sequence_ ## type ## _realloc (CORBA_sequence_ ## type *seq, \
- CORBA_unsigned_long new_max) \
-{ \
- type *new_buf; \
- int i; \
- new_buf = CORBA_sequence_ ## type ## _allocbuf (new_max); \
- for (i = 0; i < seq->_maximum; i ++) \
- new_buf[i] = CORBA_string_dup (seq->_buffer[i]); \
- CORBA_free (seq->_buffer); \
- seq->_buffer = new_buf; \
- seq->_maximum = new_max; \
+static void
+e_data_book_view_dispose (GObject *object)
+{
+ EDataBookView *book_view = E_DATA_BOOK_VIEW (object);
+ EDataBookViewPrivate *priv = book_view->priv;
+
+ if (priv->book) {
+ /* Remove the weak reference */
+ g_object_weak_unref (G_OBJECT (priv->book), book_destroyed_cb, book_view);
+ priv->book = NULL;
+ }
+
+ if (priv->backend) {
+ e_book_backend_remove_book_view (priv->backend, book_view);
+ g_object_unref (priv->backend);
+ priv->backend = NULL;
+ }
+
+ if (priv->card_sexp) {
+ g_object_unref (priv->card_sexp);
+ priv->card_sexp = NULL;
+ }
+
+ if (priv->idle_id) {
+ g_source_remove (priv->idle_id);
+ priv->idle_id = 0;
+ }
+
+ G_OBJECT_CLASS (e_data_book_view_parent_class)->dispose (object);
}
-MAKE_REALLOC (GNOME_Evolution_Addressbook_VCard)
-MAKE_REALLOC (GNOME_Evolution_Addressbook_ContactId)
-
static void
-notify_change (EDataBookView *book_view, const char *vcard)
+e_data_book_view_finalize (GObject *object)
{
- CORBA_sequence_GNOME_Evolution_Addressbook_VCard *changes;
+ EDataBookView *book_view = E_DATA_BOOK_VIEW (object);
+ EDataBookViewPrivate *priv = book_view->priv;
- send_pending_adds (book_view, TRUE);
- send_pending_removes (book_view);
+ 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);
- changes = &book_view->priv->changes;
+ g_free (priv->card_query);
- if (changes->_length == changes->_maximum) {
- CORBA_sequence_GNOME_Evolution_Addressbook_VCard_realloc (
- changes, 2 * (changes->_maximum + 1));
- }
+ g_mutex_free (priv->pending_mutex);
- changes->_buffer[changes->_length++] = CORBA_string_dup (vcard);
+ g_hash_table_destroy (priv->ids);
+
+ G_OBJECT_CLASS (e_data_book_view_parent_class)->finalize (object);
}
-static void
-notify_remove (EDataBookView *book_view, const char *id)
+static gboolean
+bookview_idle_start (gpointer data)
{
- CORBA_sequence_GNOME_Evolution_Addressbook_ContactId *removes;
-
- send_pending_adds (book_view, TRUE);
- send_pending_changes (book_view);
+ EDataBookView *book_view = data;
- removes = &book_view->priv->removes;
+ book_view->priv->running = TRUE;
+ book_view->priv->idle_id = 0;
- if (removes->_length == removes->_maximum) {
- CORBA_sequence_GNOME_Evolution_Addressbook_ContactId_realloc (
- removes, 2 * (removes->_maximum + 1));
- }
-
- removes->_buffer[removes->_length++] = CORBA_string_dup (id);
- g_hash_table_remove (book_view->priv->ids, id);
+ e_book_backend_start_book_view (book_view->priv->backend, book_view);
+ return FALSE;
}
-static void
-notify_add (EDataBookView *book_view, const char *id, const char *vcard)
+static gboolean
+impl_BookView_start (EDataBookView *book_view, GError **error)
{
- CORBA_sequence_GNOME_Evolution_Addressbook_VCard *adds;
- EDataBookViewPrivate *priv = book_view->priv;
-
- send_pending_changes (book_view);
- send_pending_removes (book_view);
-
- adds = &priv->adds;
+ book_view->priv->idle_id = g_idle_add (bookview_idle_start, book_view);
+ return TRUE;
+}
- if (adds->_length == adds->_maximum) {
- send_pending_adds (book_view, FALSE);
+static gboolean
+bookview_idle_stop (gpointer data)
+{
+ EDataBookView *book_view = data;
- adds->_buffer = CORBA_sequence_GNOME_Evolution_Addressbook_VCard_allocbuf (priv->next_threshold);
- adds->_maximum = priv->next_threshold;
+ e_book_backend_stop_book_view (book_view->priv->backend, book_view);
- if (priv->next_threshold < priv->threshold_max) {
- priv->next_threshold = MIN (2 * priv->next_threshold,
- priv->threshold_max);
- }
- }
+ book_view->priv->running = FALSE;
+ book_view->priv->idle_id = 0;
- adds->_buffer[adds->_length++] = CORBA_string_dup (vcard);
- g_hash_table_insert (book_view->priv->ids, g_strdup (id),
- GUINT_TO_POINTER (1));
+ return FALSE;
}
-/**
- * e_data_book_view_notify_update:
- * @book_view: an #EDataBookView
- * @contact: an #EContact
- *
- * Notify listeners that @contact has changed. This can
- * trigger an add, change or removal event depending on
- * whether the change causes the contact to start matching,
- * no longer match, or stay matching the query specified
- * by @book_view.
- **/
-void
-e_data_book_view_notify_update (EDataBookView *book_view,
- EContact *contact)
+static gboolean
+impl_BookView_stop (EDataBookView *book_view, GError **error)
{
- gboolean currently_in_view, want_in_view;
- const char *id=NULL;
- char *vcard;
-
- g_mutex_lock (book_view->priv->pending_mutex);
-
- id = e_contact_get_const (contact, E_CONTACT_UID);
- if (!id) {
- g_mutex_unlock (book_view->priv->pending_mutex);
- return;
- }
-
- currently_in_view =
- g_hash_table_lookup (book_view->priv->ids, id) != NULL;
- want_in_view = e_book_backend_sexp_match_contact (
- book_view->priv->card_sexp, contact);
-
- if (want_in_view) {
- vcard = e_vcard_to_string (E_VCARD (contact),
- EVC_FORMAT_VCARD_30);
-
- if (currently_in_view)
- notify_change (book_view, vcard);
- else
- notify_add (book_view, id, vcard);
-
- g_free (vcard);
- } else {
- if (currently_in_view)
- notify_remove (book_view, id);
- /* else nothing; we're removing a card that wasn't there */
- }
-
- g_mutex_unlock (book_view->priv->pending_mutex);
+ if (book_view->priv->idle_id)
+ g_source_remove (book_view->priv->idle_id);
+
+ book_view->priv->idle_id = g_idle_add (bookview_idle_stop, book_view);
+ return TRUE;
}
-/**
- * e_data_book_view_notify_update_vcard:
- * @book_view: an #EDataBookView
- * @vcard: a plain vCard
- *
- * Notify listeners that @vcard has changed. This can
- * trigger an add, change or removal event depending on
- * whether the change causes the contact to start matching,
- * no longer match, or stay matching the query specified
- * by @book_view. This method should be preferred over
- * #e_data_book_view_notify_update when the native
- * representation of a contact is a vCard.
- **/
-void
-e_data_book_view_notify_update_vcard (EDataBookView *book_view, char *vcard)
+static gboolean
+impl_BookView_dispose (EDataBookView *book_view, GError **eror)
{
- gboolean currently_in_view, want_in_view;
- const char *id = NULL;
- EContact *contact;
-
- g_mutex_lock (book_view->priv->pending_mutex);
-
- contact = e_contact_new_from_vcard (vcard);
- id = e_contact_get_const (contact, E_CONTACT_UID);
- if (!id) {
- free (vcard);
- g_object_unref (contact);
- g_mutex_unlock (book_view->priv->pending_mutex);
- return;
- }
-
- currently_in_view =
- g_hash_table_lookup (book_view->priv->ids, id) != NULL;
- want_in_view =
- e_book_backend_sexp_match_contact (book_view->priv->card_sexp, contact);
-
- if (want_in_view) {
- if (currently_in_view)
- notify_change (book_view, vcard);
- else
- notify_add (book_view, id, vcard);
- } else {
- if (currently_in_view)
- notify_remove (book_view, id);
- }
-
- g_free (vcard);
- g_object_unref (contact);
- g_mutex_unlock (book_view->priv->pending_mutex);
+ g_object_unref (book_view);
+
+ return TRUE;
}
-/**
- * e_data_book_view_notify_update_prefiltered_vcard:
- * @book_view: an #EDataBookView
- * @id: the UID of this contact
- * @vcard: a plain vCard
- *
- * Notify listeners that @vcard has changed. This can
- * trigger an add, change or removal event depending on
- * whether the change causes the contact to start matching,
- * no longer match, or stay matching the query specified
- * by @book_view. This method should be preferred over
- * #e_data_book_view_notify_update when the native
- * representation of a contact is a vCard.
- *
- * The important difference between this method and
- * #e_data_book_view_notify_update and #e_data_book_view_notify_update_vcard is
- * that it doesn't match the contact against the book view query to see if it
- * should be included, it assumes that this has been done and the contact is
- * known to exist in the view.
- **/
void
-e_data_book_view_notify_update_prefiltered_vcard (EDataBookView *book_view, const char *id, char *vcard)
+e_data_book_view_set_thresholds (EDataBookView *book_view,
+ int minimum_grouping_threshold,
+ int maximum_grouping_threshold)
{
- gboolean currently_in_view;
-
- g_mutex_lock (book_view->priv->pending_mutex);
-
- currently_in_view =
- g_hash_table_lookup (book_view->priv->ids, id) != NULL;
-
- if (currently_in_view)
- notify_change (book_view, vcard);
- else
- notify_add (book_view, id, vcard);
-
- g_free (vcard);
- g_mutex_unlock (book_view->priv->pending_mutex);
+ 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_notify_remove:
- * @book_view: an #EDataBookView
- * @id: a unique contact ID
- *
- * Notify listeners that a contact specified by @id
- * was removed from @book_view.
- **/
-void
-e_data_book_view_notify_remove (EDataBookView *book_view,
- const char *id)
+const char*
+e_data_book_view_get_card_query (EDataBookView *book_view)
{
- g_mutex_lock (book_view->priv->pending_mutex);
-
- if (g_hash_table_lookup (book_view->priv->ids, id))
- notify_remove (book_view, id);
-
- g_mutex_unlock (book_view->priv->pending_mutex);
+ g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL);
+ return book_view->priv->card_query;
}
-/**
- * e_data_book_view_notify_complete:
- * @book_view: an #EDataBookView
- * @status: the status of the query
- *
- * Notifies listeners that all pending updates on @book_view
- * have been sent. The listener's information should now be
- * in sync with the backend's.
- **/
-void
-e_data_book_view_notify_complete (EDataBookView *book_view,
- GNOME_Evolution_Addressbook_CallStatus status)
+EBookBackendSExp*
+e_data_book_view_get_card_sexp (EDataBookView *book_view)
{
- CORBA_Environment ev;
-
- g_mutex_lock (book_view->priv->pending_mutex);
-
- send_pending_adds (book_view, TRUE);
- send_pending_changes (book_view);
- send_pending_removes (book_view);
-
- g_mutex_unlock (book_view->priv->pending_mutex);
-
- CORBA_exception_init (&ev);
-
- GNOME_Evolution_Addressbook_BookViewListener_notifySequenceComplete (
- book_view->priv->listener, status, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_data_book_view_notify_complete: Exception signaling BookViewListener!\n");
- }
-
- CORBA_exception_free (&ev);
+ g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL);
+ return book_view->priv->card_sexp;
}
-/**
- * e_data_book_view_notify_status_message:
- * @book_view: an #EDataBookView
- * @message: a text message
- *
- * Provides listeners with a human-readable text describing the
- * current backend operation. This can be used for progress
- * reporting.
- **/
-void
-e_data_book_view_notify_status_message (EDataBookView *book_view,
- const char *message)
+int
+e_data_book_view_get_max_results (EDataBookView *book_view)
{
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
-
- GNOME_Evolution_Addressbook_BookViewListener_notifyProgress (
- book_view->priv->listener, message, 0, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_data_book_view_notify_status_message: Exception signaling BookViewListener!\n");
- }
+ g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), 0);
+ return book_view->priv->max_results;
+}
- CORBA_exception_free (&ev);
+EBookBackend*
+e_data_book_view_get_backend (EDataBookView *book_view)
+{
+ g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL);
+ return book_view->priv->backend;
}
static void
-e_data_book_view_construct (EDataBookView *book_view,
- EBookBackend *backend,
- GNOME_Evolution_Addressbook_BookViewListener listener,
- const char *card_query,
- EBookBackendSExp *card_sexp,
- int max_results)
+send_pending_adds (EDataBookView *view)
{
- EDataBookViewPrivate *priv;
- CORBA_Environment ev;
-
- g_return_if_fail (book_view != NULL);
- g_return_if_fail (listener != CORBA_OBJECT_NIL);
-
- priv = book_view->priv;
+ EDataBookViewPrivate *priv = view->priv;
- CORBA_exception_init (&ev);
+ if (priv->adds->len == 0)
+ return;
- priv->listener = bonobo_object_dup_ref (listener, &ev);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning("Unable to duplicate listener object in pas-book-view.c\n");
- CORBA_exception_free (&ev);
- return;
- }
+ g_signal_emit (view, signals[CONTACTS_ADDED], 0, priv->adds->data);
+ reset_array (priv->adds);
+}
- CORBA_exception_free (&ev);
+static void
+send_pending_changes (EDataBookView *view)
+{
+ EDataBookViewPrivate *priv = view->priv;
- priv->backend = backend;
- priv->card_query = g_strdup (card_query);
- priv->card_sexp = card_sexp;
- priv->max_results = max_results;
+ if (priv->changes->len == 0)
+ return;
- ORBit_small_listen_for_broken (e_data_book_view_get_listener (book_view), G_CALLBACK (view_listener_died_cb), book_view);
+ g_signal_emit (view, signals[CONTACTS_CHANGED], 0, priv->changes->data);
+ reset_array (priv->changes);
}
static void
-impl_GNOME_Evolution_Addressbook_BookView_start (PortableServer_Servant servant,
- CORBA_Environment *ev)
+send_pending_removes (EDataBookView *view)
{
- EDataBookView *view = E_DATA_BOOK_VIEW (bonobo_object (servant));
+ EDataBookViewPrivate *priv = view->priv;
- e_book_backend_start_book_view (e_data_book_view_get_backend (view), view);
+ if (priv->removes->len == 0)
+ return;
+
+ g_signal_emit (view, signals[CONTACTS_REMOVED], 0, priv->removes->data);
+ reset_array (priv->removes);
}
static void
-impl_GNOME_Evolution_Addressbook_BookView_stop (PortableServer_Servant servant,
- CORBA_Environment *ev)
+notify_change (EDataBookView *view, char *vcard)
{
- EDataBookView *view = E_DATA_BOOK_VIEW (bonobo_object (servant));
-
- e_book_backend_stop_book_view (e_data_book_view_get_backend (view), view);
+ EDataBookViewPrivate *priv = view->priv;
+ send_pending_adds (view);
+ send_pending_removes (view);
+
+ g_array_append_val (priv->changes, vcard);
}
static void
-impl_GNOME_Evolution_Addressbook_BookView_dispose (PortableServer_Servant servant,
- CORBA_Environment *ev)
+notify_remove (EDataBookView *view, char *id)
{
- EDataBookView *view = E_DATA_BOOK_VIEW (bonobo_object (servant));
+ EDataBookViewPrivate *priv = view->priv;
- d(printf("in impl_GNOME_Evolution_Addressbook_BookView_dispose\n"));
- ORBit_small_unlisten_for_broken (e_data_book_view_get_listener (view), G_CALLBACK (view_listener_died_cb));
+ send_pending_adds (view);
+ send_pending_changes (view);
- bonobo_object_unref (view);
+ g_array_append_val (priv->removes, id);
+ g_hash_table_remove (priv->ids, id);
}
-/**
- * e_data_book_view_get_card_query:
- * @book_view: an #EDataBookView
- *
- * Gets the text representation of the s-expression used
- * for matching contacts to @book_view.
- *
- * Return value: The textual s-expression used.
- **/
-const char*
-e_data_book_view_get_card_query (EDataBookView *book_view)
+static void
+notify_add (EDataBookView *view, const char *id, char *vcard)
{
- g_return_val_if_fail (book_view, NULL);
-
- return book_view->priv->card_query;
+ EDataBookViewPrivate *priv = view->priv;
+ send_pending_changes (view);
+ send_pending_removes (view);
+
+ if (priv->adds->len == THRESHOLD) {
+ send_pending_adds (view);
+ }
+ g_array_append_val (priv->adds, vcard);
+ g_hash_table_insert (priv->ids, g_strdup (id),
+ GUINT_TO_POINTER (1));
}
-/**
- * e_data_book_view_get_card_sexp:
- * @book_view: an #EDataBookView
- *
- * Gets the s-expression used for matching contacts to
- * @book_view.
- *
- * Return value: The #EBookBackendSExp used.
- **/
-EBookBackendSExp*
-e_data_book_view_get_card_sexp (EDataBookView *book_view)
+void
+e_data_book_view_notify_update (EDataBookView *book_view, EContact *contact)
{
- g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL);
-
- return book_view->priv->card_sexp;
+ EDataBookViewPrivate *priv = book_view->priv;
+ gboolean currently_in_view, want_in_view;
+ const char *id;
+ char *vcard;
+
+ if (!priv->running)
+ return;
+
+ g_mutex_lock (priv->pending_mutex);
+
+ id = e_contact_get_const (contact, E_CONTACT_UID);
+
+ currently_in_view =
+ g_hash_table_lookup (priv->ids, id) != NULL;
+ want_in_view =
+ e_book_backend_sexp_match_contact (priv->card_sexp, contact);
+
+ if (want_in_view) {
+ vcard = e_vcard_to_string (E_VCARD (contact),
+ EVC_FORMAT_VCARD_30);
+
+ if (currently_in_view)
+ notify_change (book_view, vcard);
+ else
+ notify_add (book_view, id, vcard);
+ } else {
+ if (currently_in_view)
+ notify_remove (book_view, g_strdup (id));
+ /* else nothing; we're removing a card that wasn't there */
+ }
+
+ g_mutex_unlock (priv->pending_mutex);
}
-/**
- * e_data_book_view_get_max_results:
- * @book_view: an #EDataBookView
- *
- * Gets the maximum number of results returned by
- * @book_view's query.
- *
- * Return value: The maximum number of results returned.
- **/
-int
-e_data_book_view_get_max_results (EDataBookView *book_view)
+void
+e_data_book_view_notify_update_vcard (EDataBookView *book_view, char *vcard)
{
- g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), 0);
-
- return book_view->priv->max_results;
+ EDataBookViewPrivate *priv = book_view->priv;
+ gboolean currently_in_view, want_in_view;
+ const char *id;
+ EContact *contact;
+
+ if (!priv->running)
+ return;
+
+ g_mutex_lock (priv->pending_mutex);
+
+ contact = e_contact_new_from_vcard (vcard);
+ id = e_contact_get_const (contact, E_CONTACT_UID);
+ currently_in_view =
+ g_hash_table_lookup (priv->ids, id) != NULL;
+ want_in_view =
+ e_book_backend_sexp_match_contact (priv->card_sexp, contact);
+
+ if (want_in_view) {
+ if (currently_in_view)
+ notify_change (book_view, vcard);
+ else
+ notify_add (book_view, id, vcard);
+ } else {
+ if (currently_in_view)
+ notify_remove (book_view, g_strdup (id));
+ else
+ /* else nothing; we're removing a card that wasn't there */
+ g_free (vcard);
+ }
+ /* Do this last so that id is still valid when notify_ is called */
+ g_object_unref (contact);
+
+ g_mutex_unlock (priv->pending_mutex);
}
-/**
- * e_data_book_view_get_backend:
- * @book_view: an #EDataBookView
- *
- * Gets the backend that @book_view is querying.
- *
- * Return value: The associated #EBookBackend.
- **/
-EBookBackend*
-e_data_book_view_get_backend (EDataBookView *book_view)
+void
+e_data_book_view_notify_update_prefiltered_vcard (EDataBookView *book_view, const char *id, char *vcard)
{
- g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL);
+ EDataBookViewPrivate *priv = book_view->priv;
+ gboolean currently_in_view;
- return book_view->priv->backend;
-}
+ if (!priv->running)
+ return;
-/**
- * e_data_book_view_get_mutex:
- * @book_view: an #EDataBookView
- *
- * Gets the internal mutex of @book_view.
- *
- * Return value: The #GMutex for @book_view.
- **/
-GMutex*
-e_data_book_view_get_mutex (EDataBookView *book_view)
-{
- g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), NULL);
+ g_mutex_lock (priv->pending_mutex);
- return book_view->priv->mutex;
-}
+ currently_in_view =
+ g_hash_table_lookup (priv->ids, id) != NULL;
-/**
- * e_data_book_view_get_listener:
- * @book_view: an #EDataBookView
- *
- * Gets the CORBA listener that @book_view is dispatching
- * events to.
- *
- * Return value: The CORBA book view listener.
- **/
-GNOME_Evolution_Addressbook_BookViewListener
-e_data_book_view_get_listener (EDataBookView *book_view)
-{
- g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (book_view), CORBA_OBJECT_NIL);
+ if (currently_in_view)
+ notify_change (book_view, vcard);
+ else
+ notify_add (book_view, id, vcard);
- return book_view->priv->listener;
+ g_mutex_unlock (priv->pending_mutex);
}
-/**
- * e_data_book_view_set_thresholds:
- * @book_view: an #EDataBookView
- * @minimum_grouping_threshold: the minimum threshold
- * @maximum_grouping_threshold: the maximum threshold
- *
- * Sets the thresholds for grouping add events together
- * for efficiency reasons. The minimum threshold specifies
- * how many adds must be grouped (as long as there are
- * pending adds), and the maximum threshold specifies
- * the maximum number of adds that can be grouped.
- **/
void
-e_data_book_view_set_thresholds (EDataBookView *book_view,
- int minimum_grouping_threshold,
- int maximum_grouping_threshold)
+e_data_book_view_notify_remove (EDataBookView *book_view, const char *id)
{
- book_view->priv->threshold_min = minimum_grouping_threshold;
- book_view->priv->threshold_max = maximum_grouping_threshold;
+ EDataBookViewPrivate *priv = E_DATA_BOOK_VIEW_GET_PRIVATE (book_view);
+
+ if (!priv->running)
+ return;
+
+ g_mutex_lock (priv->pending_mutex);
+
+ if (g_hash_table_lookup (priv->ids, id))
+ notify_remove (book_view, g_strdup (id));
+
+ g_mutex_unlock (priv->pending_mutex);
}
-/**
- * e_data_book_view_new:
- * @backend: an #EBookBackend to view
- * @listener: a CORBA listener to reveive notifications
- * @card_query: an s-expression representing the query
- * @card_sexp:
- * @max_results: the maximum number of results for the query
- *
- * Return value: A new #EDataBookView.
- **/
-EDataBookView *
-e_data_book_view_new (EBookBackend *backend,
- GNOME_Evolution_Addressbook_BookViewListener listener,
- const char *card_query,
- EBookBackendSExp *card_sexp,
- int max_results)
+void
+e_data_book_view_notify_complete (EDataBookView *book_view, EDataBookStatus status)
{
- static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
- static PortableServer_POA poa = NULL;
- EDataBookView *book_view;
+ EDataBookViewPrivate *priv = book_view->priv;
+
+ if (!priv->running)
+ return;
- g_static_mutex_lock (&mutex);
- if (poa == NULL)
- poa = bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_OBJECT, NULL);
- g_static_mutex_unlock (&mutex);
+ g_mutex_lock (priv->pending_mutex);
- book_view = g_object_new (E_TYPE_DATA_BOOK_VIEW, "poa", poa, NULL);
+ send_pending_adds (book_view);
+ send_pending_changes (book_view);
+ send_pending_removes (book_view);
- e_data_book_view_construct (book_view, backend, listener, card_query, card_sexp, max_results);
+ 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... */
- return book_view;
+ g_signal_emit (book_view, signals[COMPLETE], 0, status);
+}
+
+void
+e_data_book_view_notify_status_message (EDataBookView *book_view, const char *message)
+{
+ EDataBookViewPrivate *priv = E_DATA_BOOK_VIEW_GET_PRIVATE (book_view);
+
+ if (!priv->running)
+ return;
+
+ g_signal_emit (book_view, signals[STATUS_MESSAGE], 0, message);
}
/**
@@ -674,9 +562,9 @@ e_data_book_view_new (EBookBackend *backend,
* the transition from Bonobo to DBUS.
*/
void
-e_data_book_view_ref (EDataBookView *book_view)
+e_data_book_view_ref (EDataBookView *view)
{
- bonobo_object_ref (book_view);
+ g_object_ref (view);
}
/**
@@ -687,80 +575,24 @@ e_data_book_view_ref (EDataBookView *book_view)
* the transition from Bonobo to DBUS.
*/
void
-e_data_book_view_unref (EDataBookView *book_view)
-{
- bonobo_object_unref (book_view);
-}
-
-static void
-e_data_book_view_dispose (GObject *object)
+e_data_book_view_unref (EDataBookView *view)
{
- EDataBookView *book_view = E_DATA_BOOK_VIEW (object);
-
- d(printf ("disposing of EDataBookView\n"));
- if (book_view->priv) {
- bonobo_object_release_unref (book_view->priv->listener, NULL);
-
- if (book_view->priv->adds._buffer)
- CORBA_free (book_view->priv->adds._buffer);
- if (book_view->priv->changes._buffer)
- CORBA_free (book_view->priv->changes._buffer);
- if (book_view->priv->removes._buffer)
- CORBA_free (book_view->priv->removes._buffer);
-
- g_free (book_view->priv->card_query);
- g_object_unref (book_view->priv->card_sexp);
-
- g_mutex_free (book_view->priv->pending_mutex);
-
- g_mutex_free (book_view->priv->mutex);
-
- g_hash_table_destroy (book_view->priv->ids);
-
- g_free (book_view->priv);
- book_view->priv = NULL;
- }
-
- if (G_OBJECT_CLASS (e_data_book_view_parent_class)->dispose)
- G_OBJECT_CLASS (e_data_book_view_parent_class)->dispose (object);
+ g_object_unref (view);
}
static void
-e_data_book_view_class_init (EDataBookViewClass *klass)
+reset_array (GArray *array)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- POA_GNOME_Evolution_Addressbook_BookView__epv *epv;
-
- e_data_book_view_parent_class = g_type_class_peek_parent (klass);
-
- object_class->dispose = e_data_book_view_dispose;
-
- epv = &klass->epv;
-
- epv->start = impl_GNOME_Evolution_Addressbook_BookView_start;
- epv->stop = impl_GNOME_Evolution_Addressbook_BookView_stop;
- epv->dispose = impl_GNOME_Evolution_Addressbook_BookView_dispose;
-
+ gint i = 0;
+ gchar *tmp = NULL;
+
+ /* Free stored strings */
+ for (i = 0; i < array->len; i++)
+ {
+ tmp = g_array_index (array, gchar *, i);
+ g_free (tmp);
+ }
+
+ /* Force the array size to 0 */
+ g_array_set_size (array, 0);
}
-
-static void
-e_data_book_view_init (EDataBookView *book_view)
-{
- book_view->priv = g_new0 (EDataBookViewPrivate, 1);
-
- book_view->priv->pending_mutex = g_mutex_new();
- book_view->priv->mutex = g_mutex_new();
-
- book_view->priv->threshold_min = DEFAULT_INITIAL_THRESHOLD;
- book_view->priv->threshold_max = DEFAULT_THRESHOLD_MAX;
- book_view->priv->next_threshold = book_view->priv->threshold_min;
-
- book_view->priv->ids = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, NULL);
-}
-
-BONOBO_TYPE_FUNC_FULL (
- EDataBookView,
- GNOME_Evolution_Addressbook_BookView,
- BONOBO_TYPE_OBJECT,
- e_data_book_view);
diff --git a/addressbook/libedata-book/e-data-book-view.h b/addressbook/libedata-book/e-data-book-view.h
index 3304945..d0e8e23 100644
--- a/addressbook/libedata-book/e-data-book-view.h
+++ b/addressbook/libedata-book/e-data-book-view.h
@@ -1,23 +1,36 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * A wrapper object which exports the GNOME_Evolution_Addressbook_Book CORBA interface
- * and which maintains a request queue.
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
*
- * Author:
- * Nat Friedman (nat 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.
*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Nat Friedman <nat ximian com>
+ * Author: Ross Burton <ross linux intel com>
*/
#ifndef __E_DATA_BOOK_VIEW_H__
#define __E_DATA_BOOK_VIEW_H__
-#include <bonobo/bonobo-object.h>
#include <glib.h>
#include <glib-object.h>
+#include <dbus/dbus-glib.h>
#include <libebook/e-contact.h>
-#include <libedata-book/Evolution-DataServer-Addressbook.h>
-#include <libedata-book/e-data-book-types.h>
+#include "e-data-book-types.h"
+#include "e-book-backend.h"
+#include "e-book-backend-sexp.h"
G_BEGIN_DECLS
@@ -31,49 +44,43 @@ G_BEGIN_DECLS
typedef struct _EDataBookViewPrivate EDataBookViewPrivate;
struct _EDataBookView {
- BonoboObject parent_object;
- EDataBookViewPrivate *priv;
+ GObject parent;
+ EDataBookViewPrivate *priv;
};
struct _EDataBookViewClass {
- BonoboObjectClass parent_class;
-
- POA_GNOME_Evolution_Addressbook_BookView__epv epv;
+ GObjectClass parent;
};
-
-EDataBookView *e_data_book_view_new (EBookBackend *backend,
- GNOME_Evolution_Addressbook_BookViewListener listener,
- const char *card_query,
- EBookBackendSExp *card_sexp,
- int max_results);
+EDataBookView * e_data_book_view_new (EDataBook *book,
+ const char *path,
+ const char *card_query,
+ EBookBackendSExp *card_sexp,
+ int max_results);
void e_data_book_view_set_thresholds (EDataBookView *book_view,
- int minimum_grouping_threshold,
- int maximum_grouping_threshold);
-
-const char* e_data_book_view_get_card_query (EDataBookView *book_view);
-EBookBackendSExp* e_data_book_view_get_card_sexp (EDataBookView *book_view);
-int e_data_book_view_get_max_results (EDataBookView *book_view);
-EBookBackend* e_data_book_view_get_backend (EDataBookView *book_view);
-GNOME_Evolution_Addressbook_BookViewListener e_data_book_view_get_listener (EDataBookView *book_view);
-GMutex* e_data_book_view_get_mutex (EDataBookView *book_view);
+ int minimum_grouping_threshold,
+ int maximum_grouping_threshold);
-void e_data_book_view_notify_update (EDataBookView *book_view,
- EContact *contact);
+const char * e_data_book_view_get_card_query (EDataBookView *book_view);
+EBookBackendSExp * e_data_book_view_get_card_sexp (EDataBookView *book_view);
+int 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_update_vcard (EDataBookView *book_view,
- char *vcard);
+ char *vcard);
void e_data_book_view_notify_update_prefiltered_vcard (EDataBookView *book_view,
const char *id,
char *vcard);
-
void e_data_book_view_notify_remove (EDataBookView *book_view,
- const char *id);
-void e_data_book_view_notify_complete (EDataBookView *book_view,
- GNOME_Evolution_Addressbook_CallStatus);
+ const char *id);
+void e_data_book_view_notify_complete (EDataBookView *book_view,
+ EDataBookStatus status);
void e_data_book_view_notify_status_message (EDataBookView *book_view,
- const char *message);
+ const char *message);
+
void e_data_book_view_ref (EDataBookView *book_view);
void e_data_book_view_unref (EDataBookView *book_view);
diff --git a/addressbook/libedata-book/e-data-book.c b/addressbook/libedata-book/e-data-book.c
index 5034b97..458ba6f 100644
--- a/addressbook/libedata-book/e-data-book.c
+++ b/addressbook/libedata-book/e-data-book.c
@@ -1,1016 +1,699 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * pas-book.c
- *
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * 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 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.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Ross Burton <ross linux intel com>
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <bonobo/bonobo-main.h>
-#include <bonobo/bonobo-arg.h>
-#include "libedataserver/e-list.h"
-#include <libebook/e-contact.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <glib/gi18n.h>
+#include <glib-object.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.h"
#include "e-book-backend-sexp.h"
-#include "e-data-book.h"
-
-static BonoboObjectClass *e_data_book_parent_class;
-POA_GNOME_Evolution_Addressbook_Book__vepv e_data_book_vepv;
-
-struct _EDataBookPrivate {
- EBookBackend *backend;
- GNOME_Evolution_Addressbook_BookListener listener;
- ESource *source;
+#include "opid.h"
+
+extern DBusGConnection *connection;
+
+/* DBus glue */
+static void impl_AddressBook_Book_open(EDataBook *book, gboolean only_if_exists, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_remove(EDataBook *book, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_getContact(EDataBook *book, const char *IN_uid, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_getContactList(EDataBook *book, const char *query, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_authenticateUser(EDataBook *book, const char *IN_user, const char *IN_passwd, const char *IN_auth_method, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_addContact(EDataBook *book, const char *IN_vcard, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_modifyContact(EDataBook *book, const char *IN_vcard, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_modifyContacts(EDataBook *book, const char **IN_vcards, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_removeContacts(EDataBook *book, const char **IN_uids, DBusGMethodInvocation *context);
+static gboolean impl_AddressBook_Book_getStaticCapabilities(EDataBook *book, char **OUT_capabilities, GError **error);
+static void impl_AddressBook_Book_getSupportedFields(EDataBook *book, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_getRequiredFields(EDataBook *book, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_getSupportedAuthMethods(EDataBook *book, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_getBookView (EDataBook *book, const char *search, const guint max_results, DBusGMethodInvocation *context);
+static void impl_AddressBook_Book_getChanges(EDataBook *book, const char *IN_change_id, DBusGMethodInvocation *context);
+static gboolean impl_AddressBook_Book_cancelOperation(EDataBook *book, GError **error);
+static void impl_AddressBook_Book_close(EDataBook *book, DBusGMethodInvocation *context);
+#include "e-data-book-glue.h"
+
+static void return_status_and_list (guint32 opid, EDataBookStatus status, GList *list, gboolean free_data);
+
+enum {
+ WRITABLE,
+ CONNECTION,
+ AUTH_REQUIRED,
+ LAST_SIGNAL
};
-static void
-impl_GNOME_Evolution_Addressbook_Book_open (PortableServer_Servant servant,
- const CORBA_long opid,
- const CORBA_boolean only_if_exists,
- CORBA_Environment *ev)
-{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static GThreadPool *op_pool;
+
+typedef enum {
+ OP_OPEN,
+ OP_AUTHENTICATE,
+ OP_ADD_CONTACT,
+ OP_GET_CONTACT,
+ OP_GET_CONTACTS,
+ OP_MODIFY_CONTACT,
+ OP_REMOVE_CONTACTS,
+ OP_GET_CHANGES,
+} OperationID;
+
+typedef struct {
+ OperationID op;
+ guint32 id; /* operation id */
+ EDataBook *book; /* book */
+ union {
+ /* OP_OPEN */
+ gboolean only_if_exists;
+ /* OP_AUTHENTICATE */
+ struct {
+ char *username;
+ char *password;
+ char *method;
+ } auth;
+ /* OP_ADD_CONTACT */
+ /* OP_MODIFY_CONTACT */
+ char *vcard;
+ /* OP_GET_CONTACT */
+ char *uid;
+ /* OP_GET_CONTACTS */
+ char *query;
+ /* OP_MODIFY_CONTACT */
+ char **vcards;
+ /* OP_REMOVE_CONTACTS */
+ GList *ids;
+ /* OP_GET_CHANGES */
+ char *change_id;
+ };
+} OperationData;
- printf ("impl_GNOME_Evolution_Addressbook_Book_open (%p)\n", book);
-
- e_book_backend_open (e_data_book_get_backend (book), book, opid, only_if_exists);
-}
static void
-impl_GNOME_Evolution_Addressbook_Book_remove (PortableServer_Servant servant,
- const CORBA_long opid,
- CORBA_Environment *ev)
-{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
- printf ("impl_GNOME_Evolution_Addressbook_Book_remove\n");
-
- e_book_backend_remove (e_data_book_get_backend (book), book, opid);
-}
+operation_thread (gpointer data, gpointer user_data)
+{
+ OperationData *op = data;
+ EBookBackend *backend;
+
+ backend = e_data_book_get_backend (op->book);
+
+ switch (op->op) {
+ case OP_OPEN:
+ e_book_backend_open (backend, op->book, op->id, op->only_if_exists);
+ break;
+ case OP_AUTHENTICATE:
+ e_book_backend_authenticate_user (backend, op->book, op->id,
+ op->auth.username,
+ op->auth.password,
+ op->auth.method);
+ g_free (op->auth.username);
+ g_free (op->auth.password);
+ g_free (op->auth.method);
+ break;
+ case OP_ADD_CONTACT:
+ e_book_backend_create_contact (backend, op->book, op->id, op->vcard);
+ g_free (op->vcard);
+ break;
+ case OP_GET_CONTACT:
+ e_book_backend_get_contact (backend, op->book, op->id, op->uid);
+ g_free (op->uid);
+ break;
+ case OP_GET_CONTACTS:
+ e_book_backend_get_contact_list (backend, op->book, op->id, op->query);
+ g_free (op->query);
+ break;
+ case OP_MODIFY_CONTACT:
+ e_book_backend_modify_contact (backend, op->book, op->id, op->vcard);
+ g_free (op->vcard);
+ break;
+ case OP_REMOVE_CONTACTS:
+ e_book_backend_remove_contacts (backend, op->book, op->id, op->ids);
+ g_list_foreach (op->ids, (GFunc)g_free, NULL);
+ g_list_free (op->ids);
+ break;
+ case OP_GET_CHANGES:
+ e_book_backend_get_changes (backend, op->book, op->id, op->change_id);
+ g_free (op->change_id);
+ break;
+ }
+
+ g_object_unref (op->book);
+ g_slice_free (OperationData, op);
+}
+
+static OperationData *
+op_new (OperationID op, EDataBook *book, DBusGMethodInvocation *context)
+{
+ OperationData *data;
+
+ data = g_slice_new0 (OperationData);
+ data->op = op;
+ data->book = g_object_ref (book);
+ data->id = opid_store (context);
+
+ return data;
+}
+
+
+/* Create the EDataBook error quark */
+GQuark
+e_data_book_error_quark (void)
+{
+ static GQuark quark = 0;
+ if (G_UNLIKELY (quark == 0))
+ quark = g_quark_from_static_string ("e-data-book-error");
+ return quark;
+}
+
+
+/* Generate the GObject boilerplate */
+G_DEFINE_TYPE(EDataBook, e_data_book, G_TYPE_OBJECT)
static void
-impl_GNOME_Evolution_Addressbook_Book_getContact (PortableServer_Servant servant,
- const CORBA_long opid,
- const CORBA_char *id,
- CORBA_Environment *ev)
+e_data_book_dispose (GObject *object)
{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
+ EDataBook *book = E_DATA_BOOK (object);
+
+ if (book->backend) {
+ g_object_unref (book->backend);
+ book->backend = NULL;
+ }
- printf ("impl_GNOME_Evolution_Addressbook_Book_getContact\n");
-
- e_book_backend_get_contact (e_data_book_get_backend (book), book, opid, id);
+ if (book->source) {
+ g_object_unref (book->source);
+ book->source = NULL;
+ }
+
+ G_OBJECT_CLASS (e_data_book_parent_class)->dispose (object);
}
static void
-impl_GNOME_Evolution_Addressbook_Book_getContactList (PortableServer_Servant servant,
- const CORBA_long opid,
- const CORBA_char *query,
- CORBA_Environment *ev)
+e_data_book_class_init (EDataBookClass *e_data_book_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (e_data_book_class);
+
+ object_class->dispose = e_data_book_dispose;
+
+ signals[WRITABLE] =
+ g_signal_new ("writable",
+ G_OBJECT_CLASS_TYPE (e_data_book_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+ signals[CONNECTION] =
+ g_signal_new ("connection",
+ G_OBJECT_CLASS_TYPE (e_data_book_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+ signals[AUTH_REQUIRED] =
+ g_signal_new ("auth-required",
+ G_OBJECT_CLASS_TYPE (e_data_book_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (e_data_book_class), &dbus_glib_e_data_book_object_info);
+
+ dbus_g_error_domain_register (E_DATA_BOOK_ERROR, NULL, E_TYPE_DATA_BOOK_STATUS);
+
+ 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);
+}
+
+/* Instance init */
+static void
+e_data_book_init (EDataBook *ebook)
{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
- printf ("impl_GNOME_Evolution_Addressbook_Book_getContactList\n");
-
- e_book_backend_get_contact_list (e_data_book_get_backend (book), book, opid, query);
}
-static void
-impl_GNOME_Evolution_Addressbook_Book_authenticateUser (PortableServer_Servant servant,
- const CORBA_long opid,
- const char* user,
- const char* passwd,
- const char* auth_method,
- CORBA_Environment *ev)
+EDataBook *
+e_data_book_new (EBookBackend *backend, ESource *source, EDataBookClosedCallback closed_cb)
{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
- e_book_backend_authenticate_user (e_data_book_get_backend (book), book,
- opid, user, passwd, auth_method);
+ EDataBook *book;
+ book = g_object_new (E_TYPE_DATA_BOOK, NULL);
+ book->backend = g_object_ref (backend);
+ book->source = g_object_ref (source);
+ book->closed_cb = closed_cb;
+ return book;
}
-static void
-impl_GNOME_Evolution_Addressbook_Book_addContact (PortableServer_Servant servant,
- const CORBA_long opid,
- const CORBA_char *vcard,
- CORBA_Environment *ev)
+ESource*
+e_data_book_get_source (EDataBook *book)
{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
+ g_return_val_if_fail (book != NULL, NULL);
- e_book_backend_create_contact (e_data_book_get_backend (book), book, opid, vcard);
+ return book->source;
}
-static void
-impl_GNOME_Evolution_Addressbook_Book_removeContacts (PortableServer_Servant servant,
- const CORBA_long opid,
- const GNOME_Evolution_Addressbook_ContactIdList *ids,
- CORBA_Environment *ev)
+EBookBackend*
+e_data_book_get_backend (EDataBook *book)
{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
- int i;
- GList *id_list = NULL;
-
- for (i = 0; i < ids->_length; i ++)
- id_list = g_list_append (id_list, ids->_buffer[i]);
-
- e_book_backend_remove_contacts (e_data_book_get_backend (book), book, opid, id_list);
+ g_return_val_if_fail (book != NULL, NULL);
- g_list_free (id_list);
+ return book->backend;
}
static void
-impl_GNOME_Evolution_Addressbook_Book_modifyContact (PortableServer_Servant servant,
- const CORBA_long opid,
- const CORBA_char *vcard,
- CORBA_Environment *ev)
+impl_AddressBook_Book_open(EDataBook *book, gboolean only_if_exists, DBusGMethodInvocation *context)
{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
- e_book_backend_modify_contact (e_data_book_get_backend (book), book, opid, vcard);
+ OperationData *op;
+
+ op = op_new (OP_OPEN, book, context);
+ op->only_if_exists = only_if_exists;
+ g_thread_pool_push (op_pool, op, NULL);
}
-static void
-impl_GNOME_Evolution_Addressbook_Book_getBookView (PortableServer_Servant servant,
- const CORBA_long opid,
- const GNOME_Evolution_Addressbook_BookViewListener listener,
- const CORBA_char *search,
- const GNOME_Evolution_Addressbook_stringlist* requested_fields,
- const CORBA_long max_results,
- CORBA_Environment *ev)
+void
+e_data_book_respond_open (EDataBook *book, guint opid, EDataBookStatus status)
{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
- EBookBackend *backend = e_data_book_get_backend (book);
- EBookBackendSExp *card_sexp;
- EDataBookView *view;
-
- g_warning ("impl_GNOME_Evolution_Addressbook_Book_getBookView (%s)\n", search);
-
- /* we handle this entirely here, since it doesn't require any
- backend involvement now that we have e_data_book_view_start to
- actually kick off the search. */
-
- card_sexp = e_book_backend_sexp_new (search);
- if (!card_sexp) {
- e_data_book_respond_get_book_view (book, opid, GNOME_Evolution_Addressbook_InvalidQuery, NULL);
- return;
- }
+ DBusGMethodInvocation *context = opid_fetch (opid);
- /* XXX still need to add requested_fields here */
- view = e_data_book_view_new (backend, listener, search, card_sexp, max_results);
-
- if (!view) {
- g_object_unref (card_sexp);
- e_data_book_respond_get_book_view (book, opid, GNOME_Evolution_Addressbook_OtherError, NULL);
- return;
- }
-
- e_book_backend_add_book_view (backend, view);
-
- e_data_book_respond_get_book_view (book, opid, GNOME_Evolution_Addressbook_Success, view);
+ if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot open book")));
+ } else {
+ dbus_g_method_return (context);
+ }
}
-
static void
-impl_GNOME_Evolution_Addressbook_Book_getChanges (PortableServer_Servant servant,
- const CORBA_long opid,
- const CORBA_char *change_id,
- CORBA_Environment *ev)
+impl_AddressBook_Book_remove(EDataBook *book, DBusGMethodInvocation *context)
{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
- e_book_backend_get_changes (e_data_book_get_backend (book), book, opid, change_id);
+ e_book_backend_remove (book->backend, book, opid_store (context));
}
-static char *
-impl_GNOME_Evolution_Addressbook_Book_getStaticCapabilities (PortableServer_Servant servant,
- CORBA_Environment *ev)
+void
+e_data_book_respond_remove (EDataBook *book, guint opid, EDataBookStatus status)
{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
- char *temp;
- char *ret_val;
+ DBusGMethodInvocation *context = opid_fetch (opid);
- temp = e_book_backend_get_static_capabilities (book->priv->backend);
- ret_val = CORBA_string_dup(temp);
- g_free(temp);
- return ret_val;
+ if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot remove book")));
+ } else {
+ dbus_g_method_return (context);
+ }
}
-
static void
-impl_GNOME_Evolution_Addressbook_Book_getRequiredFields (PortableServer_Servant servant,
- const CORBA_long opid,
- CORBA_Environment *ev)
-
+impl_AddressBook_Book_getContact (EDataBook *book, const char *IN_uid, DBusGMethodInvocation *context)
{
+ OperationData *op;
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
- e_book_backend_get_required_fields (e_data_book_get_backend (book), book, opid);
-
+ if (IN_uid == NULL) {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, _("Cannot get contact")));
+ return;
+ }
+
+ op = op_new (OP_GET_CONTACT, book, context);
+ op->uid = g_strdup (IN_uid);
+ g_thread_pool_push (op_pool, op, NULL);
}
-static void
-impl_GNOME_Evolution_Addressbook_Book_getSupportedFields (PortableServer_Servant servant,
- const CORBA_long opid,
- CORBA_Environment *ev)
+void
+e_data_book_respond_get_contact (EDataBook *book, guint32 opid, EDataBookStatus status, char *vcard)
{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
+ DBusGMethodInvocation *context = opid_fetch (opid);
- e_book_backend_get_supported_fields (e_data_book_get_backend (book), book, opid);
+ if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot get contact")));
+ } else {
+ dbus_g_method_return (context, vcard);
+ }
}
static void
-impl_GNOME_Evolution_Addressbook_Book_getSupportedAuthMethods (PortableServer_Servant servant,
- const CORBA_long opid,
- CORBA_Environment *ev)
+impl_AddressBook_Book_getContactList (EDataBook *book, const char *query, DBusGMethodInvocation *context)
{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
+ OperationData *op;
- e_book_backend_get_supported_auth_methods (e_data_book_get_backend (book), book, opid);
-}
-
-static GNOME_Evolution_Addressbook_CallStatus
-impl_GNOME_Evolution_Addressbook_Book_cancelOperation (PortableServer_Servant servant,
- CORBA_Environment *ev)
-{
- EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
+ if (query == NULL || query[0] == '\0') {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_INVALID_QUERY, _("Empty query")));
+ return;
+ }
- return e_book_backend_cancel_operation (e_data_book_get_backend (book), book);
+ op = op_new (OP_GET_CONTACTS, book, context);
+ op->query = g_strdup (query);
+ g_thread_pool_push (op_pool, op, NULL);
}
-
-/**
- * e_data_book_get_backend:
- * @book: an #EDataBook
- *
- * Gets the #EBookBackend being used to store data for @book.
- *
- * Return value: The #EBookBackend being used.
- **/
-EBookBackend *
-e_data_book_get_backend (EDataBook *book)
+void
+e_data_book_respond_get_contact_list (EDataBook *book, guint32 opid, EDataBookStatus status, GList *cards)
{
- g_return_val_if_fail (book && E_IS_DATA_BOOK (book), NULL);
-
- return book->priv->backend;
+ return_status_and_list (opid, status, cards, TRUE);
}
-/**
- * e_data_book_get_listener:
- * @book: an #EDataBook
- *
- * Gets the CORBA listener associated with @book.
- *
- * Return value: A #GNOME_Evolution_Addressbook_BookListener.
- **/
-GNOME_Evolution_Addressbook_BookListener
-e_data_book_get_listener (EDataBook *book)
+static void
+impl_AddressBook_Book_authenticateUser(EDataBook *book, const char *IN_user, const char *IN_passwd, const char *IN_auth_method, DBusGMethodInvocation *context)
{
- g_return_val_if_fail (book && E_IS_DATA_BOOK (book), CORBA_OBJECT_NIL);
+ OperationData *op;
- return book->priv->listener;
+ op = op_new (OP_AUTHENTICATE, book, context);
+ op->auth.username = g_strdup (IN_user);
+ op->auth.password = g_strdup (IN_passwd);
+ op->auth.method = g_strdup (IN_auth_method);
+ g_thread_pool_push (op_pool, op, NULL);
}
-/**
- * e_data_book_get_source:
- * @book: an #EDataBook
- *
- * Gets the #ESource associated with @book.
- *
- * Return value: An #ESource.
- **/
-ESource *
-e_data_book_get_source (EDataBook *book)
-{
- return book->priv->source;
-}
-
-/**
- * e_data_book_respond_open:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- *
- * Respond to an 'open' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
void
-e_data_book_respond_open (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status)
+e_data_book_respond_authenticate_user (EDataBook *book, guint32 opid, EDataBookStatus status)
{
- CORBA_Environment ev;
+ DBusGMethodInvocation *context = opid_fetch (opid);
- CORBA_exception_init (&ev);
- GNOME_Evolution_Addressbook_BookListener_notifyBookOpened (book->priv->listener, opid, status, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_data_book_respond_open: Exception "
- "responding to BookListener!\n");
- }
-
- CORBA_exception_free (&ev);
+ if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot authenticate user")));
+ } else {
+ dbus_g_method_return (context);
+ }
}
-/**
- * e_data_book_respond_remove:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- *
- * Respond to a 'remove' request to remove all of @book's data,
- * specified by @opid, indicating @status as the outcome.
- **/
-void
-e_data_book_respond_remove (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status)
+static void
+impl_AddressBook_Book_addContact (EDataBook *book, const char *IN_vcard, DBusGMethodInvocation *context)
{
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
- GNOME_Evolution_Addressbook_BookListener_notifyBookRemoved (book->priv->listener, opid, status, &ev);
+ OperationData *op;
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_data_book_respond_remove: Exception "
- "responding to BookListener!\n");
- }
+ if (IN_vcard == NULL || IN_vcard[0] == '\0') {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_INVALID_QUERY, _("Cannot add contact")));
+ return;
+ }
- CORBA_exception_free (&ev);
+ op = op_new (OP_ADD_CONTACT, book, context);
+ op->vcard = g_strdup (IN_vcard);
+ g_thread_pool_push (op_pool, op, NULL);
}
-/**
- * e_data_book_respond_create:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @contact: the contact created, or %NULL
- *
- * Respond to a 'create' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
void
-e_data_book_respond_create (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- EContact *contact)
+e_data_book_respond_create (EDataBook *book, guint32 opid, EDataBookStatus status, EContact *contact)
{
- CORBA_Environment ev;
-
- if (status == GNOME_Evolution_Addressbook_Success) {
- e_book_backend_notify_update (book->priv->backend, contact);
- e_book_backend_notify_complete (book->priv->backend);
- }
-
- CORBA_exception_init (&ev);
+ DBusGMethodInvocation *context = opid_fetch (opid);
- GNOME_Evolution_Addressbook_BookListener_notifyContactCreated (
- book->priv->listener, opid, status,
- status == GNOME_Evolution_Addressbook_Success ? e_contact_get_const (contact, E_CONTACT_UID) : "",
- &ev);
+ if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot add contact")));
+ } else {
+ e_book_backend_notify_update (e_data_book_get_backend (book), contact);
+ e_book_backend_notify_complete (e_data_book_get_backend (book));
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_data_book_respond_create: Exception "
- "responding to BookListener!\n");
- }
-
- CORBA_exception_free (&ev);
+ dbus_g_method_return (context, e_contact_get_const (contact, E_CONTACT_UID));
+ }
}
-/**
- * e_data_book_respond_remove_contacts:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @ids: a list of contact IDs removed
- *
- * Respond to a 'remove contacts' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
-void
-e_data_book_respond_remove_contacts (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- GList *ids)
+static void
+impl_AddressBook_Book_modifyContact (EDataBook *book, const char *IN_vcard, DBusGMethodInvocation *context)
{
- CORBA_Environment ev;
- GList *i;
-
- CORBA_exception_init (&ev);
-
- if (ids) {
- for (i = ids; i; i = i->next)
- e_book_backend_notify_remove (book->priv->backend, i->data);
- e_book_backend_notify_complete (book->priv->backend);
- }
+ OperationData *op;
- GNOME_Evolution_Addressbook_BookListener_notifyContactsRemoved (
- book->priv->listener, opid, status, &ev);
+ if (IN_vcard == NULL) {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_INVALID_QUERY, _("Cannot modify contact")));
+ return;
+ }
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_data_book_respond_remove: Exception "
- "responding to BookListener!\n");
- }
-
- CORBA_exception_free (&ev);
+ op = op_new (OP_MODIFY_CONTACT, book, context);
+ op->vcard = g_strdup (IN_vcard);
+ g_thread_pool_push (op_pool, op, NULL);
}
-/**
- * e_data_book_respond_modify:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @contact: the modified #EContact
- *
- * Respond to a 'modify' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
void
-e_data_book_respond_modify (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- EContact *contact)
+e_data_book_respond_modify (EDataBook *book, guint32 opid, EDataBookStatus status, EContact *contact)
{
- CORBA_Environment ev;
-
- if (status == GNOME_Evolution_Addressbook_Success) {
- e_book_backend_notify_update (book->priv->backend, contact);
- e_book_backend_notify_complete (book->priv->backend);
- }
+ DBusGMethodInvocation *context = opid_fetch (opid);
- CORBA_exception_init (&ev);
+ if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot modify contact")));
+ } else {
+ e_book_backend_notify_update (e_data_book_get_backend (book), contact);
+ e_book_backend_notify_complete (e_data_book_get_backend (book));
- GNOME_Evolution_Addressbook_BookListener_notifyContactModified (
- book->priv->listener, opid, status, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_data_book_respond_modify: Exception "
- "responding to BookListener!\n");
- }
-
- CORBA_exception_free (&ev);
+ dbus_g_method_return (context);
+ }
}
-/**
- * e_data_book_respond_authenticate_user:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- *
- * Respond to an 'authenticate' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
-void
-e_data_book_respond_authenticate_user (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status)
+static void
+impl_AddressBook_Book_removeContacts(EDataBook *book, const char **IN_uids, DBusGMethodInvocation *context)
{
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
+ OperationData *op;
- GNOME_Evolution_Addressbook_BookListener_notifyAuthenticationResult (
- book->priv->listener, opid, status, &ev);
+ /* Allow an empty array to be removed */
+ if (IN_uids == NULL) {
+ dbus_g_method_return (context);
+ return;
+ }
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_data_book_respond_authenticate_user: Exception "
- "responding to BookListener!\n");
- }
-
- CORBA_exception_free (&ev);
+ op = op_new (OP_REMOVE_CONTACTS, book, context);
+
+ for (; *IN_uids; IN_uids++) {
+ op->ids = g_list_prepend (op->ids, g_strdup (*IN_uids));
+ }
+
+ g_thread_pool_push (op_pool, op, NULL);
}
-/**
- * e_data_book_respond_get_required_fields:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @fields: a list of required field names
- *
- * Respond to a 'get required fields' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
void
-e_data_book_respond_get_required_fields (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- GList *fields)
+e_data_book_respond_remove_contacts (EDataBook *book, guint32 opid, EDataBookStatus status, GList *ids)
{
+ DBusGMethodInvocation *context = opid_fetch (opid);
- CORBA_Environment ev;
- GNOME_Evolution_Addressbook_stringlist stringlist;
- int num_fields;
- int i;
- GList *iter;
-
- CORBA_exception_init (&ev);
-
- num_fields = g_list_length (fields);
-
- stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_fields);
- stringlist._maximum = num_fields;
- stringlist._length = num_fields;
-
- for (i = 0, iter = fields; iter; iter = iter->next, i ++) {
- stringlist._buffer[i] = CORBA_string_dup ((char*)iter->data);
- }
+ if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot remove contacts")));
+ } else {
+ GList *i;
+
+ 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));
- printf ("calling GNOME_Evolution_Addressbook_BookListener_notifyRequiredFields\n");
-
- GNOME_Evolution_Addressbook_BookListener_notifyRequiredFields (
- book->priv->listener, opid, status,
- &stringlist,
- &ev);
-
- CORBA_exception_free (&ev);
-
- CORBA_free(stringlist._buffer);
+ dbus_g_method_return (context);
+ }
}
-/**
- * e_data_book_respond_get_supported_fields:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @fields: a list of supported field names
- *
- * Respond to a 'get supported fields' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
-void
-e_data_book_respond_get_supported_fields (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- GList *fields)
+static gboolean
+impl_AddressBook_Book_getStaticCapabilities(EDataBook *book, char **OUT_capabilities, GError **error)
{
- CORBA_Environment ev;
- GNOME_Evolution_Addressbook_stringlist stringlist;
- int num_fields;
- int i;
- GList *iter;
-
- CORBA_exception_init (&ev);
-
- num_fields = g_list_length (fields);
-
- stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_fields);
- stringlist._maximum = num_fields;
- stringlist._length = num_fields;
-
- for (i = 0, iter = fields; iter; iter = iter->next, i ++) {
- stringlist._buffer[i] = CORBA_string_dup ((char*)iter->data);
- }
-
- printf ("calling GNOME_Evolution_Addressbook_BookListener_notifySupportedFields\n");
-
- GNOME_Evolution_Addressbook_BookListener_notifySupportedFields (
- book->priv->listener, opid, status,
- &stringlist,
- &ev);
-
- CORBA_exception_free (&ev);
+ *OUT_capabilities = e_book_backend_get_static_capabilities (e_data_book_get_backend (book));
+ return TRUE;
+}
- CORBA_free(stringlist._buffer);
+static void
+impl_AddressBook_Book_getSupportedFields(EDataBook *book, DBusGMethodInvocation *context)
+{
+ e_book_backend_get_supported_fields (e_data_book_get_backend (book), book, opid_store (context));
}
-/**
- * e_data_book_respond_get_supported_auth_methods:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @auth_methods: a list of names for supported auth methods
- *
- * Respond to a 'get supported auth methods' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
void
-e_data_book_respond_get_supported_auth_methods (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- GList *auth_methods)
+e_data_book_respond_get_supported_fields (EDataBook *book, guint32 opid, EDataBookStatus status, GList *fields)
{
- CORBA_Environment ev;
- GNOME_Evolution_Addressbook_stringlist stringlist;
- int num_auth_methods;
- GList *iter;
- int i;
-
- CORBA_exception_init (&ev);
-
- num_auth_methods = g_list_length (auth_methods);
-
- stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_auth_methods);
- stringlist._maximum = num_auth_methods;
- stringlist._length = num_auth_methods;
-
- for (i = 0, iter = auth_methods; iter; iter = iter->next, i ++) {
- stringlist._buffer[i] = CORBA_string_dup ((char*)iter->data);
- }
-
- GNOME_Evolution_Addressbook_BookListener_notifySupportedAuthMethods (
- book->priv->listener, opid, status,
- &stringlist,
- &ev);
-
- CORBA_exception_free (&ev);
-
- CORBA_free(stringlist._buffer);
+ return_status_and_list (opid, status, fields, FALSE);
}
static void
-view_destroy(gpointer data, GObject *where_object_was)
+impl_AddressBook_Book_getRequiredFields(EDataBook *book, DBusGMethodInvocation *context)
{
- EDataBook *book = (EDataBook *)data;
- e_book_backend_remove_book_view (book->priv->backend, (EDataBookView*)where_object_was);
+ e_book_backend_get_required_fields (e_data_book_get_backend (book), book, opid_store (context));
}
-/**
- * e_data_book_respond_get_book_view:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @book_view: the #EDataBookView created
- *
- * Respond to a 'get book view' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
void
-e_data_book_respond_get_book_view (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- EDataBookView *book_view)
+e_data_book_respond_get_required_fields (EDataBook *book, guint32 opid, EDataBookStatus status, GList *fields)
{
- CORBA_Environment ev;
- CORBA_Object object = CORBA_OBJECT_NIL;
-
- printf ("e_data_book_respond_get_book_view\n");
-
- CORBA_exception_init (&ev);
-
- if (book_view) {
- object = bonobo_object_corba_objref(BONOBO_OBJECT(book_view));
-
- g_object_weak_ref (G_OBJECT (book_view), view_destroy, book);
- }
-
- GNOME_Evolution_Addressbook_BookListener_notifyViewRequested (
- book->priv->listener, opid, status, object, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_data_book_respond_get_book_view: Exception "
- "responding to BookListener!\n");
- }
-
- CORBA_exception_free (&ev);
+ return_status_and_list (opid, status, fields, FALSE);
}
-/**
- * e_data_book_respond_get_contact:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @vcard: the found VCard, or %NULL
- *
- * Respond to a 'get contact' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
-void
-e_data_book_respond_get_contact (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- char *vcard)
+static void
+impl_AddressBook_Book_getSupportedAuthMethods(EDataBook *book, DBusGMethodInvocation *context)
{
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
-
- GNOME_Evolution_Addressbook_BookListener_notifyContactRequested (book->priv->listener,
- opid,
- status,
- vcard,
- &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION)
- g_message ("could not notify listener of get-contact response");
-
- CORBA_exception_free (&ev);
+ e_book_backend_get_supported_auth_methods (e_data_book_get_backend (book), book, opid_store (context));
}
-/**
- * e_data_book_respond_get_contact_list:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @card_list: a list of VCard strings
- *
- * Respond to a 'get contact list' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
void
-e_data_book_respond_get_contact_list (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- GList *card_list)
+e_data_book_respond_get_supported_auth_methods (EDataBook *book, guint32 opid, EDataBookStatus status, GList *auth_methods)
{
- CORBA_Environment ev;
- GNOME_Evolution_Addressbook_stringlist stringlist;
- int num_cards;
- int i;
- GList *l;
-
- CORBA_exception_init (&ev);
-
- num_cards = g_list_length (card_list);
-
- stringlist._buffer = CORBA_sequence_CORBA_string_allocbuf (num_cards);
- stringlist._maximum = num_cards;
- stringlist._length = num_cards;
-
- for (i = 0, l = card_list; l; l = l->next, i ++)
- stringlist._buffer[i] = CORBA_string_dup (l->data);
-
- g_list_foreach (card_list, (GFunc)g_free, NULL);
- g_list_free (card_list);
-
-
- GNOME_Evolution_Addressbook_BookListener_notifyContactListRequested (book->priv->listener,
- opid,
- status,
- &stringlist,
- &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION)
- g_message ("could not notify listener of get-contact-list response");
-
- CORBA_exception_free (&ev);
-
- CORBA_free(stringlist._buffer);
+ return_status_and_list (opid, status, auth_methods, FALSE);
}
-/**
- * e_data_book_respond_get_changes:
- * @book: an #EDataBook
- * @opid: the operation ID that generated the response
- * @status: the outcome of the operation
- * @changes: a list of GNOME_Evolution_Addressbook_BookChangeItem items
- *
- * Respond to a 'get changes' request specified by @opid on @book,
- * indicating @status as the outcome.
- **/
-void
-e_data_book_respond_get_changes (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- GList *changes)
+static char*
+construct_bookview_path (void)
{
- CORBA_Environment ev;
- GNOME_Evolution_Addressbook_BookChangeList changelist;
- int num_changes;
- int i;
- GList *l;
-
- CORBA_exception_init (&ev);
-
- num_changes = g_list_length (changes);
-
- changelist._buffer = CORBA_sequence_GNOME_Evolution_Addressbook_BookChangeItem_allocbuf (num_changes);
- changelist._maximum = num_changes;
- changelist._length = num_changes;
+ static volatile guint counter = 1;
- for (i = 0, l = changes; l; l = l->next, i ++) {
- GNOME_Evolution_Addressbook_BookChangeItem *change = (GNOME_Evolution_Addressbook_BookChangeItem*)l->data;
- changelist._buffer[i] = *change;
- changelist._buffer[i].vcard = CORBA_string_dup (change->vcard);
- }
+ return g_strdup_printf ("/org/gnome/evolution/dataserver/addressbook/BookView/%d/%d",
+ getpid (),
+ g_atomic_int_exchange_and_add ((int*)&counter, 1));
+}
- g_list_foreach (changes, (GFunc)CORBA_free, NULL);
- g_list_free (changes);
+static void
+impl_AddressBook_Book_getBookView (EDataBook *book, const char *search, const guint max_results, DBusGMethodInvocation *context)
+{
+ EBookBackend *backend = e_data_book_get_backend (book);
+ EBookBackendSExp *card_sexp;
+ EDataBookView *book_view;
+ char *path;
- GNOME_Evolution_Addressbook_BookListener_notifyChangesRequested (book->priv->listener,
- opid,
- status,
- &changelist,
- &ev);
+ card_sexp = e_book_backend_sexp_new (search);
+ if (!card_sexp) {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_INVALID_QUERY, _("Invalid query")));
+ return;
+ }
- if (ev._major != CORBA_NO_EXCEPTION)
- g_message ("could not notify listener of get-changes response");
+ path = construct_bookview_path ();
+ book_view = e_data_book_view_new (book, path, search, card_sexp, max_results);
- CORBA_exception_free (&ev);
+ e_book_backend_add_book_view (backend, book_view);
- CORBA_free(changelist._buffer);
+ dbus_g_method_return (context, path);
+ g_free (path);
}
-/**
- * e_data_book_report_writable:
- * @book: an #EDataBook
- * @writable: %TRUE if @book is writeable, %FALSE otherwise
- *
- * Notify listeners that @book's writeable status has changed
- * to @writable.
- **/
-void
-e_data_book_report_writable (EDataBook *book,
- gboolean writable)
+static void
+impl_AddressBook_Book_getChanges(EDataBook *book, const char *IN_change_id, DBusGMethodInvocation *context)
{
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
-
- GNOME_Evolution_Addressbook_BookListener_notifyWritable (
- book->priv->listener, (CORBA_boolean) writable, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_data_book_report_writable: Exception "
- "responding to BookListener!\n");
- }
-
- CORBA_exception_free (&ev);
+ OperationData *op;
+
+ op = op_new (OP_GET_CHANGES, book, context);
+ op->change_id = g_strdup (IN_change_id);
+ g_thread_pool_push (op_pool, op, NULL);
}
-/**
- * e_data_book_report_connection_status:
- * @book: an #EDataBook
- * @is_online: %TRUE if the book is connected, %FALSE otherwise
- *
- * Notify listeners that @book's online status has changed
- * to @is_online.
- **/
void
-e_data_book_report_connection_status (EDataBook *book,
- gboolean is_online)
+e_data_book_respond_get_changes (EDataBook *book, guint32 opid, EDataBookStatus status, GList *changes)
{
- CORBA_Environment ev;
+ DBusGMethodInvocation *context = opid_fetch (opid);
+
+ if (status != E_DATA_BOOK_STATUS_SUCCESS) {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot get changes")));
+ } else {
+ /* The DBus interface to this is a(us), an array of structs of unsigned ints
+ and strings. In dbus-glib this is a GPtrArray of GValueArray of unsigned
+ int and strings. */
+ GPtrArray *array;
- CORBA_exception_init (&ev);
+ array = g_ptr_array_new ();
- GNOME_Evolution_Addressbook_BookListener_notifyConnectionStatus (
- book->priv->listener, (CORBA_boolean) is_online, &ev);
+ while (changes != NULL) {
+ EDataBookChange *change = (EDataBookChange *) changes->data;
+ GValueArray *vals;
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_data_book_report_connection_status: Exception "
- "responding to BookListener!\n");
- }
+ vals = g_value_array_new (2);
+
+ g_value_array_append (vals, NULL);
+ g_value_init (g_value_array_get_nth (vals, 0), G_TYPE_UINT);
+ g_value_set_uint (g_value_array_get_nth (vals, 0), change->change_type);
- CORBA_exception_free (&ev);
+ g_value_array_append (vals, NULL);
+ g_value_init (g_value_array_get_nth (vals, 1), G_TYPE_STRING);
+ g_value_take_string (g_value_array_get_nth (vals, 1), change->vcard);
+ /* Now change->vcard is owned by the GValue */
+ g_free (change);
+ changes = g_list_remove (changes, change);
+ }
+
+ dbus_g_method_return (context, array);
+ g_ptr_array_foreach (array, (GFunc)g_value_array_free, NULL);
+ g_ptr_array_free (array, TRUE);
+ }
}
-/**
- * e_data_book_report_connection_status:
- * @book: an #EDataBook
- *
- * Notify listeners that @book requires authentication.
- **/
-void
-e_data_book_report_auth_required (EDataBook *book)
+static gboolean
+impl_AddressBook_Book_cancelOperation(EDataBook *book, GError **error)
{
+ if (!e_book_backend_cancel_operation (e_data_book_get_backend (book), book)) {
+ g_set_error (error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_COULD_NOT_CANCEL, "Failed to cancel operation");
+ return FALSE;
+ }
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
-
- GNOME_Evolution_Addressbook_BookListener_notifyAuthRequired (
- book->priv->listener, &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_warning ("e_data_book_report_auth_required: Exception "
- "responding to BookListener!\n");
- }
-
- CORBA_exception_free (&ev);
-
+ return TRUE;
}
static void
-e_data_book_construct (EDataBook *book,
- EBookBackend *backend,
- ESource *source,
- GNOME_Evolution_Addressbook_BookListener listener)
+impl_AddressBook_Book_close(EDataBook *book, DBusGMethodInvocation *context)
{
- EDataBookPrivate *priv;
- CORBA_Environment ev;
-
- g_return_if_fail (book != NULL);
- g_return_if_fail (source != NULL);
-
- priv = book->priv;
+ char *sender;
- CORBA_exception_init (&ev);
- book->priv->listener = CORBA_Object_duplicate (listener, &ev);
+ sender = dbus_g_method_get_sender (context);
- if (ev._major != CORBA_NO_EXCEPTION) {
- g_message ("e_data_book_construct(): could not duplicate the listener");
- CORBA_exception_free (&ev);
- return;
- }
+ book->closed_cb (book, sender);
- CORBA_exception_free (&ev);
+ g_free (sender);
- g_object_ref (source);
+ g_object_unref (book);
- priv->backend = g_object_ref(backend);
- priv->source = source;
+ dbus_g_method_return (context);
}
-/**
- * e_data_book_new:
- * @backend: an #EBookBackend
- * @source: an #ESource
- * @listener: a #GNOME_Evolution_Addressbook_BookListener CORBA object
- *
- * Create a new #EDataBook using @backend for storage, @source as the
- * storage location and @listener for reporting status.
- *
- * Return value: A new #EDataBook.
- **/
-EDataBook *
-e_data_book_new (EBookBackend *backend,
- ESource *source,
- GNOME_Evolution_Addressbook_BookListener listener)
+void
+e_data_book_report_writable (EDataBook *book, gboolean writable)
{
- static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
- static PortableServer_POA poa = NULL;
- EDataBook *book;
-
- g_static_mutex_lock (&mutex);
- if (poa == NULL)
- poa = bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL);
- g_static_mutex_unlock (&mutex);
-
- book = g_object_new (E_TYPE_DATA_BOOK, "poa", poa, NULL);
+ g_return_if_fail (book != NULL);
- e_data_book_construct (book, backend, source, listener);
-
- return book;
+ g_signal_emit (book, signals[WRITABLE], 0, writable);
}
-static void
-e_data_book_dispose (GObject *object)
+void
+e_data_book_report_connection_status (EDataBook *book, gboolean connected)
{
- EDataBook *book = E_DATA_BOOK (object);
-
- if (book->priv) {
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
- CORBA_Object_release (book->priv->listener, &ev);
+ g_return_if_fail (book != NULL);
- if (ev._major != CORBA_NO_EXCEPTION)
- g_message ("e_data_book_construct(): could not release the listener");
-
- CORBA_exception_free (&ev);
-
- g_object_unref (book->priv->source);
- g_object_unref (book->priv->backend);
- g_free (book->priv);
- book->priv = NULL;
- }
-
- if (G_OBJECT_CLASS (e_data_book_parent_class)->dispose)
- G_OBJECT_CLASS (e_data_book_parent_class)->dispose (object);
+ g_signal_emit (book, signals[CONNECTION], 0, connected);
}
-static void
-e_data_book_class_init (EDataBookClass *klass)
+void
+e_data_book_report_auth_required (EDataBook *book)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- POA_GNOME_Evolution_Addressbook_Book__epv *epv;
-
- e_data_book_parent_class = g_type_class_peek_parent (klass);
-
- object_class->dispose = e_data_book_dispose;
-
- epv = &klass->epv;
-
- epv->open = impl_GNOME_Evolution_Addressbook_Book_open;
- epv->remove = impl_GNOME_Evolution_Addressbook_Book_remove;
- epv->getContact = impl_GNOME_Evolution_Addressbook_Book_getContact;
- epv->getContactList = impl_GNOME_Evolution_Addressbook_Book_getContactList;
- epv->authenticateUser = impl_GNOME_Evolution_Addressbook_Book_authenticateUser;
- epv->addContact = impl_GNOME_Evolution_Addressbook_Book_addContact;
- epv->removeContacts = impl_GNOME_Evolution_Addressbook_Book_removeContacts;
- epv->modifyContact = impl_GNOME_Evolution_Addressbook_Book_modifyContact;
- epv->getStaticCapabilities = impl_GNOME_Evolution_Addressbook_Book_getStaticCapabilities;
- epv->getSupportedFields = impl_GNOME_Evolution_Addressbook_Book_getSupportedFields;
- epv->getRequiredFields = impl_GNOME_Evolution_Addressbook_Book_getRequiredFields;
- epv->getSupportedAuthMethods = impl_GNOME_Evolution_Addressbook_Book_getSupportedAuthMethods;
- epv->getBookView = impl_GNOME_Evolution_Addressbook_Book_getBookView;
- epv->getChanges = impl_GNOME_Evolution_Addressbook_Book_getChanges;
- epv->cancelOperation = impl_GNOME_Evolution_Addressbook_Book_cancelOperation;
+ g_return_if_fail (book != NULL);
+ g_signal_emit (book, signals[AUTH_REQUIRED], 0);
}
static void
-e_data_book_init (EDataBook *book)
-{
- book->priv = g_new0 (EDataBookPrivate, 1);
+return_status_and_list (guint32 opid, EDataBookStatus status, GList *list, gboolean free_data)
+{
+ DBusGMethodInvocation *context = opid_fetch (opid);
+
+ if (status == E_DATA_BOOK_STATUS_SUCCESS) {
+ char **array;
+ GList *l;
+ int i = 0;
+
+ array = g_new0 (char*, g_list_length (list) + 1);
+ for (l = list; l != NULL; l = l->next) {
+ array[i++] = l->data;
+ }
+
+ dbus_g_method_return (context, array);
+
+ if (free_data) {
+ g_strfreev (array);
+ } else {
+ g_free (array);
+ }
+ } else {
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, status, _("Cannot complete operation")));
+ }
}
-
-BONOBO_TYPE_FUNC_FULL (
- EDataBook,
- GNOME_Evolution_Addressbook_Book,
- BONOBO_TYPE_OBJECT,
- e_data_book);
diff --git a/addressbook/libedata-book/e-data-book.h b/addressbook/libedata-book/e-data-book.h
index 3c86994..ee4d40e 100644
--- a/addressbook/libedata-book/e-data-book.h
+++ b/addressbook/libedata-book/e-data-book.h
@@ -1,120 +1,84 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * A wrapper object which exports the GNOME_Evolution_Addressbook_Book CORBA interface
- * and which maintains a request queue.
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2006 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
*
- * Author:
- * Nat Friedman (nat 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.
*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Ross Burton <ross linux intel com>
*/
#ifndef __E_DATA_BOOK_H__
#define __E_DATA_BOOK_H__
-#include <bonobo/bonobo-object.h>
-#include "libedataserver/e-list.h"
-#include "libedataserver/e-source.h"
-#include <libedata-book/Evolution-DataServer-Addressbook.h>
-#include <libedata-book/e-data-book-types.h>
-
-G_BEGIN_DECLS
-
-#define E_TYPE_DATA_BOOK (e_data_book_get_type ())
-#define E_DATA_BOOK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_DATA_BOOK, EDataBook))
-#define E_DATA_BOOK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), E_DATA_BOOK_FACTORY_TYPE, EDataBookClass))
-#define E_IS_DATA_BOOK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_DATA_BOOK))
-#define E_IS_DATA_BOOK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_DATA_BOOK))
-#define E_DATA_BOOK_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_DATA_BOOK, EDataBookClass))
-
-typedef struct _EDataBookPrivate EDataBookPrivate;
-
-struct _EDataBook {
- BonoboObject parent_object;
- EDataBookPrivate *priv;
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include <libedataserver/e-source.h>
+#include "e-book-backend.h"
+#include "e-data-book-types.h"
+
+typedef void (* EDataBookClosedCallback) (EDataBook *book, const char *client);
+
+struct _EDataBook
+{
+ GObject parent;
+ EBookBackend *backend;
+ ESource *source;
+ /* TODO: move to private data */
+ EDataBookClosedCallback closed_cb;
};
-struct _EDataBookClass {
- BonoboObjectClass parent_class;
-
- POA_GNOME_Evolution_Addressbook_Book__epv epv;
-
- /* Padding for future expansion */
- void (*_pas_reserved0) (void);
- void (*_pas_reserved1) (void);
- void (*_pas_reserved2) (void);
- void (*_pas_reserved3) (void);
- void (*_pas_reserved4) (void);
+struct _EDataBookClass
+{
+ GObjectClass parent;
};
-
-EDataBook *e_data_book_new (EBookBackend *backend,
- ESource *source,
- GNOME_Evolution_Addressbook_BookListener listener);
-GNOME_Evolution_Addressbook_BookListener e_data_book_get_listener (EDataBook *book);
-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,
- GNOME_Evolution_Addressbook_CallStatus status);
-void e_data_book_respond_remove (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status);
-void e_data_book_respond_create (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- EContact *contact);
-void e_data_book_respond_remove_contacts (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- GList *ids);
-void e_data_book_respond_modify (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- EContact *contact);
-void e_data_book_respond_authenticate_user (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status);
-void e_data_book_respond_get_supported_fields (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- GList *fields);
-void e_data_book_respond_get_required_fields (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- GList *fields);
-void e_data_book_respond_get_supported_auth_methods (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- GList *fields);
-
-void e_data_book_respond_get_book_view (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- EDataBookView *book_view);
-void e_data_book_respond_get_contact (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- char *vcard);
-void e_data_book_respond_get_contact_list (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- GList *cards);
-void e_data_book_respond_get_changes (EDataBook *book,
- guint32 opid,
- GNOME_Evolution_Addressbook_CallStatus status,
- 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);
-
-G_END_DECLS
-
-#endif /* ! __E_DATA_BOOK_H__ */
+#define E_TYPE_DATA_BOOK (e_data_book_get_type ())
+#define E_DATA_BOOK(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), E_TYPE_DATA_BOOK, EDataBook))
+#define E_DATA_BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_DATA_BOOK, EDataBookClass))
+#define E_IS_DATA_BOOK(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), E_TYPE_DATA_BOOK))
+#define E_IS_DATA_BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_DATA_BOOK))
+#define E_DATA_BOOK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_DATA_BOOK, EDataBookClass))
+
+GQuark e_data_book_error_quark (void);
+#define E_DATA_BOOK_ERROR e_data_book_error_quark ()
+
+GType e_data_book_get_type(void);
+
+EDataBook * e_data_book_new (EBookBackend *backend, ESource *source, EDataBookClosedCallback closed_cb);
+
+ESource* e_data_book_get_source (EDataBook *book);
+EBookBackend* e_data_book_get_backend (EDataBook *book);
+
+/* Callbacks from the backends */
+void e_data_book_respond_open (EDataBook *book, guint opid, EDataBookStatus status);
+void e_data_book_respond_get_contact (EDataBook *book, guint32 opid, EDataBookStatus status, char *vcard);
+void e_data_book_respond_get_contact_list (EDataBook *book, guint32 opid, EDataBookStatus status, GList *cards);
+void e_data_book_respond_remove_contacts (EDataBook *book, guint32 opid, EDataBookStatus status, GList *ids);
+void e_data_book_respond_remove (EDataBook *book, guint32 opid, EDataBookStatus status);
+void e_data_book_respond_modify (EDataBook *book, guint32 opid, EDataBookStatus status, EContact *contact);
+void e_data_book_respond_modify_contacts (EDataBook *book, guint32 opid, EDataBookStatus status, GList *contacts);
+void e_data_book_respond_create (EDataBook *book, guint32 opid, EDataBookStatus status, EContact *contact);
+void e_data_book_respond_get_changes (EDataBook *book, guint32 opid, EDataBookStatus status, GList *changes);
+void e_data_book_respond_authenticate_user (EDataBook *book, guint32 opid, EDataBookStatus status);
+void e_data_book_respond_get_supported_fields (EDataBook *book, guint32 opid, EDataBookStatus status, GList *fields);
+void e_data_book_respond_get_required_fields (EDataBook *book, guint32 opid, EDataBookStatus status, GList *fields);
+void e_data_book_respond_get_supported_auth_methods (EDataBook *book, guint32 opid, EDataBookStatus status, GList *fields);
+
+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);
+
+#endif /* __E_DATA_BOOK_H__ */
diff --git a/addressbook/libedata-book/glib-gen.mak b/addressbook/libedata-book/glib-gen.mak
new file mode 100644
index 0000000..f510d80
--- /dev/null
+++ b/addressbook/libedata-book/glib-gen.mak
@@ -0,0 +1,42 @@
+# these are the variables your Makefile.am should set
+# the example is based on the colorbalance interface
+
+#glib_enum_headers=$(colorbalance_headers)
+#glib_enum_define=GST_COLOR_BALANCE
+#glib_enum_prefix=gst_color_balance
+
+# these are all the rules generating the relevant files
+%-marshal.h: %-marshal.list
+ glib-genmarshal --header --prefix=$(glib_enum_prefix)_marshal $^ > $*-marshal.h.tmp
+ mv $*-marshal.h.tmp $*-marshal.h
+
+%-marshal.c: %-marshal.list
+ echo "#include \"$*-marshal.h\"" >> $*-marshal.c.tmp
+ glib-genmarshal --body --prefix=$(glib_enum_prefix)_marshal $^ >> $*-marshal.c.tmp
+ mv $*-marshal.c.tmp $*-marshal.c
+
+%-enumtypes.h: $(glib_enum_headers)
+ glib-mkenums \
+ --fhead "#ifndef __$(glib_enum_define)_ENUM_TYPES_H__\n#define __$(glib_enum_define)_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
+ --fprod "/* enumerations from \"@filename \" */\n" \
+ --vhead "GType @enum_name _get_type (void);\n#define E_TYPE_ ENUMSHORT@ (@enum_name _get_type())\n" \
+ --ftail "G_END_DECLS\n\n#endif /* __$(glib_enum_define)_ENUM_TYPES_H__ */" \
+ $^ > $@
+
+%-enumtypes.c: $(glib_enum_headers)
+ @if test "x$(glib_enum_headers)" == "x"; then echo "ERROR: glib_enum_headers is empty, please fix Makefile"; exit 1; fi
+ glib-mkenums \
+ --fhead "#include <$*.h>\n#include \"$*-enumtypes.h\"" \
+ --fprod "\n/* enumerations from \"@filename \" */" \
+ --vhead "GType\n enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G Type@Value values[] = {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME \", \"@valuenick \" }," \
+ --vtail " { 0, NULL, NULL }\n };\n etype = g_ type@_register_static (\"@EnumName \", values);\n }\n return etype;\n}\n" \
+ $^ > $@
+
+# a hack rule to make sure .Plo files exist because they get include'd
+# from Makefile's
+.deps/%-marshal.Plo:
+ touch $@
+
+.deps/%-enumtypes.Plo:
+ touch $@
diff --git a/addressbook/libedata-book/libedata-book.pc.in b/addressbook/libedata-book/libedata-book.pc.in
index 8ab451e..fb06ab1 100644
--- a/addressbook/libedata-book/libedata-book.pc.in
+++ b/addressbook/libedata-book/libedata-book.pc.in
@@ -6,13 +6,11 @@ datarootdir= datarootdir@
datadir= datadir@
idldir= idldir@
-IDL_INCLUDES=-I${idldir} @IDL_INCLUDES@
-
privincludedir= privincludedir@
Name: libedatabook
Description: Backend library for evolution address books
Version: @VERSION@
-Requires: libbonobo-2.0 >= @LIBBONOBO_REQUIRED@ libedataserver-1.2 libebackend-1.2 libebook-1.2
+Requires: libedataserver-1.2 libebook-1.2 dbus-glib-1
Libs: -L${libdir} -ledata-book-1.2
Cflags: -I${privincludedir}
diff --git a/addressbook/libedata-book/opid.c b/addressbook/libedata-book/opid.c
new file mode 100644
index 0000000..ca33a61
--- /dev/null
+++ b/addressbook/libedata-book/opid.c
@@ -0,0 +1,75 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * 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 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.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Ross Burton <ross linux intel com>
+ */
+
+#include "opid.h"
+
+G_LOCK_DEFINE_STATIC (lock);
+static int counter = 0;
+static GHashTable *hash = NULL;
+
+static void
+opid_init (void)
+{
+ counter = 1;
+ hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+}
+
+guint32
+opid_store (gpointer p)
+{
+ int id;
+
+ g_return_val_if_fail (p, 0);
+
+ G_LOCK (lock);
+
+ if (G_UNLIKELY (hash == NULL))
+ opid_init ();
+
+ do {
+ id = counter++;
+ } while (g_hash_table_lookup (hash, GINT_TO_POINTER (id)) != NULL);
+
+ g_hash_table_insert (hash, GINT_TO_POINTER (id), p);
+
+ G_UNLOCK (lock);
+
+ return id;
+}
+
+gpointer
+opid_fetch (guint32 id)
+{
+ gpointer p;
+
+ G_LOCK (lock);
+
+ if (G_UNLIKELY (hash == NULL))
+ opid_init ();
+
+ p = g_hash_table_lookup (hash, GINT_TO_POINTER (id));
+
+ g_hash_table_remove (hash, GINT_TO_POINTER (id));
+
+ G_UNLOCK (lock);
+
+ return p;
+}
diff --git a/addressbook/libedata-book/opid.h b/addressbook/libedata-book/opid.h
new file mode 100644
index 0000000..12ceb0a
--- /dev/null
+++ b/addressbook/libedata-book/opid.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corporation
+ *
+ * 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 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.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Ross Burton <ross linux intel com>
+ */
+
+#include <glib.h>
+
+/* Stupid EDS internal API */
+
+guint32 opid_store (gpointer p);
+
+gpointer opid_fetch (guint32 id);
diff --git a/addressbook/libedata-book/org.gnome.evolution.dataserver.AddressBook.service.in b/addressbook/libedata-book/org.gnome.evolution.dataserver.AddressBook.service.in
new file mode 100644
index 0000000..0928311
--- /dev/null
+++ b/addressbook/libedata-book/org.gnome.evolution.dataserver.AddressBook.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gnome.evolution.dataserver.AddressBook
+Exec= LIBEXECDIR@/e-addressbook-factory
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]