1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
4 * Copyright (C) 2006 OpenedHand Ltd
5 * Copyright (C) 2009 Intel Corporation
7 * This library is free software; you can redistribute it and/or modify it under
8 * the terms of version 2.1 of the GNU Lesser General Public License as
9 * published by the Free Software Foundation.
11 * This library is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this library; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Author: Ross Burton <ross@linux.intel.com>
27 #include <glib/gi18n-lib.h>
29 #include "e-book-client.h"
30 #include "e-book-client-view.h"
31 #include "e-book-client-view-private.h"
32 #include "e-book-marshal.h"
33 #include "libedata-book/e-data-book-types.h"
34 #include "libedataserver/e-data-server-util.h"
35 #include "e-gdbus-book-view.h"
37 #define E_BOOK_CLIENT_VIEW_GET_PRIVATE(obj) \
38 (G_TYPE_INSTANCE_GET_PRIVATE \
39 ((obj), E_TYPE_BOOK_CLIENT_VIEW, EBookClientViewPrivate))
41 G_DEFINE_TYPE (EBookClientView, e_book_client_view, G_TYPE_OBJECT);
43 struct _EBookClientViewPrivate {
44 GDBusProxy *gdbus_bookview;
58 static guint signals[LAST_SIGNAL];
61 objects_added_cb (EGdbusBookView *object,
62 const gchar * const *vcards,
63 EBookClientView *view)
65 const gchar * const *p;
66 GSList *contacts = NULL;
68 if (!view->priv->running)
71 /* array contains both UID and vcard */
72 for (p = vcards; *p; p += 2) {
73 contacts = g_slist_prepend (contacts, e_contact_new_from_vcard_with_uid (p[0], p[1]));
76 contacts = g_slist_reverse (contacts);
78 g_signal_emit (view, signals[OBJECTS_ADDED], 0, contacts);
80 e_util_free_object_slist (contacts);
84 objects_modified_cb (EGdbusBookView *object,
85 const gchar * const *vcards,
86 EBookClientView *view)
88 const gchar * const *p;
89 GSList *contacts = NULL;
91 if (!view->priv->running)
94 /* array contains both UID and vcard */
95 for (p = vcards; *p; p += 2) {
96 contacts = g_slist_prepend (contacts, e_contact_new_from_vcard_with_uid (p[0], p[1]));
98 contacts = g_slist_reverse (contacts);
100 g_signal_emit (view, signals[OBJECTS_MODIFIED], 0, contacts);
102 e_util_free_object_slist (contacts);
106 objects_removed_cb (EGdbusBookView *object,
107 const gchar * const *ids,
108 EBookClientView *view)
110 const gchar * const *p;
113 if (!view->priv->running)
116 for (p = ids; *p; p++) {
117 list = g_slist_prepend (list, (gchar *) *p);
119 list = g_slist_reverse (list);
121 g_signal_emit (view, signals[OBJECTS_REMOVED], 0, list);
123 /* No need to free the values, our caller will */
128 progress_cb (EGdbusBookView *object,
130 const gchar *message,
131 EBookClientView *view)
133 if (!view->priv->running)
136 g_signal_emit (view, signals[PROGRESS], 0, percent, message);
140 complete_cb (EGdbusBookView *object,
141 const gchar * const *in_error_strv,
142 EBookClientView *view)
144 GError *error = NULL;
146 if (!view->priv->running)
149 g_return_if_fail (e_gdbus_templates_decode_error (in_error_strv, &error));
151 g_signal_emit (view, signals[COMPLETE], 0, error);
154 g_error_free (error);
158 * _e_book_client_view_new:
159 * @book_client: an #EBookClient
160 * @gdbus_bookview: The #EGdbusBookView to get signals from
162 * Creates a new #EBookClientView based on #EBookClient and listening to @gdbus_bookview.
163 * This is a private function, applications should call e_book_client_get_view() or
164 * e_book_client_get_view_sync().
166 * Returns: A new #EBookClientView.
169 _e_book_client_view_new (EBookClient *book_client,
170 EGdbusBookView *gdbus_bookview)
172 EBookClientView *view;
173 EBookClientViewPrivate *priv;
175 view = g_object_new (E_TYPE_BOOK_CLIENT_VIEW, NULL);
178 priv->client = g_object_ref (book_client);
180 /* Take ownership of the gdbus_bookview object */
181 priv->gdbus_bookview = g_object_ref (G_DBUS_PROXY (gdbus_bookview));
183 g_object_add_weak_pointer (G_OBJECT (gdbus_bookview), (gpointer) &priv->gdbus_bookview);
184 g_signal_connect (priv->gdbus_bookview, "objects-added", G_CALLBACK (objects_added_cb), view);
185 g_signal_connect (priv->gdbus_bookview, "objects-modified", G_CALLBACK (objects_modified_cb), view);
186 g_signal_connect (priv->gdbus_bookview, "objects-removed", G_CALLBACK (objects_removed_cb), view);
187 g_signal_connect (priv->gdbus_bookview, "progress", G_CALLBACK (progress_cb), view);
188 g_signal_connect (priv->gdbus_bookview, "complete", G_CALLBACK (complete_cb), view);
194 * e_book_client_view_get_client:
195 * @view: an #EBookClientView
197 * Returns the #EBookClient that this book view is monitoring.
199 * Returns: (transfer none): an #EBookClient.
202 e_book_client_view_get_client (EBookClientView *view)
204 g_return_val_if_fail (E_IS_BOOK_CLIENT_VIEW (view), NULL);
206 return view->priv->client;
210 * e_book_client_view_start:
212 * @view: an #EBookClientView
214 * Tells @view to start processing events.
217 e_book_client_view_start (EBookClientView *view,
220 EBookClientViewPrivate *priv;
222 g_return_if_fail (E_IS_BOOK_CLIENT_VIEW (view));
226 if (priv->gdbus_bookview) {
227 GError *local_error = NULL;
229 priv->running = TRUE;
230 if (!e_gdbus_book_view_call_start_sync (priv->gdbus_bookview, NULL, &local_error))
231 priv->running = FALSE;
233 e_client_unwrap_dbus_error (E_CLIENT (priv->client), local_error, error);
235 /* do not translate this string, it should ideally never happen */
236 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR, "Cannot start view, D-Bus proxy gone");
241 * e_book_client_view_stop:
242 * @view: an #EBookClientView
245 * Tells @view to stop processing events.
248 e_book_client_view_stop (EBookClientView *view,
251 EBookClientViewPrivate *priv;
253 g_return_if_fail (E_IS_BOOK_CLIENT_VIEW (view));
256 priv->running = FALSE;
258 if (priv->gdbus_bookview) {
259 GError *local_error = NULL;
261 e_gdbus_book_view_call_stop_sync (priv->gdbus_bookview, NULL, &local_error);
263 e_client_unwrap_dbus_error (E_CLIENT (priv->client), local_error, error);
265 /* do not translate this string, it should ideally never happen */
266 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR, "Cannot stop view, D-Bus proxy gone");
271 * e_book_client_view_set_flags:
272 * @view: an #EBookClientView
273 * @flags: the #EBookClientViewFlags for @view.
274 * @error: a return location for a #GError, or %NULL.
276 * Sets the @flags which control the behaviour of @view.
281 e_book_client_view_set_flags (EBookClientView *view,
282 EBookClientViewFlags flags,
285 EBookClientViewPrivate *priv;
287 g_return_if_fail (E_IS_BOOK_CLIENT_VIEW (view));
291 if (priv->gdbus_bookview) {
292 GError *local_error = NULL;
294 e_gdbus_book_view_call_set_flags_sync (priv->gdbus_bookview, flags, NULL, &local_error);
296 e_client_unwrap_dbus_error (E_CLIENT (priv->client), local_error, error);
298 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR,
299 "Cannot set flags on view, D-Bus proxy gone");
304 * e_book_client_view_set_fields_of_interest:
305 * @view: An #EBookClientView object
306 * @fields_of_interest: (element-type utf8): List of field names in which the client is interested
309 * Client can instruct server to which fields it is interested in only, thus
310 * the server can return less data over the wire. The server can still return
311 * complete objects, this is just a hint to it that the listed fields will
312 * be used only. The UID field is returned always. Initial views has no fields
313 * of interest and using %NULL for @fields_of_interest will unset any previous
316 * Some backends can use summary information of its cache to create artifical
317 * objects, which will omit stored object parsing. If this cannot be done then
318 * it will simply return object as is stored in the cache.
321 e_book_client_view_set_fields_of_interest (EBookClientView *view,
322 const GSList *fields_of_interest,
325 EBookClientViewPrivate *priv;
327 g_return_if_fail (E_IS_BOOK_CLIENT_VIEW (view));
331 if (priv->gdbus_bookview) {
332 GError *local_error = NULL;
335 strv = e_client_util_slist_to_strv (fields_of_interest);
336 e_gdbus_book_view_call_set_fields_of_interest_sync (priv->gdbus_bookview, (const gchar * const *) strv, NULL, &local_error);
339 e_client_unwrap_dbus_error (E_CLIENT (priv->client), local_error, error);
341 /* do not translate this string, it should ideally never happen */
342 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR, "Cannot set fields of interest, D-Bus proxy gone");
347 e_book_client_view_init (EBookClientView *view)
349 view->priv = E_BOOK_CLIENT_VIEW_GET_PRIVATE (view);
350 view->priv->gdbus_bookview = NULL;
352 view->priv->client = NULL;
353 view->priv->running = FALSE;
357 book_client_view_dispose (GObject *object)
359 EBookClientView *view = E_BOOK_CLIENT_VIEW (object);
361 if (view->priv->gdbus_bookview) {
362 GError *error = NULL;
364 g_signal_handlers_disconnect_matched (view->priv->gdbus_bookview, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view);
365 e_gdbus_book_view_call_dispose_sync (G_DBUS_PROXY (view->priv->gdbus_bookview), NULL, &error);
366 g_object_unref (view->priv->gdbus_bookview);
367 view->priv->gdbus_bookview = NULL;
370 g_warning ("Failed to dispose book view: %s", error->message);
371 g_error_free (error);
375 if (view->priv->client) {
376 g_object_unref (view->priv->client);
377 view->priv->client = NULL;
380 /* Chain up to parent's dispose() method. */
381 G_OBJECT_CLASS (e_book_client_view_parent_class)->dispose (object);
385 e_book_client_view_class_init (EBookClientViewClass *class)
387 GObjectClass *object_class;
389 g_type_class_add_private (class, sizeof (EBookClientViewPrivate));
391 object_class = G_OBJECT_CLASS (class);
392 object_class->dispose = book_client_view_dispose;
394 signals[OBJECTS_ADDED] =
395 g_signal_new ("objects-added",
396 G_OBJECT_CLASS_TYPE (object_class),
398 G_STRUCT_OFFSET (EBookClientViewClass, objects_added),
400 g_cclosure_marshal_VOID__POINTER,
401 G_TYPE_NONE, 1, G_TYPE_POINTER);
403 signals[OBJECTS_MODIFIED] =
404 g_signal_new ("objects-modified",
405 G_OBJECT_CLASS_TYPE (object_class),
407 G_STRUCT_OFFSET (EBookClientViewClass, objects_modified),
409 g_cclosure_marshal_VOID__POINTER,
410 G_TYPE_NONE, 1, G_TYPE_POINTER);
412 signals[OBJECTS_REMOVED] =
413 g_signal_new ("objects-removed",
414 G_OBJECT_CLASS_TYPE (object_class),
416 G_STRUCT_OFFSET (EBookClientViewClass, objects_removed),
418 g_cclosure_marshal_VOID__POINTER,
419 G_TYPE_NONE, 1, G_TYPE_POINTER);
422 g_signal_new ("progress",
423 G_OBJECT_CLASS_TYPE (object_class),
425 G_STRUCT_OFFSET (EBookClientViewClass, progress),
427 e_gdbus_marshallers_VOID__UINT_STRING,
428 G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
431 g_signal_new ("complete",
432 G_OBJECT_CLASS_TYPE (object_class),
434 G_STRUCT_OFFSET (EBookClientViewClass, complete),
436 g_cclosure_marshal_VOID__BOXED,
437 G_TYPE_NONE, 1, G_TYPE_ERROR);