/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* The Evolution addressbook client object.
*
* Author:
* Nat Friedman (nat@ximian.com)
*
* Copyright 1999, 2000, Ximian, Inc.
*/
#include <config.h>
#include "addressbook.h"
#include "e-card-cursor.h"
#include "e-book-view-listener.h"
#include "e-book-view.h"
#include "e-book.h"
#include "e-book-marshal.h"
static GObjectClass *parent_class;
struct _EBookViewPrivate {
GNOME_Evolution_Addressbook_BookView corba_book_view;
EBook *book;
EBookViewListener *listener;
int responses_queued_id;
};
enum {
CARD_CHANGED,
CARD_REMOVED,
CARD_ADDED,
SEQUENCE_COMPLETE,
STATUS_MESSAGE,
LAST_SIGNAL
};
static guint e_book_view_signals [LAST_SIGNAL];
static void
add_book_iterator (gpointer data, gpointer closure)
{
ECard *card = E_CARD (data);
EBook *book = E_BOOK (closure);
e_card_set_book (card, book);
}
static void
e_book_view_do_added_event (EBookView *book_view,
EBookViewListenerResponse *resp)
{
if (book_view->priv->book)
g_list_foreach (resp->cards, add_book_iterator, book_view->priv->book);
g_signal_emit (book_view, e_book_view_signals [CARD_ADDED], 0,
resp->cards);
g_list_foreach (resp->cards, (GFunc) g_object_unref, NULL);
g_list_free (resp->cards);
}
static void
e_book_view_do_modified_event (EBookView *book_view,
EBookViewListenerResponse *resp)
{
if (book_view->priv->book)
g_list_foreach (resp->cards, add_book_iterator, book_view->priv->book);
g_signal_emit (book_view, e_book_view_signals [CARD_CHANGED], 0,
resp->cards);
g_list_foreach (resp->cards, (GFunc) g_object_unref, NULL);
g_list_free (resp->cards);
}
static void
e_book_view_do_removed_event (EBookView *book_view,
EBookViewListenerResponse *resp)
{
g_signal_emit (book_view, e_book_view_signals [CARD_REMOVED], 0,
resp->id);
g_free(resp->id);
}
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);
}
static void
e_book_view_do_status_message_event (EBookView *book_view,
EBookViewListenerResponse *resp)
{
g_signal_emit (book_view, e_book_view_signals [STATUS_MESSAGE], 0,
resp->message);
g_free(resp->message);
}
/*
* Reading notices out of the EBookViewListener's queue.
*/
static void
e_book_view_check_listener_queue (EBookViewListener *listener, EBookView *book_view)
{
EBookViewListenerResponse *resp;
resp = e_book_view_listener_pop_response (listener);
if (resp == NULL)
return;
switch (resp->op) {
case CardAddedEvent:
e_book_view_do_added_event (book_view, resp);
break;
case CardModifiedEvent:
e_book_view_do_modified_event (book_view, resp);
break;
case CardRemovedEvent:
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;
}
g_free (resp);
}
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);
/*
* Copy in the corba_book_view.
*/
CORBA_exception_init (&ev);
book_view->priv->corba_book_view = bonobo_object_dup_ref(corba_book_view, &ev);
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 = NULL;
return FALSE;
}
CORBA_exception_free (&ev);
/*
* Create our local BookListener interface.
*/
book_view->priv->listener = listener;
book_view->priv->responses_queued_id = g_signal_connect (book_view->priv->listener, "responses_queued",
G_CALLBACK (e_book_view_check_listener_queue), book_view);
bonobo_object_ref(BONOBO_OBJECT(book_view->priv->listener));
return TRUE;
}
/**
* e_book_view_new:
*/
EBookView *
e_book_view_new (GNOME_Evolution_Addressbook_BookView corba_book_view, EBookViewListener *listener)
{
EBookView *book_view;
book_view = g_object_new (E_TYPE_BOOK_VIEW, NULL);
if (! e_book_view_construct (book_view, corba_book_view, listener)) {
g_object_unref (book_view);
return NULL;
}
return book_view;
}
void
e_book_view_set_book (EBookView *book_view, EBook *book)
{
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);
book_view->priv->book = book;
g_object_ref (book);
}
void
e_book_view_stop (EBookView *book_view)
{
g_return_if_fail (book_view && E_IS_BOOK_VIEW (book_view));
if (book_view->priv->listener)
e_book_view_listener_stop (book_view->priv->listener);
}
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->responses_queued_id = 0;
}
static void
e_book_view_dispose (GObject *object)
{
EBookView *book_view = E_BOOK_VIEW (object);
CORBA_Environment ev;
if (book_view->priv->book) {
g_object_unref (book_view->priv->book);
}
if (book_view->priv->corba_book_view) {
CORBA_exception_init (&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);
}
if (book_view->priv->listener) {
if (book_view->priv->responses_queued_id)
g_signal_handler_disconnect(book_view->priv->listener,
book_view->priv->responses_queued_id);
e_book_view_listener_stop (book_view->priv->listener);
bonobo_object_unref (BONOBO_OBJECT(book_view->priv->listener));
}
g_free (book_view->priv);
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 [CARD_CHANGED] =
g_signal_new ("card_changed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EBookViewClass, card_changed),
NULL, NULL,
e_book_marshal_NONE__POINTER,
G_TYPE_NONE, 1,
G_TYPE_POINTER);
e_book_view_signals [CARD_ADDED] =
g_signal_new ("card_added",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EBookViewClass, card_added),
NULL, NULL,
e_book_marshal_NONE__STRING,
G_TYPE_NONE, 1,
G_TYPE_STRING);
e_book_view_signals [CARD_REMOVED] =
g_signal_new ("card_removed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EBookViewClass, card_removed),
NULL, NULL,
e_book_marshal_NONE__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,
e_book_marshal_NONE__ENUM,
G_TYPE_NONE, 1,
G_TYPE_ENUM);
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,
e_book_marshal_NONE__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;
}