From 653cfffc0e00dfb59b36813c1b45c53d3f773c65 Mon Sep 17 00:00:00 2001 From: Ettore Perazzoli Date: Tue, 21 Oct 2003 18:49:34 +0000 Subject: Merge new-ui-branch to the trunk. svn path=/trunk/; revision=22965 --- addressbook/backend/pas/pas-book-view.c | 362 ++++++++++++++++++++++++-------- 1 file changed, 270 insertions(+), 92 deletions(-) (limited to 'addressbook/backend/pas/pas-book-view.c') diff --git a/addressbook/backend/pas/pas-book-view.c b/addressbook/backend/pas/pas-book-view.c index fce4173f0f..712997d258 100644 --- a/addressbook/backend/pas/pas-book-view.c +++ b/addressbook/backend/pas/pas-book-view.c @@ -6,158 +6,266 @@ */ #include +#include #include #include +#include "pas-backend.h" +#include "pas-backend-card-sexp.h" #include "pas-book-view.h" static BonoboObjectClass *pas_book_view_parent_class; struct _PASBookViewPrivate { GNOME_Evolution_Addressbook_BookViewListener listener; + +#define INITIAL_THRESHOLD 20 + GMutex *pending_mutex; + + CORBA_sequence_GNOME_Evolution_Addressbook_VCard adds; + int next_threshold; + int threshold_max; + + CORBA_sequence_GNOME_Evolution_Addressbook_VCard changes; + CORBA_sequence_GNOME_Evolution_Addressbook_ContactId removes; + + PASBackend *backend; + char *card_query; + PASBackendCardSExp *card_sexp; + GHashTable *ids; }; -/** - * pas_book_view_notify_change: - */ -void -pas_book_view_notify_change (PASBookView *book_view, - const GList *cards) +static void +send_pending_adds (PASBookView *book_view, gboolean reset) { CORBA_Environment ev; - gint i, length; - CORBA_sequence_GNOME_Evolution_Addressbook_VCard card_sequence; + CORBA_sequence_GNOME_Evolution_Addressbook_VCard *adds; + + adds = &book_view->priv->adds; + if (adds->_length == 0) + return; - length = g_list_length((GList *) cards); + CORBA_exception_init (&ev); - card_sequence._buffer = CORBA_sequence_GNOME_Evolution_Addressbook_VCard_allocbuf(length); - card_sequence._maximum = length; - card_sequence._length = length; + GNOME_Evolution_Addressbook_BookViewListener_notifyContactsAdded ( + book_view->priv->listener, adds, &ev); - for ( i = 0; cards; cards = g_list_next(cards), i++ ) { - card_sequence._buffer[i] = CORBA_string_dup((char *) cards->data); + if (ev._major != CORBA_NO_EXCEPTION) { + g_warning ("send_pending_adds: Exception signaling BookViewListener!\n"); } + CORBA_exception_free (&ev); + + CORBA_free (adds->_buffer); + adds->_buffer = NULL; + adds->_maximum = 0; + adds->_length = 0; + + if (reset) + book_view->priv->next_threshold = INITIAL_THRESHOLD; +} + +static void +send_pending_changes (PASBookView *book_view) +{ + CORBA_Environment ev; + CORBA_sequence_GNOME_Evolution_Addressbook_VCard *changes; + + changes = &book_view->priv->changes; + if (changes->_length == 0) + return; + CORBA_exception_init (&ev); - GNOME_Evolution_Addressbook_BookViewListener_notifyCardChanged ( - book_view->priv->listener, &card_sequence, &ev); + GNOME_Evolution_Addressbook_BookViewListener_notifyContactsChanged ( + book_view->priv->listener, changes, &ev); if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_view_notify_change: Exception signaling BookViewListener!\n"); + g_warning ("send_pending_changes: Exception signaling BookViewListener!\n"); } CORBA_exception_free (&ev); - CORBA_free(card_sequence._buffer); + CORBA_free (changes->_buffer); + changes->_buffer = NULL; + changes->_maximum = 0; + changes->_length = 0; } -void -pas_book_view_notify_change_1 (PASBookView *book_view, - const char *card) +static void +send_pending_removes (PASBookView *book_view) { - GList *list = g_list_append(NULL, (char *) card); - pas_book_view_notify_change(book_view, list); - g_list_free(list); + CORBA_Environment ev; + CORBA_sequence_GNOME_Evolution_Addressbook_VCard *removes; + + removes = &book_view->priv->removes; + if (removes->_length == 0) + return; + + CORBA_exception_init (&ev); + + GNOME_Evolution_Addressbook_BookViewListener_notifyContactsRemoved ( + book_view->priv->listener, removes, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) { + g_warning ("send_pending_removes: Exception signaling BookViewListener!\n"); + } + + CORBA_exception_free (&ev); + + CORBA_free (removes->_buffer); + removes->_buffer = NULL; + removes->_maximum = 0; + removes->_length = 0; } -/** - * pas_book_view_notify_remove: - */ -void -pas_book_view_notify_remove_1 (PASBookView *book_view, - const char *id) +#define MAKE_REALLOC(type) \ +static void \ +CORBA_sequence_ ## type ## _realloc (CORBA_sequence_ ## type *seq, \ + CORBA_unsigned_long new_max) \ +{ \ + type *new_buf; \ + \ + new_buf = CORBA_sequence_ ## type ## _allocbuf (new_max); \ + memcpy (new_buf, seq->_buffer, seq->_maximum * sizeof (type)); \ + CORBA_free (seq->_buffer); \ + seq->_buffer = new_buf; \ + seq->_maximum = new_max; \ +} + +MAKE_REALLOC (GNOME_Evolution_Addressbook_VCard) +MAKE_REALLOC (GNOME_Evolution_Addressbook_ContactId) + +static void +notify_change (PASBookView *book_view, const char *vcard) { - GList *ids = NULL; + CORBA_sequence_GNOME_Evolution_Addressbook_VCard *changes; + + send_pending_adds (book_view, TRUE); + send_pending_removes (book_view); - ids = g_list_prepend (ids, (char*)id); + changes = &book_view->priv->changes; - pas_book_view_notify_remove (book_view, ids); + if (changes->_length == changes->_maximum) { + CORBA_sequence_GNOME_Evolution_Addressbook_VCard_realloc ( + changes, 2 * (changes->_maximum + 1)); + } - g_list_free (ids); + changes->_buffer[changes->_length++] = CORBA_string_dup (vcard); } -void -pas_book_view_notify_remove (PASBookView *book_view, - const GList *ids) +static void +notify_remove (PASBookView *book_view, const char *id) { - GNOME_Evolution_Addressbook_CardIdList idlist; - CORBA_Environment ev; - const GList *l; - int num_ids, i; + CORBA_sequence_GNOME_Evolution_Addressbook_ContactId *removes; - CORBA_exception_init (&ev); + send_pending_adds (book_view, TRUE); + send_pending_changes (book_view); - num_ids = g_list_length ((GList*)ids); - idlist._buffer = CORBA_sequence_GNOME_Evolution_Addressbook_CardId_allocbuf (num_ids); - idlist._maximum = num_ids; - idlist._length = num_ids; + removes = &book_view->priv->removes; - for (l = ids, i = 0; l; l=l->next, i ++) { - idlist._buffer[i] = CORBA_string_dup (l->data); + if (removes->_length == removes->_maximum) { + CORBA_sequence_GNOME_Evolution_Addressbook_ContactId_realloc ( + removes, 2 * (removes->_maximum + 1)); } - GNOME_Evolution_Addressbook_BookViewListener_notifyCardsRemoved ( - book_view->priv->listener, &idlist, &ev); + removes->_buffer[removes->_length++] = CORBA_string_dup (id); + g_hash_table_remove (book_view->priv->ids, id); +} - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_view_notify_remove: Exception signaling BookViewListener!\n"); - } +static void +notify_add (PASBookView *book_view, const char *id, const char *vcard) +{ + CORBA_sequence_GNOME_Evolution_Addressbook_VCard *adds; + PASBookViewPrivate *priv = book_view->priv; - CORBA_free(idlist._buffer); + send_pending_changes (book_view); + send_pending_removes (book_view); - CORBA_exception_free (&ev); + adds = &priv->adds; + + if (adds->_length == adds->_maximum) { + send_pending_adds (book_view, FALSE); + + adds->_buffer = CORBA_sequence_GNOME_Evolution_Addressbook_VCard_allocbuf (priv->next_threshold); + adds->_maximum = priv->next_threshold; + + if (priv->next_threshold < priv->threshold_max) { + priv->next_threshold = MIN (2 * priv->next_threshold, + priv->threshold_max); + } + } + + adds->_buffer[adds->_length++] = CORBA_string_dup (vcard); + g_hash_table_insert (book_view->priv->ids, g_strdup (id), + GUINT_TO_POINTER (1)); } /** - * pas_book_view_notify_add: + * pas_book_view_notify_update: */ void -pas_book_view_notify_add (PASBookView *book_view, - const GList *cards) +pas_book_view_notify_update (PASBookView *book_view, + EContact *contact) { - CORBA_Environment ev; - gint i, length; - CORBA_sequence_GNOME_Evolution_Addressbook_VCard card_sequence; + gboolean currently_in_view, want_in_view; + const char *id; + char *vcard; - length = g_list_length((GList *)cards); + g_mutex_lock (book_view->priv->pending_mutex); - card_sequence._buffer = CORBA_sequence_GNOME_Evolution_Addressbook_VCard_allocbuf(length); - card_sequence._maximum = length; - card_sequence._length = length; + id = e_contact_get_const (contact, E_CONTACT_UID); - for ( i = 0; cards; cards = g_list_next(cards), i++ ) { - card_sequence._buffer[i] = CORBA_string_dup((char *) cards->data); - } + currently_in_view = + g_hash_table_lookup (book_view->priv->ids, id) != NULL; + want_in_view = pas_backend_card_sexp_match_contact ( + book_view->priv->card_sexp, contact); - CORBA_exception_init (&ev); + if (want_in_view) { + vcard = e_vcard_to_string (E_VCARD (contact), + EVC_FORMAT_VCARD_30); - GNOME_Evolution_Addressbook_BookViewListener_notifyCardAdded ( - book_view->priv->listener, &card_sequence, &ev); + if (currently_in_view) + notify_change (book_view, vcard); + else + notify_add (book_view, id, vcard); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("pas_book_view_notify_add: Exception signaling BookViewListener!\n"); + g_free (vcard); + } else { + if (currently_in_view) + pas_book_view_notify_remove (book_view, id); + /* else nothing; we're removing a card that wasn't there */ } - CORBA_exception_free (&ev); - - CORBA_free(card_sequence._buffer); + g_mutex_unlock (book_view->priv->pending_mutex); } +/** + * pas_book_view_notify_remove: + */ void -pas_book_view_notify_add_1 (PASBookView *book_view, - const char *card) +pas_book_view_notify_remove (PASBookView *book_view, + const char *id) { - GList *list = g_list_append(NULL, (char *) card); - pas_book_view_notify_add(book_view, list); - g_list_free(list); + g_mutex_lock (book_view->priv->pending_mutex); + notify_remove (book_view, id); + g_mutex_unlock (book_view->priv->pending_mutex); } + void pas_book_view_notify_complete (PASBookView *book_view, - GNOME_Evolution_Addressbook_BookViewListener_CallStatus status) + GNOME_Evolution_Addressbook_CallStatus status) { 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 ( @@ -178,8 +286,8 @@ pas_book_view_notify_status_message (PASBookView *book_view, CORBA_exception_init (&ev); - GNOME_Evolution_Addressbook_BookViewListener_notifyStatusMessage ( - book_view->priv->listener, message, &ev); + GNOME_Evolution_Addressbook_BookViewListener_notifyProgress ( + book_view->priv->listener, message, 0, &ev); if (ev._major != CORBA_NO_EXCEPTION) { g_warning ("pas_book_view_notify_status_message: Exception signaling BookViewListener!\n"); @@ -190,7 +298,10 @@ pas_book_view_notify_status_message (PASBookView *book_view, static void pas_book_view_construct (PASBookView *book_view, - GNOME_Evolution_Addressbook_BookViewListener listener) + PASBackend *backend, + GNOME_Evolution_Addressbook_BookViewListener listener, + const char *card_query, + PASBackendCardSExp *card_sexp) { PASBookViewPrivate *priv; CORBA_Environment ev; @@ -202,29 +313,70 @@ pas_book_view_construct (PASBookView *book_view, CORBA_exception_init (&ev); - bonobo_object_dup_ref (listener, &ev); + priv->listener = CORBA_Object_duplicate (listener, &ev); if (ev._major != CORBA_NO_EXCEPTION) { - g_warning("Unable to duplicate & ref listener object in pas-book-view.c\n"); + g_warning("Unable to duplicate listener object in pas-book-view.c\n"); CORBA_exception_free (&ev); return; } CORBA_exception_free (&ev); - priv->listener = listener; + priv->backend = backend; + priv->card_query = g_strdup (card_query); + priv->card_sexp = card_sexp; +} + +/** + * pas_book_view_new: + */ +static void +impl_GNOME_Evolution_Addressbook_BookView_start (PortableServer_Servant servant, + CORBA_Environment *ev) +{ + PASBookView *view = PAS_BOOK_VIEW (bonobo_object (servant)); + + pas_backend_start_book_view (pas_book_view_get_backend (view), view); +} + +/** + * pas_book_view_get_card_query + */ +const char* +pas_book_view_get_card_query (PASBookView *book_view) +{ + return book_view->priv->card_query; +} + +/** + * pas_book_view_get_card_sexp + */ +PASBackendCardSExp* +pas_book_view_get_card_sexp (PASBookView *book_view) +{ + return book_view->priv->card_sexp; +} + +PASBackend* +pas_book_view_get_backend (PASBookView *book_view) +{ + return book_view->priv->backend; } /** * pas_book_view_new: */ PASBookView * -pas_book_view_new (GNOME_Evolution_Addressbook_BookViewListener listener) +pas_book_view_new (PASBackend *backend, + GNOME_Evolution_Addressbook_BookViewListener listener, + const char *card_query, + PASBackendCardSExp *card_sexp) { PASBookView *book_view; book_view = g_object_new (PAS_TYPE_BOOK_VIEW, NULL); - pas_book_view_construct (book_view, listener); + pas_book_view_construct (book_view, backend, listener, card_query, card_sexp); return book_view; } @@ -237,6 +389,19 @@ pas_book_view_dispose (GObject *object) 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); + book_view->priv->pending_mutex = NULL; + g_free (book_view->priv); book_view->priv = NULL; } @@ -249,17 +414,30 @@ static void pas_book_view_class_init (PASBookViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + POA_GNOME_Evolution_Addressbook_BookView__epv *epv; pas_book_view_parent_class = g_type_class_peek_parent (klass); object_class->dispose = pas_book_view_dispose; + + epv = &klass->epv; + + epv->start = impl_GNOME_Evolution_Addressbook_BookView_start; + } static void pas_book_view_init (PASBookView *book_view) { - book_view->priv = g_new0 (PASBookViewPrivate, 1); - book_view->priv->listener = CORBA_OBJECT_NIL; + book_view->priv = g_new0 (PASBookViewPrivate, 1); + + book_view->priv->pending_mutex = g_mutex_new(); + + book_view->priv->next_threshold = INITIAL_THRESHOLD; + book_view->priv->threshold_max = 3000; + + book_view->priv->ids = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); } BONOBO_TYPE_FUNC_FULL ( -- cgit