diff options
Diffstat (limited to 'addressbook/gui/widgets')
31 files changed, 3066 insertions, 5054 deletions
diff --git a/addressbook/gui/widgets/Makefile.am b/addressbook/gui/widgets/Makefile.am index c3a14d8aeb..9e3affcb2f 100644 --- a/addressbook/gui/widgets/Makefile.am +++ b/addressbook/gui/widgets/Makefile.am @@ -7,11 +7,11 @@ INCLUDES = \ -DEVOLUTION_GALVIEWSDIR=\""$(viewsdir)"\" \ -DSEARCH_RULE_DIR=\"$(ruledir)\" \ -I$(top_srcdir) \ + -I$(top_srcdir)/filter \ -I$(top_srcdir)/widgets \ -I$(top_srcdir)/addressbook \ - -I$(top_srcdir)/addressbook/gui/contact-editor \ -I$(top_srcdir)/addressbook/gui/merging \ - -I$(top_srcdir)/addressbook/gui/component \ + -I$(top_srcdir)/addressbook/util \ -I$(top_srcdir)/widgets/misc \ -I$(top_builddir)/shell \ $(EVOLUTION_ADDRESSBOOK_CFLAGS) @@ -22,9 +22,7 @@ noinst_LTLIBRARIES = \ eabincludedir = $(privincludedir)/addressbook/gui/widgets eabinclude_HEADERS = \ - eab-config.h \ - eab-menu.h \ - eab-popup.h + eab-config.h libeabwidgets_la_SOURCES = \ eab-config.c \ @@ -32,13 +30,6 @@ libeabwidgets_la_SOURCES = \ eab-contact-display.h \ eab-gui-util.c \ eab-gui-util.h \ - eab-menu.c \ - eab-popup.c \ - eab-popup.h \ - eab-popup-control.c \ - eab-popup-control.h \ - eab-vcard-control.c \ - eab-vcard-control.h \ e-minicard.c \ e-minicard.h \ e-minicard-label.c \ @@ -53,6 +44,8 @@ libeabwidgets_la_SOURCES = \ e-addressbook-table-adapter.h \ e-addressbook-model.c \ e-addressbook-model.h \ + e-addressbook-selector.c \ + e-addressbook-selector.h \ e-addressbook-view.c \ e-addressbook-view.h \ gal-view-minicard.c \ @@ -60,6 +53,10 @@ libeabwidgets_la_SOURCES = \ gal-view-factory-minicard.c \ gal-view-factory-minicard.h +libeabwidgets_la_LIBADD = \ + $(top_builddir)/widgets/misc/libemiscwidgets.la \ + $(top_builddir)/a11y/addressbook/libevolution-addressbook-a11y.la + dist-hook: cd $(distdir); rm -f $(BUILT_SOURCES) @@ -67,6 +64,6 @@ etspec_DATA= e-addressbook-view.etspec EXTRA_DIST = \ $(etspec_DATA) \ - addresstypes.xml + $(rule_DATA) -include $(top_srcdir)/git.mk diff --git a/addressbook/gui/widgets/e-addressbook-model.c b/addressbook/gui/widgets/e-addressbook-model.c index 7273689fd1..772e72e3af 100644 --- a/addressbook/gui/widgets/e-addressbook-model.c +++ b/addressbook/gui/widgets/e-addressbook-model.c @@ -22,32 +22,45 @@ #include <config.h> #include <string.h> -#include <gtk/gtk.h> #include <glib/gi18n.h> -#include "e-util/e-util.h" #include "e-addressbook-model.h" -#include <libxml/tree.h> -#include <libxml/parser.h> -#include <libxml/xmlmemory.h> +#include <e-util/e-util.h> #include <misc/e-gui-utils.h> #include "eab-gui-util.h" -#define PARENT_TYPE G_TYPE_OBJECT -static GObjectClass *parent_class; - -/* - * EABModel callbacks - * These are the callbacks that define the behavior of our custom model. - */ -static void eab_model_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); -static void eab_model_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); - +#define E_ADDRESSBOOK_MODEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ADDRESSBOOK_MODEL, EAddressbookModelPrivate)) + +struct _EAddressbookModelPrivate { + EBook *book; + EBookQuery *query; + EBookView *book_view; + guint book_view_idle_id; + + /* Query Results */ + GPtrArray *contacts; + + /* Signal Handler IDs */ + gulong create_contact_id; + gulong remove_contact_id; + gulong modify_contact_id; + gulong status_message_id; + gulong writable_status_id; + gulong sequence_complete_id; + gulong backend_died_id; + + guint search_in_progress : 1; + guint editable : 1; + guint editable_set : 1; + guint first_get_view : 1; +}; enum { PROP_0, PROP_BOOK, - PROP_QUERY, PROP_EDITABLE, + PROP_QUERY }; enum { @@ -65,673 +78,799 @@ enum { LAST_SIGNAL }; -static guint eab_model_signals [LAST_SIGNAL] = {0, }; +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; static void -free_data (EABModel *model) +free_data (EAddressbookModel *model) { - if (model->data) { - int i; - - for ( i = 0; i < model->data_count; i++ ) { - g_object_unref (model->data[i]); - } + GPtrArray *array; - g_free(model->data); - model->data = NULL; - model->data_count = 0; - model->allocated_count = 0; - } + array = model->priv->contacts; + g_ptr_array_foreach (array, (GFunc) g_object_unref, NULL); + g_ptr_array_set_size (array, 0); } static void -remove_book_view(EABModel *model) -{ - if (model->book_view && model->create_contact_id) - g_signal_handler_disconnect (model->book_view, - model->create_contact_id); - if (model->book_view && model->remove_contact_id) - g_signal_handler_disconnect (model->book_view, - model->remove_contact_id); - if (model->book_view && model->modify_contact_id) - g_signal_handler_disconnect (model->book_view, - model->modify_contact_id); - if (model->book_view && model->status_message_id) - g_signal_handler_disconnect (model->book_view, - model->status_message_id); - if (model->book_view && model->sequence_complete_id) - g_signal_handler_disconnect (model->book_view, - model->sequence_complete_id); - - model->create_contact_id = 0; - model->remove_contact_id = 0; - model->modify_contact_id = 0; - model->status_message_id = 0; - model->sequence_complete_id = 0; - - model->search_in_progress = FALSE; - - if (model->book_view) { - e_book_view_stop (model->book_view); - g_object_unref (model->book_view); - model->book_view = NULL; - } -} - -static void -addressbook_dispose(GObject *object) +remove_book_view(EAddressbookModel *model) { - EABModel *model = EAB_MODEL(object); - - remove_book_view(model); - free_data (model); - - if (model->book) { - if (model->writable_status_id) - g_signal_handler_disconnect (model->book, - model->writable_status_id); - model->writable_status_id = 0; - - if (model->backend_died_id) - g_signal_handler_disconnect (model->book, - model->backend_died_id); - model->backend_died_id = 0; - - g_object_unref (model->book); - model->book = NULL; + if (model->priv->book_view && model->priv->create_contact_id) + g_signal_handler_disconnect ( + model->priv->book_view, + model->priv->create_contact_id); + if (model->priv->book_view && model->priv->remove_contact_id) + g_signal_handler_disconnect ( + model->priv->book_view, + model->priv->remove_contact_id); + if (model->priv->book_view && model->priv->modify_contact_id) + g_signal_handler_disconnect ( + model->priv->book_view, + model->priv->modify_contact_id); + if (model->priv->book_view && model->priv->status_message_id) + g_signal_handler_disconnect ( + model->priv->book_view, + model->priv->status_message_id); + if (model->priv->book_view && model->priv->sequence_complete_id) + g_signal_handler_disconnect ( + model->priv->book_view, + model->priv->sequence_complete_id); + + model->priv->create_contact_id = 0; + model->priv->remove_contact_id = 0; + model->priv->modify_contact_id = 0; + model->priv->status_message_id = 0; + model->priv->sequence_complete_id = 0; + + model->priv->search_in_progress = FALSE; + + if (model->priv->book_view) { + e_book_view_stop (model->priv->book_view); + g_object_unref (model->priv->book_view); + model->priv->book_view = NULL; } - - if (model->query) { - e_book_query_unref (model->query); - model->query = NULL; - } - - if (G_OBJECT_CLASS(parent_class)->dispose) - G_OBJECT_CLASS(parent_class)->dispose(object); } static void -update_folder_bar_message (EABModel *model) +update_folder_bar_message (EAddressbookModel *model) { - int count; + guint count; char *message; - count = model->data_count; + count = model->priv->contacts->len; switch (count) { case 0: message = g_strdup (_("No contacts")); break; default: - message = g_strdup_printf (ngettext("%d contact", "%d contacts", count), count); + message = g_strdup_printf ( + ngettext ("%d contact", "%d contacts", count), count); break; } - g_signal_emit (model, - eab_model_signals [FOLDER_BAR_MESSAGE], 0, - message); + g_signal_emit (model, signals[FOLDER_BAR_MESSAGE], 0, message); g_free (message); } static void -create_contact(EBookView *book_view, - const GList *contacts, - EABModel *model) +create_contact (EBookView *book_view, + const GList *contact_list, + EAddressbookModel *model) { - int old_count = model->data_count; - int length = g_list_length ((GList *)contacts); + GPtrArray *array; + guint count; + guint index; - if (model->data_count + length > model->allocated_count) { - while (model->data_count + length > model->allocated_count) - model->allocated_count = model->allocated_count * 2 + 1; - model->data = g_renew(EContact *, model->data, model->allocated_count); - } + array = model->priv->contacts; + index = array->len; + count = g_list_length ((GList *) contact_list); - for ( ; contacts; contacts = contacts->next) { - model->data[model->data_count++] = contacts->data; - g_object_ref (contacts->data); - } + while (contact_list != NULL) { + EContact *contact = contact_list->data; - g_signal_emit (model, - eab_model_signals [CONTACT_ADDED], 0, - old_count, model->data_count - old_count); + g_ptr_array_add (array, g_object_ref (contact)); + contact_list = contact_list->next; + } + g_signal_emit (model, signals[CONTACT_ADDED], 0, index, count); update_folder_bar_message (model); } static void remove_contact(EBookView *book_view, GList *ids, - EABModel *model) + EAddressbookModel *model) { /* XXX we should keep a hash around instead of this O(n*m) loop */ - gint i = 0; - GList *l; + GList *iter; GArray *indices; + GPtrArray *array; + gint ii; + array = model->priv->contacts; indices = g_array_new (FALSE, FALSE, sizeof (gint)); - for (l = ids; l; l = l->next) { - char *id = l->data; - for ( i = 0; i < model->data_count; i++) { - if ( !strcmp(e_contact_get_const (model->data[i], E_CONTACT_UID), id) ) { - g_object_unref (model->data[i]); - memmove(model->data + i, model->data + i + 1, (model->data_count - i - 1) * sizeof (EContact *)); - model->data_count--; - g_array_append_val (indices, i); - break; + + for (iter = ids; iter != NULL; iter = iter->next) { + const gchar *target_uid = iter->data; + + for (ii = 0; ii < array->len; ii++) { + EContact *contact; + const gchar *uid; + + contact = array->pdata[ii]; + uid = e_contact_get_const (contact, E_CONTACT_UID); + if (strcmp (uid, target_uid) == 0) { + g_object_unref (contact); + g_array_append_val (indices, ii); } } } - g_signal_emit (model, - eab_model_signals [CONTACTS_REMOVED], 0, - indices); + + for (ii = 0; ii < indices->len; ii++) { + gint index; + + index = g_array_index (indices, gint, ii); + g_ptr_array_remove_index (array, index); + } + + g_signal_emit (model, signals[CONTACTS_REMOVED], 0, indices); g_array_free (indices, FALSE); + update_folder_bar_message (model); } static void modify_contact(EBookView *book_view, - const GList *contacts, - EABModel *model) -{ - for ( ; contacts; contacts = contacts->next) { - int i; - for ( i = 0; i < model->data_count; i++) { - if ( !strcmp(e_contact_get_const(model->data[i], E_CONTACT_UID), - e_contact_get_const(E_CONTACT(contacts->data), E_CONTACT_UID)) ) { - g_object_unref (model->data[i]); - model->data[i] = e_contact_duplicate(E_CONTACT(contacts->data)); - g_signal_emit (model, - eab_model_signals [CONTACT_CHANGED], 0, - i); - break; - } + const GList *contact_list, + EAddressbookModel *model) +{ + GPtrArray *array; + + array = model->priv->contacts; + + while (contact_list != NULL) { + EContact *contact = contact_list->data; + const gchar *target_uid; + gint ii; + + target_uid = e_contact_get_const (contact, E_CONTACT_UID); + + for (ii = 0; ii < array->len; ii++) { + const gchar *uid; + + uid = e_contact_get_const ( + array->pdata[ii], E_CONTACT_UID); + + if (strcmp (uid, target_uid) != 0) + continue; + + g_object_unref (array->pdata[ii]); + contact = e_contact_duplicate (contact); + array->pdata[ii] = contact; + + g_signal_emit ( + model, signals[CONTACT_CHANGED], 0, contact); + break; } + + contact_list = contact_list->next; } } static void status_message (EBookView *book_view, char* status, - EABModel *model) + EAddressbookModel *model) { - g_signal_emit (model, - eab_model_signals [STATUS_MESSAGE], 0, - status); + g_signal_emit (model, signals[STATUS_MESSAGE], 0, status); } static void sequence_complete (EBookView *book_view, - EBookViewStatus status, - EABModel *model) + EBookViewStatus status, + EAddressbookModel *model) { - model->search_in_progress = FALSE; + model->priv->search_in_progress = FALSE; status_message (book_view, NULL, model); - g_signal_emit (model, - eab_model_signals [SEARCH_RESULT], 0, - status); - g_signal_emit (model, - eab_model_signals [STOP_STATE_CHANGED], 0); + g_signal_emit (model, signals[SEARCH_RESULT], 0, status); + g_signal_emit (model, signals[STOP_STATE_CHANGED], 0); } static void writable_status (EBook *book, gboolean writable, - EABModel *model) + EAddressbookModel *model) { - if (!model->editable_set) { - model->editable = writable; + if (!model->priv->editable_set) { + model->priv->editable = writable; - g_signal_emit (model, - eab_model_signals [WRITABLE_STATUS], 0, - writable); + g_signal_emit (model, signals[WRITABLE_STATUS], 0, writable); } } static void backend_died (EBook *book, - EABModel *model) + EAddressbookModel *model) +{ + g_signal_emit (model, signals[BACKEND_DIED], 0); +} + +static void +book_view_loaded (EBook *book, + EBookStatus status, + EBookView *book_view, + gpointer closure) +{ + EAddressbookModel *model = closure; + + if (status != E_BOOK_ERROR_OK) { + eab_error_dialog (_("Error getting book view"), status); + return; + } + + remove_book_view (model); + free_data (model); + + model->priv->book_view = book_view; + if (model->priv->book_view) + g_object_ref (model->priv->book_view); + + model->priv->create_contact_id = g_signal_connect ( + model->priv->book_view, "contacts-added", + G_CALLBACK (create_contact), model); + model->priv->remove_contact_id = g_signal_connect ( + model->priv->book_view, "contacts-removed", + G_CALLBACK (remove_contact), model); + model->priv->modify_contact_id = g_signal_connect ( + model->priv->book_view, "contacts-changed", + G_CALLBACK (modify_contact), model); + model->priv->status_message_id = g_signal_connect ( + model->priv->book_view, "status-message", + G_CALLBACK (status_message), model); + model->priv->sequence_complete_id = g_signal_connect ( + model->priv->book_view, "sequence-complete", + G_CALLBACK (sequence_complete), model); + + model->priv->search_in_progress = TRUE; + g_signal_emit (model, signals[MODEL_CHANGED], 0); + g_signal_emit (model, signals[SEARCH_STARTED], 0); + g_signal_emit (model, signals[STOP_STATE_CHANGED], 0); + + e_book_view_start (model->priv->book_view); +} + +static gboolean +addressbook_model_idle_cb (EAddressbookModel *model) +{ + model->priv->book_view_idle_id = 0; + + if (model->priv->book && model->priv->query) { + ESource *source; + const char *limit_str; + int limit = -1; + + source = e_book_get_source (model->priv->book); + + limit_str = e_source_get_property (source, "limit"); + if (limit_str && *limit_str) + limit = atoi (limit_str); + + remove_book_view(model); + + if (model->priv->first_get_view) { + model->priv->first_get_view = FALSE; + + if (e_book_check_static_capability (model->priv->book, "do-initial-query")) { + e_book_async_get_book_view ( + model->priv->book, model->priv->query, + NULL, limit, book_view_loaded, model); + } else { + free_data (model); + + g_signal_emit (model, + signals[MODEL_CHANGED], 0); + g_signal_emit (model, + signals[STOP_STATE_CHANGED], 0); + } + } else + e_book_async_get_book_view ( + model->priv->book, model->priv->query, + NULL, limit, book_view_loaded, model); + + } + + g_object_unref (model); + + return FALSE; +} + +static void +addressbook_model_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id){ + case PROP_BOOK: + e_addressbook_model_set_book ( + E_ADDRESSBOOK_MODEL (object), + g_value_get_object (value)); + return; + + case PROP_EDITABLE: + e_addressbook_model_set_editable ( + E_ADDRESSBOOK_MODEL (object), + g_value_get_boolean (value)); + return; + + case PROP_QUERY: + e_addressbook_model_set_query ( + E_ADDRESSBOOK_MODEL (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + +} + +static void +addressbook_model_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_BOOK: + g_value_set_object ( + value, e_addressbook_model_get_book ( + E_ADDRESSBOOK_MODEL (object))); + return; + + case PROP_EDITABLE: + g_value_set_boolean ( + value, e_addressbook_model_get_editable ( + E_ADDRESSBOOK_MODEL (object))); + return; + + case PROP_QUERY: + g_value_take_string ( + value, e_addressbook_model_get_query ( + E_ADDRESSBOOK_MODEL (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +addressbook_model_dispose (GObject *object) { - g_signal_emit (model, - eab_model_signals [BACKEND_DIED], 0); + EAddressbookModel *model = E_ADDRESSBOOK_MODEL(object); + + remove_book_view (model); + free_data (model); + + if (model->priv->book) { + if (model->priv->writable_status_id) + g_signal_handler_disconnect ( + model->priv->book, + model->priv->writable_status_id); + model->priv->writable_status_id = 0; + + if (model->priv->backend_died_id) + g_signal_handler_disconnect ( + model->priv->book, + model->priv->backend_died_id); + model->priv->backend_died_id = 0; + + g_object_unref (model->priv->book); + model->priv->book = NULL; + } + + if (model->priv->query) { + e_book_query_unref (model->priv->query); + model->priv->query = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } static void -eab_model_class_init (GObjectClass *object_class) -{ - parent_class = g_type_class_ref (PARENT_TYPE); - - object_class->dispose = addressbook_dispose; - object_class->set_property = eab_model_set_property; - object_class->get_property = eab_model_get_property; - - g_object_class_install_property (object_class, PROP_BOOK, - g_param_spec_object ("book", - _("Book"), - /*_( */"XXX blurb" /*)*/, - E_TYPE_BOOK, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_QUERY, - g_param_spec_string ("query", - _("Query"), - /*_( */"XXX blurb" /*)*/, - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_EDITABLE, - g_param_spec_boolean ("editable", - _("Editable"), - /*_( */"XXX blurb" /*)*/, - FALSE, - G_PARAM_READWRITE)); - - eab_model_signals [WRITABLE_STATUS] = +addressbook_model_finalize (GObject *object) +{ + EAddressbookModelPrivate *priv; + + priv = E_ADDRESSBOOK_MODEL_GET_PRIVATE (object); + + g_ptr_array_free (priv->contacts, TRUE); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +addressbook_model_class_init (EAddressbookModelClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EAddressbookModelPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = addressbook_model_set_property; + object_class->get_property = addressbook_model_get_property; + object_class->dispose = addressbook_model_dispose; + object_class->finalize = addressbook_model_finalize; + + g_object_class_install_property ( + object_class, + PROP_BOOK, + g_param_spec_object ( + "book", + _("Book"), + NULL, + E_TYPE_BOOK, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_EDITABLE, + g_param_spec_boolean ( + "editable", + _("Editable"), + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_QUERY, + g_param_spec_string ( + "query", + _("Query"), + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + signals[WRITABLE_STATUS] = g_signal_new ("writable_status", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, writable_status), + G_STRUCT_OFFSET (EAddressbookModelClass, writable_status), NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - eab_model_signals [STATUS_MESSAGE] = + signals[STATUS_MESSAGE] = g_signal_new ("status_message", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, status_message), + G_STRUCT_OFFSET (EAddressbookModelClass, status_message), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); - eab_model_signals [SEARCH_STARTED] = + signals[SEARCH_STARTED] = g_signal_new ("search_started", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, search_started), + G_STRUCT_OFFSET (EAddressbookModelClass, search_started), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - eab_model_signals [SEARCH_RESULT] = + signals[SEARCH_RESULT] = g_signal_new ("search_result", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, search_result), + G_STRUCT_OFFSET (EAddressbookModelClass, search_result), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); - eab_model_signals [FOLDER_BAR_MESSAGE] = + signals[FOLDER_BAR_MESSAGE] = g_signal_new ("folder_bar_message", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, folder_bar_message), + G_STRUCT_OFFSET (EAddressbookModelClass, folder_bar_message), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); - eab_model_signals [CONTACT_ADDED] = + signals[CONTACT_ADDED] = g_signal_new ("contact_added", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, contact_added), + G_STRUCT_OFFSET (EAddressbookModelClass, contact_added), NULL, NULL, e_marshal_NONE__INT_INT, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT); - eab_model_signals [CONTACTS_REMOVED] = + signals[CONTACTS_REMOVED] = g_signal_new ("contacts_removed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, contacts_removed), + G_STRUCT_OFFSET (EAddressbookModelClass, contacts_removed), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); - eab_model_signals [CONTACT_CHANGED] = + signals[CONTACT_CHANGED] = g_signal_new ("contact_changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, contact_changed), + G_STRUCT_OFFSET (EAddressbookModelClass, contact_changed), NULL, NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, G_TYPE_INT); + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, E_TYPE_CONTACT); - eab_model_signals [MODEL_CHANGED] = + signals[MODEL_CHANGED] = g_signal_new ("model_changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, model_changed), + G_STRUCT_OFFSET (EAddressbookModelClass, model_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - eab_model_signals [STOP_STATE_CHANGED] = + signals[STOP_STATE_CHANGED] = g_signal_new ("stop_state_changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, stop_state_changed), + G_STRUCT_OFFSET (EAddressbookModelClass, stop_state_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - eab_model_signals [BACKEND_DIED] = + signals[BACKEND_DIED] = g_signal_new ("backend_died", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, backend_died), + G_STRUCT_OFFSET (EAddressbookModelClass, backend_died), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void -eab_model_init (GObject *object) -{ - EABModel *model = EAB_MODEL(object); - model->book = NULL; - model->query = e_book_query_any_field_contains (""); - model->book_view = NULL; - model->create_contact_id = 0; - model->remove_contact_id = 0; - model->modify_contact_id = 0; - model->status_message_id = 0; - model->writable_status_id = 0; - model->backend_died_id = 0; - model->sequence_complete_id = 0; - model->data = NULL; - model->data_count = 0; - model->allocated_count = 0; - model->search_in_progress = FALSE; - model->editable = FALSE; - model->editable_set = FALSE; - model->first_get_view = TRUE; +addressbook_model_init (EAddressbookModel *model) +{ + model->priv = E_ADDRESSBOOK_MODEL_GET_PRIVATE (model); + + model->priv->contacts = g_ptr_array_new (); + model->priv->first_get_view = TRUE; } -static void -book_view_loaded (EBook *book, EBookStatus status, EBookView *book_view, gpointer closure) +GType +e_addressbook_model_get_type (void) { - EABModel *model = closure; + static GType type = 0; - if (status != E_BOOK_ERROR_OK) { - eab_error_dialog (_("Error getting book view"), status); - return; + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EAddressbookModelClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) addressbook_model_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EAddressbookModel), + 0, /* n_preallocs */ + (GInstanceInitFunc) addressbook_model_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_OBJECT, "EAddressbookModel", &type_info, 0); } - remove_book_view (model); - free_data (model); + return type; +} - model->book_view = book_view; - if (model->book_view) - g_object_ref (model->book_view); - model->create_contact_id = g_signal_connect(model->book_view, - "contacts_added", - G_CALLBACK (create_contact), - model); - model->remove_contact_id = g_signal_connect(model->book_view, - "contacts_removed", - G_CALLBACK (remove_contact), - model); - model->modify_contact_id = g_signal_connect(model->book_view, - "contacts_changed", - G_CALLBACK(modify_contact), - model); - model->status_message_id = g_signal_connect(model->book_view, - "status_message", - G_CALLBACK(status_message), - model); - model->sequence_complete_id = g_signal_connect(model->book_view, - "sequence_complete", - G_CALLBACK(sequence_complete), - model); - - model->search_in_progress = TRUE; - g_signal_emit (model, - eab_model_signals [MODEL_CHANGED], 0); - g_signal_emit (model, - eab_model_signals [SEARCH_STARTED], 0); - g_signal_emit (model, - eab_model_signals [STOP_STATE_CHANGED], 0); - - e_book_view_start (model->book_view); +EAddressbookModel* +e_addressbook_model_new (void) +{ + return g_object_new (E_TYPE_ADDRESSBOOK_MODEL, NULL); } -static void -get_view (EABModel *model) +EContact * +e_addressbook_model_get_contact (EAddressbookModel *model, + gint row) { - /* Should this be checked somehow? */ - gboolean success; + GPtrArray *array; - if (model->book && model->query) { - ESource *source; - const char *limit_str; - int limit = -1; + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL); - source = e_book_get_source (model->book); + array = model->priv->contacts; - limit_str = e_source_get_property (source, "limit"); - if (limit_str && *limit_str) - limit = atoi (limit_str); + if (0 <= row && row < array->len) + return e_contact_duplicate (array->pdata[row]); - remove_book_view(model); + return NULL; +} - if (model->first_get_view) { - model->first_get_view = FALSE; +void +e_addressbook_model_stop (EAddressbookModel *model) +{ + const gchar *message; - if (e_book_check_static_capability (model->book, "do-initial-query")) { - success = e_book_async_get_book_view (model->book, model->query, NULL, limit, book_view_loaded, model); - } else { - free_data (model); + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); - g_signal_emit (model, - eab_model_signals [MODEL_CHANGED], 0); - g_signal_emit (model, - eab_model_signals [STOP_STATE_CHANGED], 0); - return; - } - } - else - success = e_book_async_get_book_view (model->book, model->query, NULL, limit, book_view_loaded, model); + remove_book_view (model); - } + message = _("Search Interrupted"); + g_signal_emit (model, signals[STOP_STATE_CHANGED], 0); + g_signal_emit (model, signals[STATUS_MESSAGE], 0, message); } -static gboolean -get_view_idle (EABModel *model) +gboolean +e_addressbook_model_can_stop (EAddressbookModel *model) { - model->book_view_idle_id = 0; - get_view (model); - g_object_unref (model); - return FALSE; -} + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), FALSE); + return model->priv->search_in_progress; +} -EContact * -eab_model_get_contact(EABModel *model, - int row) +void +e_addressbook_model_force_folder_bar_message (EAddressbookModel *model) { - if (model->data && 0 <= row && row < model->data_count) { - return e_contact_duplicate (model->data[row]); - } - return NULL; + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); + + update_folder_bar_message (model); } -static void -eab_model_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +gint +e_addressbook_model_contact_count (EAddressbookModel *model) { - EABModel *model; - gboolean need_get_book_view = FALSE; + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), 0); - model = EAB_MODEL (object); + return model->priv->contacts->len; +} - switch (prop_id){ - case PROP_BOOK: - if (model->book) { - if (model->writable_status_id) - g_signal_handler_disconnect (model->book, - model->writable_status_id); - model->writable_status_id = 0; +EContact * +e_addressbook_model_contact_at (EAddressbookModel *model, + gint index) +{ + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL); - if (model->backend_died_id) - g_signal_handler_disconnect (model->book, - model->backend_died_id); - model->backend_died_id = 0; + return model->priv->contacts->pdata[index]; +} - g_object_unref (model->book); - } - model->book = E_BOOK(g_value_get_object (value)); - if (model->book) { - model->writable_status_id = - g_signal_connect (model->book, - "writable_status", - G_CALLBACK (writable_status), model); - model->backend_died_id = - g_signal_connect (model->book, - "backend_died", - G_CALLBACK (backend_died), model); - - if (!model->editable_set) { - model->editable = e_book_is_writable (model->book); +gint +e_addressbook_model_find (EAddressbookModel *model, + EContact *contact) +{ + GPtrArray *array; + gint ii; - g_signal_emit (model, - eab_model_signals [WRITABLE_STATUS], 0, - model->editable); - } + /* XXX This searches for a particular EContact instance, + * as opposed to an equivalent but possibly different + * EContact instance. Might have to revise this in + * the future. */ - model->first_get_view = TRUE; - g_object_ref (model->book); - need_get_book_view = TRUE; - } - break; - case PROP_QUERY: - if (model->query) - e_book_query_unref (model->query); - model->query = e_book_query_from_string (g_value_get_string (value)); - need_get_book_view = TRUE; - break; - case PROP_EDITABLE: - model->editable = g_value_get_boolean (value); - model->editable_set = TRUE; - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), -1); + g_return_val_if_fail (E_IS_CONTACT (contact), -1); - if (need_get_book_view) { - if (!model->book_view_idle_id) { - g_object_ref (model); - model->book_view_idle_id = g_idle_add ((GSourceFunc)get_view_idle, model); - } + array = model->priv->contacts; + for (ii = 0; ii < array->len; ii++) { + EContact *candidate = array->pdata[ii]; + + if (contact == candidate) + return ii; } + return -1; } -static void -eab_model_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +EBook * +e_addressbook_model_get_book (EAddressbookModel *model) { - EABModel *eab_model; - - eab_model = EAB_MODEL (object); + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL); - switch (prop_id) { - case PROP_BOOK: - g_value_set_object (value, eab_model->book); - break; - case PROP_QUERY: { - char *query_string = e_book_query_to_string (eab_model->query); - g_value_set_string (value, query_string); - break; - } - case PROP_EDITABLE: - g_value_set_boolean (value, eab_model->editable); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + return model->priv->book; } -GType -eab_model_get_type (void) +void +e_addressbook_model_set_book (EAddressbookModel *model, + EBook *book) { - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (EABModelClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) eab_model_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EABModel), - 0, /* n_preallocs */ - (GInstanceInitFunc) eab_model_init, - }; - - type = g_type_register_static (PARENT_TYPE, "EABModel", &info, 0); + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); + g_return_if_fail (E_IS_BOOK (book)); + + if (model->priv->book != NULL) { + if (model->priv->writable_status_id != 0) + g_signal_handler_disconnect ( + model->priv->book, + model->priv->writable_status_id); + model->priv->writable_status_id = 0; + + if (model->priv->backend_died_id != 0) + g_signal_handler_disconnect ( + model->priv->book, + model->priv->backend_died_id); + model->priv->backend_died_id = 0; + + g_object_unref (model->priv->book); } - return type; -} + model->priv->book = g_object_ref (book); + model->priv->first_get_view = TRUE; -EABModel* -eab_model_new (void) -{ - EABModel *et; + model->priv->writable_status_id = g_signal_connect ( + book, "writable-status", + G_CALLBACK (writable_status), model); - et = g_object_new (EAB_TYPE_MODEL, NULL); + model->priv->backend_died_id = g_signal_connect ( + book, "backend-died", + G_CALLBACK (backend_died), model); - return et; -} + if (!model->priv->editable_set) { + model->priv->editable = e_book_is_writable (book); + g_signal_emit ( + model, signals[WRITABLE_STATUS], 0, + model->priv->editable); + } -void eab_model_stop (EABModel *model) -{ - remove_book_view(model); - g_signal_emit (model, - eab_model_signals [STOP_STATE_CHANGED], 0); - g_signal_emit (model, - eab_model_signals [STATUS_MESSAGE], 0, - "Search Interrupted."); + if (model->priv->book_view_idle_id == 0) + model->priv->book_view_idle_id = g_idle_add ( + (GSourceFunc) addressbook_model_idle_cb, + g_object_ref (model)); + + g_object_notify (G_OBJECT (model), "book"); } gboolean -eab_model_can_stop (EABModel *model) +e_addressbook_model_get_editable (EAddressbookModel *model) { - return model->search_in_progress; + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), FALSE); + + return model->priv->editable; } void -eab_model_force_folder_bar_message (EABModel *model) +e_addressbook_model_set_editable (EAddressbookModel *model, + gboolean editable) { - update_folder_bar_message (model); -} + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); -int -eab_model_contact_count (EABModel *model) -{ - return model->data_count; -} + model->priv->editable = editable; + model->priv->editable_set = TRUE; -const EContact * -eab_model_contact_at (EABModel *model, int index) -{ - return model->data[index]; + g_object_notify (G_OBJECT (model), "editable"); } -gboolean -eab_model_editable (EABModel *model) +gchar * +e_addressbook_model_get_query (EAddressbookModel *model) { - return model->editable; + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL); + + return e_book_query_to_string (model->priv->query); } -EBook * -eab_model_get_ebook (EABModel *model) +void +e_addressbook_model_set_query (EAddressbookModel *model, + const gchar *query) { - return model->book; + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); + + if (model->priv->query != NULL) + e_book_query_unref (model->priv->query); + + if (query == NULL) + model->priv->query = e_book_query_any_field_contains (""); + else + model->priv->query = e_book_query_from_string (query); + + if (model->priv->book_view_idle_id == 0) + model->priv->book_view_idle_id = g_idle_add ( + (GSourceFunc) addressbook_model_idle_cb, + g_object_ref (model)); + + g_object_notify (G_OBJECT (model), "query"); } diff --git a/addressbook/gui/widgets/e-addressbook-model.h b/addressbook/gui/widgets/e-addressbook-model.h index 6558d94812..1a7be828f6 100644 --- a/addressbook/gui/widgets/e-addressbook-model.h +++ b/addressbook/gui/widgets/e-addressbook-model.h @@ -18,84 +18,99 @@ * */ -#ifndef _EAB_MODEL_H_ -#define _EAB_MODEL_H_ +#ifndef E_ADDRESSBOOK_MODEL_H +#define E_ADDRESSBOOK_MODEL_H -#include <glib.h> -#include <glib-object.h> #include <libebook/e-book.h> +#include <libebook/e-book-query.h> #include <libebook/e-book-view.h> -#define EAB_TYPE_MODEL (eab_model_get_type ()) -#define EAB_MODEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EAB_TYPE_MODEL, EABModel)) -#define EAB_MODEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EAB_TYPE_MODEL, EABModelClass)) -#define E_IS_ADDRESSBOOK_MODEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EAB_TYPE_MODEL)) -#define E_IS_ADDRESSBOOK_MODEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EAB_TYPE_MODEL)) - -typedef struct _EABModel EABModel; -typedef struct _EABModelClass EABModelClass; - -struct _EABModel { +/* Standard GObject macros */ +#define E_TYPE_ADDRESSBOOK_MODEL \ + (e_addressbook_model_get_type ()) +#define E_ADDRESSBOOK_MODEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ADDRESSBOOK_MODEL, EAddressbookModel)) +#define E_ADDRESSBOOK_MODEL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ADDRESSBOOK_MODEL, EAddressbookModelClass)) +#define E_IS_ADDRESSBOOK_MODEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_MODEL)) +#define E_IS_ADDRESSBOOK_MODEL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ADDRESSBOOK_MODEL)) +#define E_ADDRESSBOOK_MODEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ADDRESSBOOK_MODEL)) + +G_BEGIN_DECLS + +typedef struct _EAddressbookModel EAddressbookModel; +typedef struct _EAddressbookModelClass EAddressbookModelClass; +typedef struct _EAddressbookModelPrivate EAddressbookModelPrivate; + +struct _EAddressbookModel { GObject parent; - - /* item specific fields */ - EBook *book; - EBookQuery *query; - EBookView *book_view; - - int book_view_idle_id; - - EContact **data; - int data_count; - int allocated_count; - - int create_contact_id, remove_contact_id, modify_contact_id; - int status_message_id, writable_status_id, sequence_complete_id; - int backend_died_id; - - guint search_in_progress : 1; - guint editable : 1; - guint editable_set : 1; - guint first_get_view : 1; + EAddressbookModelPrivate *priv; }; -struct _EABModelClass { +struct _EAddressbookModelClass { GObjectClass parent_class; - /* - * Signals - */ - void (*writable_status) (EABModel *model, gboolean writable); - void (*search_started) (EABModel *model); - void (*search_result) (EABModel *model, EBookViewStatus status); - void (*status_message) (EABModel *model, const gchar *message); - void (*folder_bar_message) (EABModel *model, const gchar *message); - void (*contact_added) (EABModel *model, gint index, gint count); - void (*contacts_removed) (EABModel *model, gpointer id_list); - void (*contact_changed) (EABModel *model, gint index); - void (*model_changed) (EABModel *model); - void (*stop_state_changed) (EABModel *model); - void (*backend_died) (EABModel *model); + /* Signals */ + void (*writable_status) (EAddressbookModel *model, + gboolean writable); + void (*search_started) (EAddressbookModel *model); + void (*search_result) (EAddressbookModel *model, + EBookViewStatus status); + void (*status_message) (EAddressbookModel *model, + const gchar *message); + void (*folder_bar_message) (EAddressbookModel *model, + const gchar *message); + void (*contact_added) (EAddressbookModel *model, + gint index, + gint count); + void (*contacts_removed) (EAddressbookModel *model, + gpointer id_list); + void (*contact_changed) (EAddressbookModel *model, + EContact *contact); + void (*model_changed) (EAddressbookModel *model); + void (*stop_state_changed) (EAddressbookModel *model); + void (*backend_died) (EAddressbookModel *model); }; - -GType eab_model_get_type (void); -EABModel *eab_model_new (void); +GType e_addressbook_model_get_type (void); +EAddressbookModel * + e_addressbook_model_new (void); /* Returns object with ref count of 1. */ -EContact *eab_model_get_contact (EABModel *model, - int row); -EBook *eab_model_get_ebook (EABModel *model); - -void eab_model_stop (EABModel *model); -gboolean eab_model_can_stop (EABModel *model); - -void eab_model_force_folder_bar_message (EABModel *model); - -int eab_model_contact_count (EABModel *model); -const EContact *eab_model_contact_at (EABModel *model, - int index); -gboolean eab_model_editable (EABModel *model); - -#endif /* _EAB_MODEL_H_ */ +EContact * e_addressbook_model_get_contact (EAddressbookModel *model, + gint row); + +void e_addressbook_model_stop (EAddressbookModel *model); +gboolean e_addressbook_model_can_stop (EAddressbookModel *model); + +void e_addressbook_model_force_folder_bar_message + (EAddressbookModel *model); + +gint e_addressbook_model_contact_count + (EAddressbookModel *model); +EContact * e_addressbook_model_contact_at (EAddressbookModel *model, + gint index); +gint e_addressbook_model_find (EAddressbookModel *model, + EContact *contact); +EBook * e_addressbook_model_get_book (EAddressbookModel *model); +void e_addressbook_model_set_book (EAddressbookModel *model, + EBook *book); +gboolean e_addressbook_model_get_editable(EAddressbookModel *model); +void e_addressbook_model_set_editable(EAddressbookModel *model, + gboolean editable); +gchar * e_addressbook_model_get_query (EAddressbookModel *model); +void e_addressbook_model_set_query (EAddressbookModel *model, + const gchar *query); + +G_END_DECLS + +#endif /* E_ADDRESSBOOK_MODEL_H */ diff --git a/addressbook/gui/widgets/e-addressbook-reflow-adapter.c b/addressbook/gui/widgets/e-addressbook-reflow-adapter.c index 1f2b1aad7a..2a2f1a2d87 100644 --- a/addressbook/gui/widgets/e-addressbook-reflow-adapter.c +++ b/addressbook/gui/widgets/e-addressbook-reflow-adapter.c @@ -20,19 +20,18 @@ #include <string.h> #include <glib/gi18n.h> -#include "e-util/e-util.h" #include "e-addressbook-reflow-adapter.h" #include "e-addressbook-model.h" -#include "e-addressbook-view.h" #include "eab-gui-util.h" #include "e-minicard.h" +#include <e-util/e-util.h> #include <misc/e-gui-utils.h> #include "addressbook/printing/e-contact-print.h" struct _EAddressbookReflowAdapterPrivate { - EABModel *model; + EAddressbookModel *model; gboolean loading; @@ -55,10 +54,11 @@ enum { enum { DRAG_BEGIN, + OPEN_CONTACT, LAST_SIGNAL }; -static guint e_addressbook_reflow_adapter_signals [LAST_SIGNAL] = {0, }; +static guint signals [LAST_SIGNAL] = {0, }; static void unlink_model(EAddressbookReflowAdapter *adapter) @@ -130,7 +130,7 @@ addressbook_count (EReflowModel *erm) EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(erm); EAddressbookReflowAdapterPrivate *priv = adapter->priv; - return eab_model_contact_count (priv->model); + return e_addressbook_model_contact_count (priv->model); } /* This function returns the height of the minicontact in question */ @@ -142,7 +142,7 @@ addressbook_height (EReflowModel *erm, int i, GnomeCanvasGroup *parent) EContactField field; int count = 0; char *string; - EContact *contact = (EContact*)eab_model_contact_at (priv->model, i); + EContact *contact = (EContact*)e_addressbook_model_contact_at (priv->model, i); PangoLayout *layout = gtk_widget_create_pango_layout (GTK_WIDGET (GNOME_CANVAS_ITEM (parent)->canvas), ""); int height; @@ -191,8 +191,8 @@ addressbook_compare (EReflowModel *erm, int n1, int n2) return n1-n2; } else { - contact1 = (EContact*)eab_model_contact_at (priv->model, n1); - contact2 = (EContact*)eab_model_contact_at (priv->model, n2); + contact1 = (EContact*)e_addressbook_model_contact_at (priv->model, n1); + contact2 = (EContact*)e_addressbook_model_contact_at (priv->model, n2); if (contact1 && contact2) { const char *file_as1, *file_as2; @@ -228,12 +228,20 @@ adapter_drag_begin (EMinicard *card, GdkEvent *event, EAddressbookReflowAdapter gint ret_val = 0; g_signal_emit (adapter, - e_addressbook_reflow_adapter_signals[DRAG_BEGIN], 0, + signals[DRAG_BEGIN], 0, event, &ret_val); return ret_val; } +static void +adapter_open_contact (EMinicard *card, + EContact *contact, + EAddressbookReflowAdapter *adapter) +{ + g_signal_emit (adapter, signals[OPEN_CONTACT], 0, contact); +} + static GnomeCanvasItem * addressbook_incarnate (EReflowModel *erm, int i, GnomeCanvasGroup *parent) { @@ -243,8 +251,8 @@ addressbook_incarnate (EReflowModel *erm, int i, GnomeCanvasGroup *parent) item = gnome_canvas_item_new(parent, e_minicard_get_type(), - "contact", eab_model_contact_at (priv->model, i), - "editable", eab_model_editable (priv->model), + "contact", e_addressbook_model_contact_at (priv->model, i), + "editable", e_addressbook_model_get_editable (priv->model), NULL); #if 0 @@ -253,7 +261,10 @@ addressbook_incarnate (EReflowModel *erm, int i, GnomeCanvasGroup *parent) #endif g_signal_connect (item, "drag_begin", - G_CALLBACK(adapter_drag_begin), adapter); + G_CALLBACK (adapter_drag_begin), adapter); + + g_signal_connect (item, "open-contact", + G_CALLBACK (adapter_open_contact), adapter); return item; } @@ -265,12 +276,12 @@ addressbook_reincarnate (EReflowModel *erm, int i, GnomeCanvasItem *item) EAddressbookReflowAdapterPrivate *priv = adapter->priv; gnome_canvas_item_set(item, - "contact", eab_model_contact_at (priv->model, i), + "contact", e_addressbook_model_contact_at (priv->model, i), NULL); } static void -create_contact (EABModel *model, +create_contact (EAddressbookModel *model, gint index, gint count, EAddressbookReflowAdapter *adapter) { @@ -280,7 +291,7 @@ create_contact (EABModel *model, } static void -remove_contacts (EABModel *model, +remove_contacts (EAddressbookModel *model, gpointer data, EAddressbookReflowAdapter *adapter) { @@ -295,7 +306,7 @@ remove_contacts (EABModel *model, } static void -modify_contact (EABModel *model, +modify_contact (EAddressbookModel *model, gint index, EAddressbookReflowAdapter *adapter) { @@ -303,14 +314,14 @@ modify_contact (EABModel *model, } static void -model_changed (EABModel *model, +model_changed (EAddressbookModel *model, EAddressbookReflowAdapter *adapter) { e_reflow_model_changed (E_REFLOW_MODEL (adapter)); } static void -search_started (EABModel *model, +search_started (EAddressbookModel *model, EAddressbookReflowAdapter *adapter) { EAddressbookReflowAdapterPrivate *priv = adapter->priv; @@ -319,7 +330,7 @@ search_started (EABModel *model, } static void -search_result (EABModel *model, +search_result (EAddressbookModel *model, EBookViewStatus status, EAddressbookReflowAdapter *adapter) { @@ -425,10 +436,10 @@ e_addressbook_reflow_adapter_class_init (GObjectClass *object_class) g_param_spec_object ("model", _("Model"), /*_( */"XXX blurb" /*)*/, - EAB_TYPE_MODEL, + E_TYPE_ADDRESSBOOK_MODEL, G_PARAM_READABLE)); - e_addressbook_reflow_adapter_signals [DRAG_BEGIN] = + signals [DRAG_BEGIN] = g_signal_new ("drag_begin", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, @@ -437,6 +448,16 @@ e_addressbook_reflow_adapter_class_init (GObjectClass *object_class) e_marshal_INT__POINTER, G_TYPE_INT, 1, G_TYPE_POINTER); + signals [OPEN_CONTACT] = + g_signal_new ("open-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookReflowAdapterClass, open_contact), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CONTACT); + model_class->set_width = addressbook_set_width; model_class->count = addressbook_count; model_class->height = addressbook_height; @@ -488,7 +509,7 @@ e_addressbook_reflow_adapter_get_type (void) void e_addressbook_reflow_adapter_construct (EAddressbookReflowAdapter *adapter, - EABModel *model) + EAddressbookModel *model) { EAddressbookReflowAdapterPrivate *priv = adapter->priv; @@ -522,7 +543,7 @@ e_addressbook_reflow_adapter_construct (EAddressbookReflowAdapter *adapter, } EReflowModel * -e_addressbook_reflow_adapter_new (EABModel *model) +e_addressbook_reflow_adapter_new (EAddressbookModel *model) { EAddressbookReflowAdapter *et; @@ -540,5 +561,5 @@ e_addressbook_reflow_adapter_get_contact (EAddressbookReflowAdapter *adapter, { EAddressbookReflowAdapterPrivate *priv = adapter->priv; - return eab_model_get_contact (priv->model, index); + return e_addressbook_model_get_contact (priv->model, index); } diff --git a/addressbook/gui/widgets/e-addressbook-reflow-adapter.h b/addressbook/gui/widgets/e-addressbook-reflow-adapter.h index fd7842684f..5032f3e2d0 100644 --- a/addressbook/gui/widgets/e-addressbook-reflow-adapter.h +++ b/addressbook/gui/widgets/e-addressbook-reflow-adapter.h @@ -48,14 +48,17 @@ struct _EAddressbookReflowAdapterClass { /* * Signals */ - gint (* drag_begin) (EAddressbookReflowAdapter *adapter, GdkEvent *event); + gint (*drag_begin) (EAddressbookReflowAdapter *adapter, + GdkEvent *event); + void (*open_contact) (EAddressbookReflowAdapter *adapter, + EContact *contact); }; GType e_addressbook_reflow_adapter_get_type (void); void e_addressbook_reflow_adapter_construct (EAddressbookReflowAdapter *adapter, - EABModel *model); -EReflowModel *e_addressbook_reflow_adapter_new (EABModel *model); + EAddressbookModel *model); +EReflowModel *e_addressbook_reflow_adapter_new (EAddressbookModel *model); /* Returns object with ref count of 1. */ EContact *e_addressbook_reflow_adapter_get_contact (EAddressbookReflowAdapter *adapter, diff --git a/addressbook/gui/widgets/e-addressbook-selector.c b/addressbook/gui/widgets/e-addressbook-selector.c new file mode 100644 index 0000000000..e7bec99ba2 --- /dev/null +++ b/addressbook/gui/widgets/e-addressbook-selector.c @@ -0,0 +1,443 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-addressbook-selector.c + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU 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 General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "e-addressbook-selector.h" + +#include <eab-book-util.h> +#include <eab-contact-merging.h> + +#define E_ADDRESSBOOK_SELECTOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelectorPrivate)) + +#define PRIMARY_ADDRESSBOOK_KEY \ + "/apps/evolution/addressbook/display/primary_addressbook" + +typedef struct _MergeContext MergeContext; + +struct _EAddressbookSelectorPrivate { + EAddressbookView *current_view; +}; + +struct _MergeContext { + EBook *source_book; + EBook *target_book; + + EContact *current_contact; + GList *remaining_contacts; + guint pending_removals; + + gint remove_from_source : 1; + gint copy_done : 1; +}; + +enum { + PROP_0, + PROP_CURRENT_VIEW +}; + +enum { + DND_TARGET_TYPE_VCARD, + DND_TARGET_TYPE_SOURCE_VCARD +}; + +static GtkTargetEntry drag_types[] = { + { "text/x-vcard", 0, DND_TARGET_TYPE_VCARD }, + { "text/x-source-vcard", 0, DND_TARGET_TYPE_SOURCE_VCARD } +}; + +static gpointer parent_class; + +static void +merge_context_next (MergeContext *merge_context) +{ + GList *list; + + list = merge_context->remaining_contacts; + merge_context->current_contact = list->data; + list = g_list_delete_link (list, list); + merge_context->remaining_contacts = list; +} + +static MergeContext * +merge_context_new (EBook *source_book, + EBook *target_book, + GList *contact_list) +{ + MergeContext *merge_context; + + merge_context = g_slice_new0 (MergeContext); + merge_context->source_book = source_book; + merge_context->target_book = target_book; + merge_context->remaining_contacts = contact_list; + merge_context_next (merge_context); + + return merge_context; +} + +static void +merge_context_free (MergeContext *merge_context) +{ + if (merge_context->source_book != NULL) + g_object_unref (merge_context->source_book); + + if (merge_context->target_book != NULL) + g_object_unref (merge_context->target_book); + + g_slice_free (MergeContext, merge_context); +} + +static void +addressbook_selector_removed_cb (EBook *book, + EBookStatus status, + MergeContext *merge_context) +{ + merge_context->pending_removals--; + + if (merge_context->remaining_contacts != NULL) + return; + + if (merge_context->pending_removals > 0) + return; + + merge_context_free (merge_context); +} + +static void +addressbook_selector_merge_next_cb (EBook *book, + EBookStatus status, + const gchar *id, + MergeContext *merge_context) +{ + if (merge_context->remove_from_source && status == E_BOOK_ERROR_OK) { + /* Remove previous contact from source. */ + e_book_async_remove_contact ( + merge_context->source_book, + merge_context->current_contact, + (EBookCallback) addressbook_selector_removed_cb, + merge_context); + merge_context->pending_removals++; + } + + g_object_unref (merge_context->current_contact); + + if (merge_context->remaining_contacts != NULL) { + merge_context_next (merge_context); + eab_merging_book_add_contact ( + merge_context->target_book, + merge_context->current_contact, + (EBookIdCallback) addressbook_selector_merge_next_cb, + merge_context); + + } else if (merge_context->pending_removals == 0) + merge_context_free (merge_context); +} + +static void +addressbook_selector_load_primary_source (ESourceSelector *selector) +{ + GConfClient *client; + ESourceList *source_list; + ESource *source = NULL; + const gchar *key; + gchar *uid; + + /* XXX If ESourceSelector had a "primary-uid" property, + * we could just bind the GConf key to it. */ + + source_list = e_source_selector_get_source_list (selector); + + client = gconf_client_get_default (); + key = PRIMARY_ADDRESSBOOK_KEY; + uid = gconf_client_get_string (client, key, NULL); + g_object_unref (client); + + if (uid != NULL) { + source = e_source_list_peek_source_by_uid (source_list, uid); + g_free (uid); + } else { + GSList *groups; + + /* Dig up the first source in the source list. + * XXX libedataserver should provide API for this. */ + groups = e_source_list_peek_groups (source_list); + while (groups != NULL) { + ESourceGroup *source_group = groups->data; + GSList *sources; + + sources = e_source_group_peek_sources (source_group); + if (sources != NULL) { + source = sources->data; + break; + } + + groups = g_slist_next (groups); + } + } + + if (source != NULL) + e_source_selector_set_primary_selection (selector, source); +} + +static void +addressbook_selector_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CURRENT_VIEW: + e_addressbook_selector_set_current_view ( + E_ADDRESSBOOK_SELECTOR (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +addressbook_selector_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CURRENT_VIEW: + g_value_set_object ( + value, + e_addressbook_selector_get_current_view ( + E_ADDRESSBOOK_SELECTOR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +addressbook_selector_dispose (GObject *object) +{ + EAddressbookSelectorPrivate *priv; + + priv = E_ADDRESSBOOK_SELECTOR_GET_PRIVATE (object); + + if (priv->current_view != NULL) { + g_object_unref (priv->current_view); + priv->current_view = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +addressbook_selector_constructed (GObject *object) +{ + ESourceSelector *selector; + + selector = E_SOURCE_SELECTOR (object); + addressbook_selector_load_primary_source (selector); +} + +static void +addressbook_selector_primary_selection_changed (ESourceSelector *selector) +{ + ESource *source; + GConfClient *client; + const gchar *key; + const gchar *string; + + /* XXX If ESourceSelector had a "primary-uid" property, + * we could just bind the GConf key to it. */ + + source = e_source_selector_peek_primary_selection (selector); + if (source == NULL) + return; + + client = gconf_client_get_default (); + key = PRIMARY_ADDRESSBOOK_KEY; + string = e_source_peek_uid (source); + gconf_client_set_string (client, key, string, NULL); + g_object_unref (client); +} + +static gboolean +addressbook_selector_data_dropped (ESourceSelector *selector, + GtkSelectionData *selection_data, + ESource *destination, + GdkDragAction action, + guint info) +{ + EAddressbookSelectorPrivate *priv; + MergeContext *merge_context; + EAddressbookModel *model; + EBook *source_book; + EBook *target_book; + GList *list; + const gchar *string; + gboolean remove_from_source; + + priv = E_ADDRESSBOOK_SELECTOR_GET_PRIVATE (selector); + g_return_val_if_fail (priv->current_view != NULL, FALSE); + + string = (const gchar *) selection_data->data; + remove_from_source = (action == GDK_ACTION_MOVE); + + target_book = e_book_new (destination, NULL); + if (target_book == NULL) + return FALSE; + + e_book_open (target_book, FALSE, NULL); + + /* XXX Function assumes both out arguments are provided. All we + * care about is the contact list; source_book will be NULL. */ + eab_book_and_contact_list_from_string (string, &source_book, &list); + if (list == NULL) + return FALSE; + + model = e_addressbook_view_get_model (priv->current_view); + source_book = e_addressbook_model_get_book (model); + g_return_val_if_fail (E_IS_BOOK (source_book), FALSE); + + merge_context = merge_context_new (source_book, target_book, list); + merge_context->remove_from_source = remove_from_source; + + eab_merging_book_add_contact ( + target_book, merge_context->current_contact, + (EBookIdCallback) addressbook_selector_merge_next_cb, + merge_context); + + return TRUE; +} + +static void +addressbook_selector_class_init (EAddressbookSelectorClass *class) +{ + GObjectClass *object_class; + ESourceSelectorClass *selector_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EAddressbookSelectorPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = addressbook_selector_set_property; + object_class->get_property = addressbook_selector_get_property; + object_class->dispose = addressbook_selector_dispose; + object_class->constructed = addressbook_selector_constructed; + + selector_class = E_SOURCE_SELECTOR_CLASS (class); + selector_class->primary_selection_changed = + addressbook_selector_primary_selection_changed; + selector_class->data_dropped = addressbook_selector_data_dropped; + + g_object_class_install_property ( + object_class, + PROP_CURRENT_VIEW, + g_param_spec_object ( + "current-view", + NULL, + NULL, + E_TYPE_ADDRESSBOOK_VIEW, + G_PARAM_READWRITE)); +} + +static void +addressbook_selector_init (EAddressbookSelector *selector) +{ + selector->priv = E_ADDRESSBOOK_SELECTOR_GET_PRIVATE (selector); + + gtk_drag_dest_set ( + GTK_WIDGET (selector), GTK_DEST_DEFAULT_ALL, + drag_types, G_N_ELEMENTS (drag_types), + GDK_ACTION_COPY | GDK_ACTION_MOVE); +} + +GType +e_addressbook_selector_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + const GTypeInfo type_info = { + sizeof (EAddressbookSelectorClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) addressbook_selector_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EAddressbookSelector), + 0, /* n_preallocs */ + (GInstanceInitFunc) addressbook_selector_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + E_TYPE_SOURCE_SELECTOR, "EAddressbookSelector", + &type_info, 0); + } + + return type; +} + +GtkWidget * +e_addressbook_selector_new (ESourceList *source_list) +{ + g_return_val_if_fail (E_IS_SOURCE_LIST (source_list), NULL); + + return g_object_new ( + E_TYPE_ADDRESSBOOK_SELECTOR, + "source-list", source_list, NULL); +} + +EAddressbookView * +e_addressbook_selector_get_current_view (EAddressbookSelector *selector) +{ + g_return_val_if_fail (E_IS_ADDRESSBOOK_SELECTOR (selector), NULL); + + return selector->priv->current_view; +} + +void +e_addressbook_selector_set_current_view (EAddressbookSelector *selector, + EAddressbookView *current_view) +{ + /* XXX This is only needed for moving contacts via drag-and-drop. + * The selection data doesn't include the source of the data + * (the model for the currently selected address book view), + * so we have to rely on it being provided to us. I would + * be happy to see this function go away. */ + + g_return_if_fail (E_IS_ADDRESSBOOK_SELECTOR (selector)); + + if (current_view != NULL) + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (current_view)); + + if (selector->priv->current_view != NULL) { + g_object_unref (selector->priv->current_view); + selector->priv->current_view = NULL; + } + + if (current_view != NULL) + g_object_ref (current_view); + + selector->priv->current_view = current_view; + + g_object_notify (G_OBJECT (selector), "current-view"); +} diff --git a/addressbook/gui/widgets/e-addressbook-selector.h b/addressbook/gui/widgets/e-addressbook-selector.h new file mode 100644 index 0000000000..c0102cb3b8 --- /dev/null +++ b/addressbook/gui/widgets/e-addressbook-selector.h @@ -0,0 +1,73 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-addressbook-selector.h + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU 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 General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef E_ADDRESSBOOK_SELECTOR_H +#define E_ADDRESSBOOK_SELECTOR_H + +#include <libedataserver/e-source-list.h> +#include <libedataserverui/e-source-selector.h> +#include "e-addressbook-view.h" + +/* Standard GObject macros */ +#define E_TYPE_ADDRESSBOOK_SELECTOR \ + (e_addressbook_selector_get_type ()) +#define E_ADDRESSBOOK_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelector)) +#define E_ADDRESSBOOK_SELECTOR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelectorClass)) +#define E_IS_ADDRESSBOOK_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR)) +#define E_IS_ADDRESSBOOK_SELECTOR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ADDRESSBOOK_SELECTOR)) +#define E_ADDRESSBOOK_SELECTOR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelectorClass)) + +G_BEGIN_DECLS + +typedef struct _EAddressbookSelector EAddressbookSelector; +typedef struct _EAddressbookSelectorClass EAddressbookSelectorClass; +typedef struct _EAddressbookSelectorPrivate EAddressbookSelectorPrivate; + +struct _EAddressbookSelector { + ESourceSelector parent; + EAddressbookSelectorPrivate *priv; +}; + +struct _EAddressbookSelectorClass { + ESourceSelectorClass parent_class; +}; + +GType e_addressbook_selector_get_type (void); +GtkWidget * e_addressbook_selector_new (ESourceList *source_list); +EAddressbookView * + e_addressbook_selector_get_current_view + (EAddressbookSelector *selector); +void e_addressbook_selector_set_current_view + (EAddressbookSelector *selector, + EAddressbookView *current_view); + +G_END_DECLS + +#endif /* E_ADDRESSBOOK_SELECTOR_H */ diff --git a/addressbook/gui/widgets/e-addressbook-table-adapter.c b/addressbook/gui/widgets/e-addressbook-table-adapter.c index a4440155d9..356aabdf8f 100644 --- a/addressbook/gui/widgets/e-addressbook-table-adapter.c +++ b/addressbook/gui/widgets/e-addressbook-table-adapter.c @@ -31,7 +31,7 @@ #include <libxml/xmlmemory.h> struct _EAddressbookTableAdapterPrivate { - EABModel *model; + EAddressbookModel *model; int create_contact_id, remove_contact_id, modify_contact_id, model_changed_id; @@ -100,7 +100,7 @@ addressbook_row_count (ETableModel *etc) EAddressbookTableAdapter *adapter = EAB_TABLE_ADAPTER(etc); EAddressbookTableAdapterPrivate *priv = adapter->priv; - return eab_model_contact_count (priv->model); + return e_addressbook_model_contact_count (priv->model); } /* This function returns the value at a particular point in our ETableModel. */ @@ -111,10 +111,10 @@ addressbook_value_at (ETableModel *etc, int col, int row) EAddressbookTableAdapterPrivate *priv = adapter->priv; const char *value; - if ( col >= COLS || row >= eab_model_contact_count (priv->model) ) + if ( col >= COLS || row >= e_addressbook_model_contact_count (priv->model) ) return NULL; - value = e_contact_get_const((EContact*)eab_model_contact_at (priv->model, row), col); + value = e_contact_get_const((EContact*)e_addressbook_model_contact_at (priv->model, row), col); if (value && *value && (col == E_CONTACT_EMAIL_1 || col == E_CONTACT_EMAIL_2 || col == E_CONTACT_EMAIL_3)) { char *val = g_hash_table_lookup (priv->emails, value); @@ -156,13 +156,13 @@ addressbook_set_value_at (ETableModel *etc, int col, int row, const void *val) EAddressbookTableAdapter *adapter = EAB_TABLE_ADAPTER(etc); EAddressbookTableAdapterPrivate *priv = adapter->priv; - if (eab_model_editable (priv->model)) { + if (e_addressbook_model_get_editable (priv->model)) { EContact *contact; - if (col >= COLS || row >= eab_model_contact_count (priv->model)) + if (col >= COLS || row >= e_addressbook_model_contact_count (priv->model)) return; - contact = eab_model_get_contact (priv->model, row); + contact = e_addressbook_model_get_contact (priv->model, row); if (!contact) return; @@ -177,7 +177,7 @@ addressbook_set_value_at (ETableModel *etc, int col, int row, const void *val) } e_contact_set(contact, col, (void *) val); - eab_merging_book_commit_contact (eab_model_get_ebook (priv->model), + eab_merging_book_commit_contact (e_addressbook_model_get_book (priv->model), contact, contact_modified_cb, etc); g_object_unref (contact); @@ -196,12 +196,12 @@ addressbook_is_cell_editable (ETableModel *etc, int col, int row) EAddressbookTableAdapterPrivate *priv = adapter->priv; const EContact *contact; - if (row >= 0 && row < eab_model_contact_count (priv->model)) - contact = eab_model_contact_at (priv->model, row); + if (row >= 0 && row < e_addressbook_model_contact_count (priv->model)) + contact = e_addressbook_model_contact_at (priv->model, row); else contact = NULL; - if (!eab_model_editable(priv->model)) + if (!e_addressbook_model_editable(priv->model)) return FALSE; else if (contact && e_contact_get ((EContact *) contact, E_CONTACT_IS_LIST)) /* we only allow editing of the name and file as for @@ -229,7 +229,7 @@ addressbook_append_row (ETableModel *etm, ETableModel *source, gint row) e_contact_set (contact, col, (void *) val); } - eab_merging_book_add_contact (eab_model_get_ebook (priv->model), contact, NULL, NULL); + eab_merging_book_add_contact (e_addressbook_model_get_book (priv->model), contact, NULL, NULL); g_object_unref (contact); } @@ -304,7 +304,7 @@ eab_table_adapter_init (GObject *object) static void -create_contact (EABModel *model, +create_contact (EAddressbookModel *model, gint index, gint count, EAddressbookTableAdapter *adapter) { @@ -313,7 +313,7 @@ create_contact (EABModel *model, } static void -remove_contacts (EABModel *model, +remove_contacts (EAddressbookModel *model, gpointer data, EAddressbookTableAdapter *adapter) { @@ -331,7 +331,7 @@ remove_contacts (EABModel *model, } static void -modify_contact (EABModel *model, +modify_contact (EAddressbookModel *model, gint index, EAddressbookTableAdapter *adapter) { @@ -343,7 +343,7 @@ modify_contact (EABModel *model, } static void -model_changed (EABModel *model, +model_changed (EAddressbookModel *model, EAddressbookTableAdapter *adapter) { /* clear whole cache */ @@ -379,7 +379,7 @@ eab_table_adapter_get_type (void) void eab_table_adapter_construct (EAddressbookTableAdapter *adapter, - EABModel *model) + EAddressbookModel *model) { EAddressbookTableAdapterPrivate *priv = adapter->priv; @@ -407,7 +407,7 @@ eab_table_adapter_construct (EAddressbookTableAdapter *adapter, } ETableModel * -eab_table_adapter_new (EABModel *model) +eab_table_adapter_new (EAddressbookModel *model) { EAddressbookTableAdapter *et; diff --git a/addressbook/gui/widgets/e-addressbook-table-adapter.h b/addressbook/gui/widgets/e-addressbook-table-adapter.h index c4182d2d2b..338c87948c 100644 --- a/addressbook/gui/widgets/e-addressbook-table-adapter.h +++ b/addressbook/gui/widgets/e-addressbook-table-adapter.h @@ -49,7 +49,7 @@ struct _EAddressbookTableAdapterClass { GType eab_table_adapter_get_type (void); void eab_table_adapter_construct (EAddressbookTableAdapter *adapter, - EABModel *model); -ETableModel *eab_table_adapter_new (EABModel *model); + EAddressbookModel *model); +ETableModel *eab_table_adapter_new (EAddressbookModel *model); #endif /* _EAB_TABLE_ADAPTER_H_ */ diff --git a/addressbook/gui/widgets/e-addressbook-view.c b/addressbook/gui/widgets/e-addressbook-view.c index 3c0c28f6ad..a979e5a1cb 100644 --- a/addressbook/gui/widgets/e-addressbook-view.c +++ b/addressbook/gui/widgets/e-addressbook-view.c @@ -30,11 +30,9 @@ #include <widgets/menus/gal-view-factory-etable.h> #include <filter/rule-editor.h> #include <widgets/menus/gal-view-etable.h> -#include <e-util/e-xml-utils.h> +#include <e-shell-sidebar.h> #include "addressbook/printing/e-contact-print.h" -#include "addressbook/gui/widgets/eab-popup.h" -#include "addressbook/gui/widgets/eab-menu.h" #include "a11y/addressbook/ea-addressbook.h" #include "e-util/e-print.h" @@ -55,1532 +53,946 @@ #include "e-util/e-error.h" #include "e-util/e-util-private.h" -#include "e-contact-editor.h" #include <gdk/gdkkeysyms.h> #include <ctype.h> #include <string.h> -#include <libxml/tree.h> -#include <libxml/parser.h> - -#define SHOW_ALL_SEARCH "(contains \"x-evolution-any-field\" \"\")" +#define E_ADDRESSBOOK_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW, EAddressbookViewPrivate)) #define d(x) -static void eab_view_init (EABView *card); -static void eab_view_class_init (EABViewClass *class); - -static void eab_view_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); -static void eab_view_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); - -static void eab_view_dispose (GObject *object); -static void change_view_type (EABView *view, EABViewType view_type); - -static void status_message (GtkObject *object, const gchar *status, EABView *eav); -static void search_result (GtkObject *object, EBookViewStatus status, EABView *eav); -static void folder_bar_message (GtkObject *object, const gchar *status, EABView *eav); -static void stop_state_changed (GtkObject *object, EABView *eav); -static void writable_status (GtkObject *object, gboolean writable, EABView *eav); -static void backend_died (GtkObject *object, EABView *eav); -static void contact_changed (EABModel *model, gint index, EABView *eav); -static void contacts_removed (EABModel *model, gpointer data, EABView *eav); -static GList *get_selected_contacts (EABView *view); - -static void command_state_change (EABView *eav); - -static void selection_clear_event (GtkWidget *invisible, GdkEventSelection *event, - EABView *view); -static void selection_received (GtkWidget *invisible, GtkSelectionData *selection_data, - guint time, EABView *view); -static void selection_get (GtkWidget *invisible, GtkSelectionData *selection_data, - guint info, guint time_stamp, EABView *view); -static void invisible_destroyed (gpointer data, GObject *where_object_was); - -static void categories_changed_cb (gpointer object, gpointer user_data); -static void make_suboptions (EABView *view); -static void query_changed (ESearchBar *esb, EABView *view); -static void search_activated (ESearchBar *esb, EABView *view); -static void search_menu_activated (ESearchBar *esb, int id, EABView *view); -static GList *get_master_list (gboolean force_rebuild); +static void status_message (EAddressbookView *view, const gchar *status); +static void search_result (EAddressbookView *view, EBookViewStatus status); +static void folder_bar_message (EAddressbookView *view, const gchar *status); +static void stop_state_changed (GtkObject *object, EAddressbookView *view); +static void backend_died (EAddressbookView *view); -static gpointer parent_class; +static void command_state_change (EAddressbookView *view); + +struct _EAddressbookViewPrivate { + gpointer shell_view; /* weak pointer */ + + EAddressbookModel *model; + EActivity *activity; + + GList *clipboard_contacts; + ESource *source; + + GObject *object; + GtkWidget *widget; + + GalViewInstance *view_instance; + + GtkWidget *invisible; +}; -/* The arguments we take */ enum { PROP_0, - PROP_BOOK, - PROP_SOURCE, - PROP_QUERY, - PROP_TYPE, + PROP_MODEL, + PROP_SHELL_VIEW, + PROP_SOURCE }; enum { - STATUS_MESSAGE, - SEARCH_RESULT, - FOLDER_BAR_MESSAGE, + OPEN_CONTACT, + POPUP_EVENT, COMMAND_STATE_CHANGE, + SELECTION_CHANGE, LAST_SIGNAL }; -enum DndTargetType { +enum { DND_TARGET_TYPE_SOURCE_VCARD, DND_TARGET_TYPE_VCARD }; -#define VCARD_TYPE "text/x-vcard" -#define SOURCE_VCARD_TYPE "text/x-source-vcard" - -typedef struct EABSearchBarItem { - ESearchBarItem search; - char *image; -}EABSearchBarItem; static GtkTargetEntry drag_types[] = { - { SOURCE_VCARD_TYPE, 0, DND_TARGET_TYPE_SOURCE_VCARD }, - { VCARD_TYPE, 0, DND_TARGET_TYPE_VCARD } + { "text/x-source-vcard", 0, DND_TARGET_TYPE_SOURCE_VCARD }, + { "text/x-vcard", 0, DND_TARGET_TYPE_VCARD } }; -static const int num_drag_types = sizeof (drag_types) / sizeof (drag_types[0]); - -static guint eab_view_signals [LAST_SIGNAL] = {0, }; +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; static GdkAtom clipboard_atom = GDK_NONE; -static GalViewCollection *collection = NULL; - -enum { - ESB_FULL_NAME, - ESB_EMAIL, - ESB_ANY, -}; - -#if 0 -static ESearchBarItem addressbook_search_option_items[] = { - { N_("Name begins with"), ESB_FULL_NAME, ESB_ITEMTYPE_RADIO }, - { N_("Email begins with"), ESB_EMAIL, ESB_ITEMTYPE_RADIO }, - { N_("Any field contains"), ESB_ANY, ESB_ITEMTYPE_RADIO }, - { NULL, -1, 0 } -}; -#endif - -static ESearchBarItem addressbook_search_items[] = { - E_FILTERBAR_ADVANCED, - {NULL, 0, 0}, - E_FILTERBAR_SAVE, - E_FILTERBAR_EDIT, - {NULL, -1, 0} -}; - -GType -eab_view_get_type (void) +static void +addressbook_view_emit_open_contact (EAddressbookView *view, + EContact *contact, + gboolean is_new_contact) { - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (EABViewClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) eab_view_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EABView), - 0, /* n_preallocs */ - (GInstanceInitFunc) eab_view_init, - }; - - type = g_type_register_static (GTK_TYPE_VBOX, "EABView", &info, 0); - } - - return type; + g_signal_emit (view, signals[OPEN_CONTACT], 0, contact, is_new_contact); } static void -eab_view_class_init (EABViewClass *class) +addressbook_view_emit_popup_event (EAddressbookView *view, + GdkEvent *event) { - GObjectClass *object_class; - - parent_class = g_type_class_peek_parent (class); - - object_class = G_OBJECT_CLASS(class); - object_class->set_property = eab_view_set_property; - object_class->get_property = eab_view_get_property; - object_class->dispose = eab_view_dispose; - - g_object_class_install_property (object_class, PROP_BOOK, - g_param_spec_object ("book", - _("Book"), - /*_( */"XXX blurb" /*)*/, - E_TYPE_BOOK, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_SOURCE, - g_param_spec_object ("source", - _("Source"), - /*_( */"XXX blurb" /*)*/, - E_TYPE_SOURCE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_QUERY, - g_param_spec_string ("query", - _("Query"), - /*_( */"XXX blurb" /*)*/, - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_TYPE, - g_param_spec_int ("type", - _("Type"), - /*_( */"XXX blurb" /*)*/, - EAB_VIEW_NONE, - EAB_VIEW_TABLE, - EAB_VIEW_NONE, - G_PARAM_READWRITE)); - - eab_view_signals [STATUS_MESSAGE] = - g_signal_new ("status_message", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABViewClass, status_message), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - eab_view_signals [SEARCH_RESULT] = - g_signal_new ("search_result", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABViewClass, search_result), - NULL, NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, G_TYPE_INT); - - eab_view_signals [FOLDER_BAR_MESSAGE] = - g_signal_new ("folder_bar_message", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABViewClass, folder_bar_message), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - eab_view_signals [COMMAND_STATE_CHANGE] = - g_signal_new ("command_state_change", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABViewClass, command_state_change), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - if (!clipboard_atom) - clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); - - /* init the accessibility support for e_addressbook_view */ - eab_view_a11y_init(); + g_signal_emit (view, signals[POPUP_EVENT], 0, event); } static void -eab_view_init (EABView *eav) +addressbook_view_emit_selection_change (EAddressbookView *view) { - eav->view_type = EAB_VIEW_NONE; - - eav->model = NULL; - eav->object = NULL; - eav->widget = NULL; - eav->contact_display_window = NULL; - eav->contact_display = NULL; - eav->displayed_contact = -1; - - eav->view_instance = NULL; - eav->view_menus = NULL; - eav->current_view = NULL; - eav->uic = NULL; - - eav->book = NULL; - eav->source = NULL; - eav->query = NULL; - - eav->invisible = NULL; - eav->clipboard_contacts = NULL; + g_signal_emit (view, signals[SELECTION_CHANGE], 0); } static void -eab_view_dispose (GObject *object) +addressbook_view_open_contact (EAddressbookView *view, + EContact *contact) { - EABView *eav = EAB_VIEW(object); - - e_categories_unregister_change_listener (G_CALLBACK (categories_changed_cb), eav); - - if (eav->model) { - g_signal_handlers_disconnect_matched (eav->model, - G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, - object); - g_object_unref (eav->model); - eav->model = NULL; - } - - if (eav->book) { - g_object_unref (eav->book); - eav->book = NULL; - } - - if (eav->source) { - g_object_unref (eav->source); - eav->source = NULL; - } - - if (eav->query) { - g_free(eav->query); - eav->query = NULL; - } - - eav->uic = NULL; - - if (eav->view_instance) { - g_object_unref (eav->view_instance); - eav->view_instance = NULL; - } - - if (eav->view_menus) { - g_object_unref (eav->view_menus); - eav->view_menus = NULL; - } - - if (eav->clipboard_contacts) { - g_list_foreach (eav->clipboard_contacts, (GFunc)g_object_unref, NULL); - g_list_free (eav->clipboard_contacts); - eav->clipboard_contacts = NULL; - } - - if (eav->invisible) { - gtk_widget_destroy (eav->invisible); - eav->invisible = NULL; - } - - /* - if (eav->search_context) { - g_object_unref (eav->search_context); - eav->search_context = NULL; - } - */ - - if (eav->search_rule) { - g_object_unref (eav->search_rule); - eav->search_rule = NULL; - } - - G_OBJECT_CLASS (parent_class)->dispose (object); + addressbook_view_emit_open_contact (view, contact, FALSE); } static void -set_paned_position (EABView *eav) +addressbook_view_create_contact (EAddressbookView *view) { - GConfClient *gconf_client; - gint pos; - - /* XXX this should use the addressbook's global gconf client */ - gconf_client = gconf_client_get_default (); - pos = gconf_client_get_int (gconf_client, "/apps/evolution/addressbook/display/vpane_position", NULL); - if (pos < 1) - pos = 144; - - gtk_paned_set_position (GTK_PANED (eav->paned), pos); + EContact *contact; - g_object_unref (gconf_client); + contact = e_contact_new (); + addressbook_view_emit_open_contact (view, contact, TRUE); + g_object_unref (contact); } -static gboolean -get_paned_position (EABView *eav) +static void +addressbook_view_create_contact_list (EAddressbookView *view) { - GConfClient *gconf_client; - gint pos; - - /* XXX this should use the addressbook's global gconf client */ - gconf_client = gconf_client_get_default (); - - pos = gtk_paned_get_position (GTK_PANED (eav->paned)); - gconf_client_set_int (gconf_client, "/apps/evolution/addressbook/display/vpane_position", pos, NULL); - - g_object_unref (gconf_client); + EContact *contact; - return FALSE; + contact = e_contact_new (); + e_contact_set (contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (TRUE)); + addressbook_view_emit_open_contact (view, contact, TRUE); + g_object_unref (contact); } -GtkWidget* -eab_view_new (void) +static void +table_double_click (ETableScrolled *table, + gint row, + gint col, + GdkEvent *event, + EAddressbookView *view) { - GtkWidget *widget = GTK_WIDGET (g_object_new (E_TYPE_AB_VIEW, NULL)); - EABView *eav = EAB_VIEW (widget); - FilterPart *part; - char *xmlfile; - char *userfile; - - /* create our model */ - eav->model = eab_model_new (); - - g_signal_connect (eav->model, "status_message", - G_CALLBACK (status_message), eav); - g_signal_connect (eav->model, "search_result", - G_CALLBACK (search_result), eav); - g_signal_connect (eav->model, "folder_bar_message", - G_CALLBACK (folder_bar_message), eav); - g_signal_connect (eav->model, "stop_state_changed", - G_CALLBACK (stop_state_changed), eav); - g_signal_connect (eav->model, "writable_status", - G_CALLBACK (writable_status), eav); - g_signal_connect (eav->model, "backend_died", - G_CALLBACK (backend_died), eav); - g_signal_connect (eav->model, "contact_changed", - G_CALLBACK (contact_changed), eav); - g_signal_connect (eav->model, "contacts_removed", - G_CALLBACK (contacts_removed), eav); - - eav->editable = FALSE; - eav->query = g_strdup (SHOW_ALL_SEARCH); - - /* create the search context */ - eav->search_context = rule_context_new (); - rule_context_add_part_set (eav->search_context, "partset", filter_part_get_type (), - rule_context_add_part, rule_context_next_part); - rule_context_add_rule_set (eav->search_context, "ruleset", filter_rule_get_type (), - rule_context_add_rule, rule_context_next_rule); - - userfile = g_build_filename ( g_get_home_dir (), ".evolution/addressbook/searches.xml", NULL); - xmlfile = g_build_filename (SEARCH_RULE_DIR, "addresstypes.xml", NULL); - - g_object_set_data_full (G_OBJECT (eav->search_context), "user", userfile, g_free); - g_object_set_data_full (G_OBJECT (eav->search_context), "system", xmlfile, g_free); - - rule_context_load (eav->search_context, xmlfile, userfile); - - eav->search_rule = filter_rule_new (); - part = rule_context_next_part (eav->search_context, NULL); - - if (part == NULL) - g_warning ("Could not load addressbook search; no parts."); - else - filter_rule_add_part (eav->search_rule, filter_part_clone (part)); - - eav->search = e_filter_bar_new (eav->search_context, xmlfile, userfile, NULL, eav); - - g_free (xmlfile); - g_free (userfile); - - e_search_bar_set_menu ( (ESearchBar *) eav->search, addressbook_search_items); - gtk_widget_show (GTK_WIDGET (eav->search)); - make_suboptions (eav); - - e_categories_register_change_listener (G_CALLBACK (categories_changed_cb), eav); - - g_signal_connect (eav->search, "query_changed", - G_CALLBACK (query_changed), eav); - g_signal_connect (eav->search, "search_activated", - G_CALLBACK (search_activated), eav); - g_signal_connect (eav->search, "menu_activated", - G_CALLBACK (search_menu_activated), eav); - - gtk_box_pack_start (GTK_BOX (eav), GTK_WIDGET (eav->search), FALSE, FALSE, 0); - - /* create the paned window and contact display */ - eav->paned = gtk_vpaned_new (); - gtk_box_pack_start (GTK_BOX (eav), eav->paned, TRUE, TRUE, 0); - g_signal_connect_swapped (eav->paned, "button_release_event", - G_CALLBACK (get_paned_position), eav); - - eav->contact_display = eab_contact_display_new (); - eav->contact_display_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (eav->contact_display_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (eav->contact_display_window), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (eav->contact_display_window), eav->contact_display); - gtk_paned_add2 (GTK_PANED (eav->paned), eav->contact_display_window); - gtk_widget_show (eav->contact_display); - gtk_widget_show (eav->contact_display_window); - gtk_widget_show (eav->paned); - - /* gtk selection crap */ - eav->invisible = gtk_invisible_new (); - - gtk_selection_add_target (eav->invisible, - clipboard_atom, - GDK_SELECTION_TYPE_STRING, - 0); - - g_signal_connect (eav->invisible, "selection_get", - G_CALLBACK (selection_get), - eav); - g_signal_connect (eav->invisible, "selection_clear_event", - G_CALLBACK (selection_clear_event), - eav); - g_signal_connect (eav->invisible, "selection_received", - G_CALLBACK (selection_received), - eav); - g_object_weak_ref (G_OBJECT (eav->invisible), invisible_destroyed, eav); - - return widget; -} + EAddressbookModel *model; + EContact *contact; -RuleContext * -eab_view_peek_search_context (EABView *view) -{ - return view->search_context; -} + if (!E_IS_ADDRESSBOOK_TABLE_ADAPTER (view->priv->object)) + return; -FilterRule * -eab_view_peek_search_rule (EABView *view) -{ - return view->search_rule; + model = e_addressbook_view_get_model (view); + contact = e_addressbook_model_get_contact (model, row); + addressbook_view_emit_open_contact (view, contact, FALSE); + g_object_unref (contact); } -static void -writable_status (GtkObject *object, gboolean writable, EABView *eav) +static gint +table_right_click (ETableScrolled *table, + gint row, + gint col, + GdkEvent *event, + EAddressbookView *view) { - eav->editable = writable; - command_state_change (eav); -} + addressbook_view_emit_popup_event (view, event); -static void -init_collection (void) -{ - GalViewFactory *factory; - ETableSpecification *spec; - char *galview; - char *addressbookdir; - char *etspecfile; - - if (collection == NULL) { - collection = gal_view_collection_new(); - - gal_view_collection_set_title (collection, _("Address Book")); - - galview = g_build_filename ( - e_get_user_data_dir (), "addressbook", "views", NULL); - addressbookdir = g_build_filename (EVOLUTION_GALVIEWSDIR, - "addressbook", - NULL); - gal_view_collection_set_storage_directories - (collection, - addressbookdir, - galview); - g_free(addressbookdir); - g_free(galview); - - spec = e_table_specification_new(); - etspecfile = g_build_filename (EVOLUTION_ETSPECDIR, - "e-addressbook-view.etspec", - NULL); - if (!e_table_specification_load_from_file (spec, etspecfile)) - g_error ("Unable to load ETable specification file " - "for address book"); - g_free (etspecfile); - - factory = gal_view_factory_etable_new (spec); - g_object_unref (spec); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - - factory = gal_view_factory_minicard_new(); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - - gal_view_collection_load(collection); - } + return TRUE; } -static void -set_view_preview (EABView *view) +static gint +table_white_space_event (ETableScrolled *table, + GdkEvent *event, + EAddressbookView *view) { - /* XXX this should use the addressbook's global gconf client */ - GConfClient *gconf_client; - gboolean state; - - gconf_client = gconf_client_get_default(); - state = gconf_client_get_bool(gconf_client, "/apps/evolution/addressbook/display/show_preview", NULL); - bonobo_ui_component_set_prop (view->uic, - "/commands/ContactsViewPreview", - "state", - state ? "1" : "0", NULL); + gint button = ((GdkEventButton *) event)->button; - eab_view_show_contact_preview (view, state); - - g_object_unref (gconf_client); -} - -static void -display_view(GalViewInstance *instance, - GalView *view, - gpointer data) -{ - EABView *address_view = data; - if (GAL_IS_VIEW_ETABLE(view)) { - change_view_type (address_view, EAB_VIEW_TABLE); - gal_view_etable_attach_table (GAL_VIEW_ETABLE(view), e_table_scrolled_get_table(E_TABLE_SCROLLED(address_view->widget))); - } - else if (GAL_IS_VIEW_MINICARD(view)) { - change_view_type (address_view, EAB_VIEW_MINICARD); - gal_view_minicard_attach (GAL_VIEW_MINICARD (view), address_view); + if (event->type == GDK_BUTTON_PRESS && button == 3) { + addressbook_view_emit_popup_event (view, event); + return TRUE; } - address_view->current_view = view; - set_paned_position (address_view); - set_view_preview (address_view); + return FALSE; } static void -view_preview(BonoboUIComponent *uic, const char *path, Bonobo_UIComponent_EventType type, const char *state, void *data) -{ - /* XXX this should use the addressbook's global gconf client */ - GConfClient *gconf_client; - EABView *view = EAB_VIEW (data); +table_drag_data_get (ETable *table, + gint row, + gint col, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time, + gpointer user_data) +{ + EAddressbookView *view = user_data; + EAddressbookModel *model; + EBook *book; + GList *contact_list; + gchar *value; - if (type != Bonobo_UIComponent_STATE_CHANGED) + if (!E_IS_ADDRESSBOOK_TABLE_ADAPTER (view->priv->object)) return; - gconf_client = gconf_client_get_default(); - gconf_client_set_bool(gconf_client, "/apps/evolution/addressbook/display/show_preview", state[0] != '0', NULL); + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); - eab_view_show_contact_preview(view, state[0] != '0'); + contact_list = e_addressbook_view_get_selected (view); - g_object_unref (gconf_client); -} + switch (info) { + case DND_TARGET_TYPE_VCARD: + value = eab_contact_list_to_string (contact_list); -static void -setup_menus (EABView *view) -{ - if (view->book && view->view_instance == NULL) { - init_collection (); - view->view_instance = gal_view_instance_new (collection, e_book_get_uri (view->book)); - } + gtk_selection_data_set ( + selection_data, selection_data->target, + 8, (guchar *)value, strlen (value)); - if (view->view_instance && view->uic) { - view->view_menus = gal_view_menus_new(view->view_instance); - gal_view_menus_apply(view->view_menus, view->uic, NULL); + g_free (value); + break; - display_view (view->view_instance, gal_view_instance_get_current_view (view->view_instance), view); + case DND_TARGET_TYPE_SOURCE_VCARD: + value = eab_book_and_contact_list_to_string ( + book, contact_list); - g_signal_connect(view->view_instance, "display_view", - G_CALLBACK (display_view), view); - } + gtk_selection_data_set ( + selection_data, selection_data->target, + 8, (guchar *)value, strlen (value)); - bonobo_ui_component_add_listener(view->uic, "ContactsViewPreview", view_preview, view); + g_free (value); + break; + } - set_view_preview (view); + g_list_foreach (contact_list, (GFunc) g_object_unref, NULL); + g_list_free (contact_list); } static void -eab_view_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +addressbook_view_create_table_view (EAddressbookView *view) { - EABView *eav = EAB_VIEW(object); + ETableModel *adapter; + ETable *table; + GtkWidget *widget; + gchar *etspecfile; - switch (prop_id){ - case PROP_BOOK: - if (eav->book) { - g_object_unref (eav->book); - } - if (g_value_get_object (value)) { - eav->book = E_BOOK(g_value_get_object (value)); - g_object_ref (eav->book); - gtk_widget_set_sensitive (GTK_WIDGET (eav->search), TRUE); - } - else { - eav->book = NULL; - gtk_widget_set_sensitive (GTK_WIDGET (eav->search), FALSE); - } + adapter = eab_table_adapter_new (view->priv->model); - if (eav->view_instance) { - g_object_unref (eav->view_instance); - eav->view_instance = NULL; - } + /* Here we create the table. We give it the three pieces of + the table we've created, the header, the model, and the + initial layout. It does the rest. */ + etspecfile = g_build_filename ( + EVOLUTION_ETSPECDIR, "e-addressbook-view.etspec", NULL); + widget = e_table_scrolled_new_from_spec_file ( + adapter, NULL, etspecfile, NULL); + table = E_TABLE (E_TABLE_SCROLLED (widget)->table); + g_free (etspecfile); - g_object_set(eav->model, - "book", eav->book, - NULL); + view->priv->object = G_OBJECT (adapter); + view->priv->widget = widget; - setup_menus (eav); + g_signal_connect ( + table, "double_click", + G_CALLBACK(table_double_click), view); + g_signal_connect ( + table, "right_click", + G_CALLBACK(table_right_click), view); + g_signal_connect ( + table, "white_space_event", + G_CALLBACK(table_white_space_event), view); + g_signal_connect_swapped ( + table, "selection_change", + G_CALLBACK (addressbook_view_emit_selection_change), view); - break; - case PROP_SOURCE: - if (eav->source) { - g_warning ("EABView at present does not support multiple writes on the \"source\" property."); - break; - } - else { - if (g_value_get_object (value)) { - eav->source = E_SOURCE(g_value_get_object (value)); - g_object_ref (eav->source); - } - else { - eav->source = NULL; - } - } - break; - case PROP_QUERY: -#if 0 /* This code will mess up ldap a bit. We need to think about the ramifications of this more. */ - if ((g_value_get_string (value) == NULL && !strcmp (eav->query, SHOW_ALL_SEARCH)) || - (g_value_get_string (value) != NULL && !strcmp (eav->query, g_value_get_string (value)))) - break; -#endif - g_free(eav->query); - eav->query = g_strdup(g_value_get_string (value)); - if (!eav->query) - eav->query = g_strdup (SHOW_ALL_SEARCH); - g_object_set(eav->model, - "query", eav->query, - NULL); - break; - case PROP_TYPE: - change_view_type(eav, g_value_get_int (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + e_table_drag_source_set ( + table, GDK_BUTTON1_MASK, + drag_types, G_N_ELEMENTS (drag_types), + GDK_ACTION_MOVE | GDK_ACTION_COPY); + + g_signal_connect ( + table, "table_drag_data_get", + G_CALLBACK (table_drag_data_get), view); + + gtk_box_pack_start (GTK_BOX (view), widget, TRUE, TRUE, 0); + + gtk_widget_show (widget); } static void -eab_view_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +addressbook_view_create_minicard_view (EAddressbookView *view) { - EABView *eav = EAB_VIEW(object); + GtkWidget *scrolled_window; + GtkWidget *minicard_view; + EAddressbookReflowAdapter *adapter; - switch (prop_id) { - case PROP_BOOK: - if (eav->book) - g_value_set_object (value, eav->book); - else - g_value_set_object (value, NULL); - break; - case PROP_SOURCE: - if (eav->source) - g_value_set_object (value, eav->source); - else - g_value_set_object (value, NULL); - break; - - case PROP_QUERY: - g_value_set_string (value, eav->query); - break; - case PROP_TYPE: - g_value_set_int (value, eav->view_type); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} + adapter = E_ADDRESSBOOK_REFLOW_ADAPTER ( + e_addressbook_reflow_adapter_new (view->priv->model)); + minicard_view = e_minicard_view_widget_new (adapter); -static ESelectionModel* -get_selection_model (EABView *view) -{ - if (view->view_type == EAB_VIEW_TABLE) - return e_table_get_selection_model (e_table_scrolled_get_table (E_TABLE_SCROLLED(view->widget))); - else if (view->view_type == EAB_VIEW_MINICARD) - return e_minicard_view_widget_get_selection_model (E_MINICARD_VIEW_WIDGET(view->object)); - g_return_val_if_reached (NULL); -} + g_signal_connect_swapped ( + adapter, "open-contact", + G_CALLBACK (addressbook_view_open_contact), view); -/* Popup menu stuff */ -typedef struct { - EABView *view; - gpointer closure; -} ContactAndBook; + g_signal_connect_swapped ( + minicard_view, "create-contact", + G_CALLBACK (addressbook_view_create_contact), view); -static ESelectionModel* -contact_and_book_get_selection_model (ContactAndBook *contact_and_book) -{ - return get_selection_model (contact_and_book->view); -} + g_signal_connect_swapped ( + minicard_view, "create-contact-list", + G_CALLBACK (addressbook_view_create_contact_list), view); -static GList * -get_contact_list (EABPopupTargetSelect *t) -{ - GList *list = NULL; - int i; + g_signal_connect_swapped ( + minicard_view, "selection_change", + G_CALLBACK (addressbook_view_emit_selection_change), view); - for (i=0;i<t->cards->len;i++) - list = g_list_prepend(list, t->cards->pdata[i]); + g_signal_connect_swapped ( + minicard_view, "right_click", + G_CALLBACK (addressbook_view_emit_popup_event), view); - return list; -} + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); -static void -save_as (EPopup *ep, EPopupItem *pitem, void *data) -{ - /*ContactAndBook *contact_and_book = data;*/ - GList *contacts = get_contact_list ((EABPopupTargetSelect *)ep->target); + view->priv->object = G_OBJECT (minicard_view); + view->priv->widget = scrolled_window; - if (contacts) { - eab_contact_list_save(_("Save as vCard..."), contacts, NULL); - g_list_free(contacts); - } -} + gtk_container_add (GTK_CONTAINER (scrolled_window), minicard_view); + gtk_widget_show (minicard_view); -static void -send_as (EPopup *ep, EPopupItem *pitem, void *data) -{ - /*ContactAndBook *contact_and_book = data;*/ - GList *contacts = get_contact_list ((EABPopupTargetSelect *)ep->target); + gtk_widget_show_all (scrolled_window); - if (contacts) { - eab_send_contact_list(contacts, EAB_DISPOSITION_AS_ATTACHMENT); - g_list_free(contacts); - } + gtk_box_pack_start (GTK_BOX (view), scrolled_window, TRUE, TRUE, 0); + + e_reflow_model_changed (E_REFLOW_MODEL (adapter)); } static void -send_to (EPopup *ep, EPopupItem *pitem, void *data) -{ - /*ContactAndBook *contact_and_book = data;*/ - GList *contacts = get_contact_list ((EABPopupTargetSelect *)ep->target); - - if (contacts) { - eab_send_contact_list(contacts, EAB_DISPOSITION_AS_TO); - g_list_free(contacts); +addressbook_view_display_view_cb (EAddressbookView *view, + GalView *gal_view) +{ + if (view->priv->widget != NULL) { + gtk_container_remove ( + GTK_CONTAINER (view), + view->priv->widget); + view->priv->widget = NULL; + } + view->priv->object = NULL; + + if (GAL_IS_VIEW_ETABLE (gal_view)) { + addressbook_view_create_table_view (view); + gal_view_etable_attach_table ( + GAL_VIEW_ETABLE (gal_view), + e_table_scrolled_get_table ( + E_TABLE_SCROLLED (view->priv->widget))); } + else if (GAL_IS_VIEW_MINICARD (gal_view)) { + addressbook_view_create_minicard_view (view); + gal_view_minicard_attach ( + GAL_VIEW_MINICARD (gal_view), view); + } + + command_state_change (view); } static void -print (EPopup *ep, EPopupItem *pitem, void *data) +addressbook_view_selection_get_cb (EAddressbookView *view, + GtkSelectionData *selection_data, + guint info, + guint time_stamp) { - /*ContactAndBook *contact_and_book = data;*/ - EABPopupTargetSelect *t = (EABPopupTargetSelect *)ep->target; - GList *contact_list; + gchar *string; - contact_list = get_contact_list (t); - e_contact_print ( - NULL, NULL, contact_list, - GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG); - g_list_free (contact_list); -} + string = eab_contact_list_to_string (view->priv->clipboard_contacts); -static void -copy (EPopup *ep, EPopupItem *pitem, void *data) -{ - ContactAndBook *contact_and_book = data; + gtk_selection_data_set ( + selection_data, GDK_SELECTION_TYPE_STRING, + 8, (guchar *) string, strlen (string)); - eab_view_copy (contact_and_book->view); + g_free (string); } static void -paste (EPopup *ep, EPopupItem *pitem, void *data) +addressbook_view_selection_clear_event_cb (EAddressbookView *view, + GdkEventSelection *event) { - ContactAndBook *contact_and_book = data; + GList *list; + + list = view->priv->clipboard_contacts; + view->priv->clipboard_contacts = NULL; - eab_view_paste (contact_and_book->view); + g_list_foreach (list, (GFunc) g_object_unref, NULL); + g_list_free (list); } static void -cut (EPopup *ep, EPopupItem *pitem, void *data) +addressbook_view_selection_received_cb (EAddressbookView *view, + GtkSelectionData *selection_data, + guint time) { - ContactAndBook *contact_and_book = data; + EAddressbookModel *model; + GList *list, *iter; + EBook *book; - eab_view_cut (contact_and_book->view); -} + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); -static void -delete (EPopup *ep, EPopupItem *pitem, void *data) -{ - ContactAndBook *contact_and_book = data; + if (selection_data->length <= 0) + return; - eab_view_delete_selection(contact_and_book->view, TRUE); -} + if (selection_data->type != GDK_SELECTION_TYPE_STRING) + return; -static void -copy_to_folder (EPopup *ep, EPopupItem *pitem, void *data) -{ - ContactAndBook *contact_and_book = data; + if (selection_data->data[selection_data->length - 1] != 0) { + gchar *string; - eab_view_copy_to_folder (contact_and_book->view, FALSE); -} + string = g_malloc0 (selection_data->length + 1); + memcpy (string, selection_data->data, selection_data->length); + list = eab_contact_list_from_string (string); + g_free (string); + } else + list = eab_contact_list_from_string ( + (gchar *) selection_data->data); -static void -move_to_folder (EPopup *ep, EPopupItem *pitem, void *data) -{ - ContactAndBook *contact_and_book = data; + for (iter = list; iter != NULL; iter = iter->next) { + EContact *contact = iter->data; - eab_view_move_to_folder (contact_and_book->view, FALSE); + /* XXX NULL for a callback /sigh */ + eab_merging_book_add_contact ( + book, contact, NULL /* XXX */, NULL); + } + + g_list_foreach (list, (GFunc) g_object_unref, NULL); + g_list_free (list); } static void -open_contact (EPopup *ep, EPopupItem *pitem, void *data) +addressbook_view_set_shell_view (EAddressbookView *view, + EShellView *shell_view) { - ContactAndBook *contact_and_book = data; + g_return_if_fail (view->priv->shell_view == NULL); - eab_view_view (contact_and_book->view); -} + view->priv->shell_view = shell_view; + g_object_add_weak_pointer ( + G_OBJECT (shell_view), + &view->priv->shell_view); +} static void -new_card (EPopup *ep, EPopupItem *pitem, void *data) +addressbook_view_set_source (EAddressbookView *view, + ESource *source) { - /*ContactAndBook *contact_and_book = data;*/ - EContact *contact = e_contact_new(); + g_return_if_fail (view->priv->source == NULL); - eab_show_contact_editor (((EABPopupTargetSelect *)ep->target)->book, contact, TRUE, TRUE); - g_object_unref (contact); + view->priv->source = g_object_ref (source); } static void -new_list (EPopup *ep, EPopupItem *pitem, void *data) -{ - /*ContactAndBook *contact_and_book = data;*/ - EContact *contact = e_contact_new (); +addressbook_view_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id){ + case PROP_SHELL_VIEW: + addressbook_view_set_shell_view ( + E_ADDRESSBOOK_VIEW (object), + g_value_get_object (value)); + return; + + case PROP_SOURCE: + addressbook_view_set_source ( + E_ADDRESSBOOK_VIEW (object), + g_value_get_object (value)); + return; + } - eab_show_contact_list_editor (((EABPopupTargetSelect *)ep->target)->book, contact, TRUE, TRUE); - g_object_unref(contact); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } -static EPopupItem eabv_popup_items[] = { - { E_POPUP_ITEM, "05.open", N_("_Open"), open_contact, NULL, NULL, EAB_POPUP_SELECT_ANY|EAB_POPUP_SELECT_EDITABLE }, - { E_POPUP_BAR, "10.bar" }, - { E_POPUP_ITEM, "10.new", N_("_New Contact..."), new_card, NULL, "contact-new", 0, EAB_POPUP_SELECT_EDITABLE}, - { E_POPUP_ITEM, "15.newlist", N_("New Contact _List..."), new_list, NULL, "stock_contact-list", 0, EAB_POPUP_SELECT_EDITABLE }, - - { E_POPUP_BAR, "20.bar" }, - { E_POPUP_ITEM, "30.saveas", N_("_Save as vCard..."), save_as, NULL, "document-save-as", 0, EAB_POPUP_SELECT_ANY }, - { E_POPUP_ITEM, "40.forward", N_("_Forward Contact"), send_as, NULL, "mail-forward", EAB_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "40.forward", N_("_Forward Contacts"), send_as, NULL, "mail-forward", EAB_POPUP_SELECT_MANY }, - { E_POPUP_ITEM, "50.mailto", N_("Send _Message to Contact"), send_to, NULL, "mail-message-new", EAB_POPUP_SELECT_ONE|EAB_POPUP_SELECT_EMAIL|EAB_POPUP_CONTACT }, - { E_POPUP_ITEM, "50.mailto", N_("Send _Message to List"), send_to, NULL, "mail-message-new", EAB_POPUP_SELECT_ONE|EAB_POPUP_SELECT_EMAIL|EAB_POPUP_LIST }, - { E_POPUP_ITEM, "50.mailto", N_("Send _Message to Contacts"), send_to, NULL, "mail-message-new", EAB_POPUP_SELECT_MANY|EAB_POPUP_SELECT_EMAIL }, - { E_POPUP_ITEM, "60.print", N_("_Print"), print, NULL, "document-print", 0, EAB_POPUP_SELECT_ANY }, - - { E_POPUP_BAR, "70.bar" }, - { E_POPUP_ITEM, "80.copyto", N_("Cop_y to Address Book..."), copy_to_folder, NULL, NULL, 0, EAB_POPUP_SELECT_ANY }, - { E_POPUP_ITEM, "90.moveto", N_("Mo_ve to Address Book..."), move_to_folder, NULL, NULL, 0, EAB_POPUP_SELECT_ANY|EAB_POPUP_SELECT_EDITABLE }, - - { E_POPUP_BAR, "a0.bar" }, - { E_POPUP_ITEM, "b0.cut", N_("Cu_t"), cut, NULL, "edit-cut", 0, EAB_POPUP_SELECT_ANY|EAB_POPUP_SELECT_EDITABLE }, - { E_POPUP_ITEM, "c0.copy", N_("_Copy"), copy, NULL, "edit-copy", 0, EAB_POPUP_SELECT_ANY }, - { E_POPUP_ITEM, "d0.paste", N_("P_aste"), paste, NULL, "edit-paste", 0, EAB_POPUP_SELECT_EDITABLE }, - { E_POPUP_ITEM, "e0.delete", N_("_Delete"), delete, NULL, "edit-delete", 0, EAB_POPUP_SELECT_EDITABLE|EAB_POPUP_SELECT_ANY }, -}; - static void -get_card_1(gint model_row, void *data) -{ - ContactAndBook *contact_and_book = data; - EContact *contact; +addressbook_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_MODEL: + g_value_set_object ( + value, e_addressbook_view_get_model ( + E_ADDRESSBOOK_VIEW (object))); + return; + + case PROP_SHELL_VIEW: + g_value_set_object ( + value, e_addressbook_view_get_shell_view ( + E_ADDRESSBOOK_VIEW (object))); + return; + + case PROP_SOURCE: + g_value_set_object ( + value, e_addressbook_view_get_source ( + E_ADDRESSBOOK_VIEW (object))); + return; + } - contact = eab_model_get_contact(contact_and_book->view->model, model_row); - if (contact) - g_ptr_array_add((GPtrArray *)contact_and_book->closure, contact); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -eabv_popup_free(EPopup *ep, GSList *list, void *data) +addressbook_view_dispose (GObject *object) { - ContactAndBook *cab = data; - ESelectionModel *selection; + EAddressbookViewPrivate *priv; - /* NB: this looks strange to me */ - selection = contact_and_book_get_selection_model(cab); - if (selection) - e_selection_model_right_click_up(selection); + priv = E_ADDRESSBOOK_VIEW_GET_PRIVATE (object); - g_slist_free(list); - g_object_unref(cab->view); - g_free(cab); -} + if (priv->shell_view != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->shell_view), + &priv->shell_view); + priv->shell_view = NULL; + } -static void -do_popup_menu(EABView *view, GdkEvent *event) -{ - EABPopup *ep; - EABPopupTargetSelect *t; - GSList *menus = NULL; - int i; - GtkMenu *menu; - GPtrArray *cards = g_ptr_array_new(); - ContactAndBook *contact_and_book; - ESelectionModel *selection_model; - - contact_and_book = g_new(ContactAndBook, 1); - contact_and_book->view = view; - g_object_ref(contact_and_book->view); - - selection_model = contact_and_book_get_selection_model(contact_and_book); - if (selection_model) { - contact_and_book->closure = cards; - e_selection_model_foreach(selection_model, get_card_1, contact_and_book); + if (priv->model != NULL) { + g_signal_handlers_disconnect_matched ( + priv->model, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->model); + priv->model = NULL; } - /** @HookPoint-EABPopup:Addressbook view Context Menu - * @Id: org.gnome.evolution.addressbook.view.popup - * @Class: org.gnome.evolution.addresbook.popup:1.0 - * @Target: EABPopupTargetSelect - * - * The context menu on the contacts view. - */ + if (priv->activity != NULL) { + /* XXX Activity is not cancellable. */ + e_activity_complete (priv->activity); + g_object_unref (priv->activity); + priv->activity = NULL; + } - ep = eab_popup_new("org.gnome.evolution.addressbook.view.popup"); - t = eab_popup_target_new_select(ep, view->book, !eab_model_editable(view->model), cards); - t->target.widget = (GtkWidget *)view; + if (priv->invisible != NULL) { + gtk_widget_destroy (priv->invisible); + priv->invisible = NULL; + } - for (i=0;i<sizeof(eabv_popup_items)/sizeof(eabv_popup_items[0]);i++) - menus = g_slist_prepend(menus, &eabv_popup_items[i]); + if (priv->source != NULL) { + g_object_unref (priv->source); + priv->source = NULL; + } + + if (priv->view_instance != NULL) { + g_object_unref (priv->view_instance); + priv->view_instance = NULL; + } - e_popup_add_items((EPopup *)ep, menus, NULL, eabv_popup_free, contact_and_book); + g_list_foreach ( + priv->clipboard_contacts, + (GFunc) g_object_unref, NULL); + g_list_free (priv->clipboard_contacts); + priv->clipboard_contacts = NULL; - menu = e_popup_create_menu_once((EPopup *)ep, (EPopupTarget *)t, 0); - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event?event->button.button:0, event?event->button.time:gtk_get_current_event_time()); + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } static void -render_contact (int row, EABView *view) +addressbook_view_constructed (GObject *object) { - EContact *contact = eab_model_get_contact (view->model, row); + EAddressbookView *view = E_ADDRESSBOOK_VIEW (object); + GalViewInstance *view_instance; + EShellView *shell_view; + ESource *source; + gchar *uri; - view->displayed_contact = row; + shell_view = e_addressbook_view_get_shell_view (view); + source = e_addressbook_view_get_source (view); + uri = e_source_get_uri (source); - eab_contact_display_render (EAB_CONTACT_DISPLAY (view->contact_display), contact, - EAB_CONTACT_DISPLAY_RENDER_NORMAL); + view_instance = e_shell_view_new_view_instance (shell_view, uri); + g_signal_connect_swapped ( + view_instance, "display-view", + G_CALLBACK (addressbook_view_display_view_cb), view); + gal_view_instance_load (view_instance); + view->priv->view_instance = view_instance; + + g_free (uri); } static void -selection_changed (GObject *o, EABView *view) +addressbook_view_class_init (EAddressbookViewClass *class) { - ESelectionModel *selection_model; - - command_state_change (view); + GObjectClass *object_class; - selection_model = get_selection_model (view); + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EAddressbookViewPrivate)); - if (e_selection_model_selected_count (selection_model) == 1) - e_selection_model_foreach (selection_model, - (EForeachFunc)render_contact, view); - else { - view->displayed_contact = -1; - eab_contact_display_render (EAB_CONTACT_DISPLAY (view->contact_display), NULL, - EAB_CONTACT_DISPLAY_RENDER_NORMAL); - } + object_class = G_OBJECT_CLASS(class); + object_class->set_property = addressbook_view_set_property; + object_class->get_property = addressbook_view_get_property; + object_class->dispose = addressbook_view_dispose; + object_class->constructed = addressbook_view_constructed; + + g_object_class_install_property ( + object_class, + PROP_MODEL, + g_param_spec_object ( + "model", + _("Model"), + NULL, + E_TYPE_ADDRESSBOOK_MODEL, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, + PROP_SHELL_VIEW, + g_param_spec_object ( + "shell-view", + _("Shell View"), + NULL, + E_TYPE_SHELL_VIEW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property ( + object_class, + PROP_SOURCE, + g_param_spec_object ( + "source", + _("Source"), + NULL, + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + signals[OPEN_CONTACT] = g_signal_new ( + "open-contact", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookViewClass, open_contact), + NULL, NULL, + e_marshal_VOID__OBJECT_BOOLEAN, + G_TYPE_NONE, 2, + E_TYPE_CONTACT, + G_TYPE_BOOLEAN); + + signals[POPUP_EVENT] = g_signal_new ( + "popup-event", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookViewClass, popup_event), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + + signals[COMMAND_STATE_CHANGE] = g_signal_new ( + "command-state-change", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookViewClass, command_state_change), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[SELECTION_CHANGE] = g_signal_new ( + "selection-change", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookViewClass, selection_change), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + if (clipboard_atom == NULL) + clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); + /* init the accessibility support for e_addressbook_view */ + eab_view_a11y_init (); } static void -table_double_click(ETableScrolled *table, gint row, gint col, GdkEvent *event, EABView *view) +addressbook_view_init (EAddressbookView *view) { - if (E_IS_ADDRESSBOOK_TABLE_ADAPTER(view->object)) { - EABModel *model = view->model; - EContact *contact = eab_model_get_contact (model, row); - EBook *book; + view->priv = E_ADDRESSBOOK_VIEW_GET_PRIVATE (view); - g_object_get(model, - "book", &book, - NULL); + view->priv->model = e_addressbook_model_new (); - g_return_if_fail (E_IS_BOOK (book)); + view->priv->invisible = gtk_invisible_new (); - if (e_contact_get (contact, E_CONTACT_IS_LIST)) - eab_show_contact_list_editor (book, contact, FALSE, view->editable); - else - eab_show_contact_editor (book, contact, FALSE, view->editable); + gtk_selection_add_target ( + view->priv->invisible, clipboard_atom, + GDK_SELECTION_TYPE_STRING, 0); - g_object_unref (book); - g_object_unref (contact); - } + g_signal_connect_swapped ( + view->priv->invisible, "selection-get", + G_CALLBACK (addressbook_view_selection_get_cb), view); + g_signal_connect_swapped ( + view->priv->invisible, "selection-clear-event", + G_CALLBACK (addressbook_view_selection_clear_event_cb), view); + g_signal_connect_swapped ( + view->priv->invisible, "selection-received", + G_CALLBACK (addressbook_view_selection_received_cb), view); } -static gint -table_right_click(ETableScrolled *table, gint row, gint col, GdkEvent *event, EABView *view) +GType +e_addressbook_view_get_type (void) { - do_popup_menu(view, event); - return TRUE; -} + static GType type = 0; -static gint -table_white_space_event(ETableScrolled *table, GdkEvent *event, EABView *view) -{ - if (event->type == GDK_BUTTON_PRESS && ((GdkEventButton *)event)->button == 3) { - do_popup_menu(view, event); - return TRUE; - } else { - return FALSE; + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EAddressbookViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) addressbook_view_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EAddressbookView), + 0, /* n_preallocs */ + (GInstanceInitFunc) addressbook_view_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_VBOX, "EAddressbookView", &type_info, 0); } + + return type; } -static void -table_drag_data_get (ETable *table, - int row, - int col, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint time, - gpointer user_data) +GtkWidget * +e_addressbook_view_new (EShellView *shell_view, + ESource *source) { - EABView *view = user_data; - GList *contact_list; + GtkWidget *widget; + EAddressbookView *view; - if (!E_IS_ADDRESSBOOK_TABLE_ADAPTER(view->object)) - return; + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - contact_list = get_selected_contacts (view); + widget = g_object_new ( + E_TYPE_ADDRESSBOOK_VIEW, "shell-view", + shell_view, "source", source, NULL); - switch (info) { - case DND_TARGET_TYPE_VCARD: { - char *value; + view = E_ADDRESSBOOK_VIEW (widget); - value = eab_contact_list_to_string (contact_list); + g_signal_connect_swapped ( + view->priv->model, "status_message", + G_CALLBACK (status_message), view); + g_signal_connect_swapped ( + view->priv->model, "search_result", + G_CALLBACK (search_result), view); + g_signal_connect_swapped ( + view->priv->model, "folder_bar_message", + G_CALLBACK (folder_bar_message), view); + g_signal_connect (view->priv->model, "stop_state_changed", + G_CALLBACK (stop_state_changed), view); + g_signal_connect_swapped ( + view->priv->model, "writable-status", + G_CALLBACK (command_state_change), view); + g_signal_connect_swapped ( + view->priv->model, "backend_died", + G_CALLBACK (backend_died), view); - gtk_selection_data_set (selection_data, - selection_data->target, - 8, - (guchar *)value, strlen (value)); - g_free (value); - break; - } - case DND_TARGET_TYPE_SOURCE_VCARD: { - char *value; - - value = eab_book_and_contact_list_to_string (view->book, contact_list); - - gtk_selection_data_set (selection_data, - selection_data->target, - 8, - (guchar *)value, strlen (value)); - g_free (value); - break; - } - } - - g_list_foreach (contact_list, (GFunc) g_object_unref, NULL); - g_list_free (contact_list); + return widget; } -static void -emit_status_message (EABView *eav, const gchar *status) +EAddressbookModel * +e_addressbook_view_get_model (EAddressbookView *view) { - g_signal_emit (eav, - eab_view_signals [STATUS_MESSAGE], 0, - status); -} + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); -static void -emit_search_result (EABView *eav, EBookViewStatus status) -{ - g_signal_emit (eav, - eab_view_signals [SEARCH_RESULT], 0, - status); + return view->priv->model; } -static void -emit_folder_bar_message (EABView *eav, const gchar *message) +GalViewInstance * +e_addressbook_view_get_view_instance (EAddressbookView *view) { - g_signal_emit (eav, - eab_view_signals [FOLDER_BAR_MESSAGE], 0, - message); -} + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); -static void -status_message (GtkObject *object, const gchar *status, EABView *eav) -{ - emit_status_message (eav, status); + return view->priv->view_instance; } -static void -search_result (GtkObject *object, EBookViewStatus status, EABView *eav) +GObject * +e_addressbook_view_get_view_object (EAddressbookView *view) { - emit_search_result (eav, status); -} + /* XXX Find a more descriptive name for this. */ -static void -folder_bar_message (GtkObject *object, const gchar *status, EABView *eav) -{ - emit_folder_bar_message (eav, status); -} + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); -static void -stop_state_changed (GtkObject *object, EABView *eav) -{ - command_state_change (eav); + return view->priv->object; } -static void -command_state_change (EABView *eav) +GtkWidget * +e_addressbook_view_get_view_widget (EAddressbookView *view) { - /* Reffing during emission is unnecessary. Gtk automatically refs during an emission. */ - g_signal_emit (eav, eab_view_signals [COMMAND_STATE_CHANGE], 0); -} + /* XXX Find a more descriptive name for this. */ -static void -backend_died (GtkObject *object, EABView *eav) -{ - e_error_run (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (eav))), - "addressbook:backend-died", e_book_get_uri (eav->book), NULL); + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); + + return view->priv->widget; } +/* Helper for e_addressbook_view_get_selected() */ static void -contact_changed (EABModel *model, gint index, EABView *eav) +add_to_list (gint model_row, gpointer closure) { - if (eav->displayed_contact == index) { - /* if the contact that's presently displayed is changed, re-render it */ - render_contact (index, eav); - } + GList **list = closure; + *list = g_list_prepend (*list, GINT_TO_POINTER (model_row)); } -static void -contacts_removed (EABModel *model, gpointer data, EABView *eav) +GList * +e_addressbook_view_get_selected (EAddressbookView *view) { - GArray *indices = (GArray *) data; - int count = indices->len; - gint i; - - for (i = 0; i < count; i ++) { + GList *list, *iter; + ESelectionModel *selection; + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); - if (eav->displayed_contact == g_array_index (indices, gint, i)) { + list = NULL; + selection = e_addressbook_view_get_selection_model (view); + e_selection_model_foreach (selection, add_to_list, &list); - /* if the contact that's presently displayed is changed, clear the display */ - eab_contact_display_render (EAB_CONTACT_DISPLAY (eav->contact_display), NULL, - EAB_CONTACT_DISPLAY_RENDER_NORMAL); - eav->displayed_contact = -1; - break; - } - } -} + for (iter = list; iter != NULL; iter = iter->next) + iter->data = e_addressbook_model_get_contact ( + view->priv->model, GPOINTER_TO_INT (iter->data)); + list = g_list_reverse (list); -static void -minicard_right_click (EMinicardView *minicard_view_item, GdkEvent *event, EABView *view) -{ - do_popup_menu(view, event); + return list; } -static void -create_minicard_view (EABView *view) +ESelectionModel * +e_addressbook_view_get_selection_model (EAddressbookView *view) { - GtkWidget *scrolled_window; - GtkWidget *minicard_view; - EAddressbookReflowAdapter *adapter; + GalView *gal_view; + GalViewInstance *view_instance; + ESelectionModel *model = NULL; - adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(e_addressbook_reflow_adapter_new (view->model)); - minicard_view = e_minicard_view_widget_new(adapter); + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); - g_signal_connect(minicard_view, "selection_change", - G_CALLBACK(selection_changed), view); + view_instance = e_addressbook_view_get_view_instance (view); + gal_view = gal_view_instance_get_current_view (view_instance); - g_signal_connect(minicard_view, "right_click", - G_CALLBACK(minicard_right_click), view); + if (GAL_IS_VIEW_ETABLE (gal_view)) { + ETableScrolled *scrolled_table; + ETable *table; - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); + scrolled_table = E_TABLE_SCROLLED (view->priv->widget); + table = e_table_scrolled_get_table (scrolled_table); - view->object = G_OBJECT(minicard_view); - view->widget = scrolled_window; + model = e_table_get_selection_model (table); - gtk_container_add (GTK_CONTAINER (scrolled_window), minicard_view); - gtk_widget_show (minicard_view); + } else if (GAL_IS_VIEW_MINICARD (gal_view)) { + EMinicardViewWidget *widget; - gtk_widget_show_all( GTK_WIDGET(scrolled_window) ); + widget = E_MINICARD_VIEW_WIDGET (view->priv->object); - gtk_paned_add1 (GTK_PANED (view->paned), scrolled_window); + model = e_minicard_view_widget_get_selection_model (widget); + } - e_reflow_model_changed (E_REFLOW_MODEL (adapter)); + return model; } -static void -create_table_view (EABView *view) +EShellView * +e_addressbook_view_get_shell_view (EAddressbookView *view) { - ETableModel *adapter; - GtkWidget *table; - char *etspecfile; - - adapter = eab_table_adapter_new(view->model); + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); - /* Here we create the table. We give it the three pieces of - the table we've created, the header, the model, and the - initial layout. It does the rest. */ - etspecfile = g_build_filename (EVOLUTION_ETSPECDIR, - "e-addressbook-view.etspec", - NULL); - table = e_table_scrolled_new_from_spec_file (adapter, NULL, etspecfile, NULL); - g_free (etspecfile); - - view->object = G_OBJECT(adapter); - view->widget = table; - - g_signal_connect(e_table_scrolled_get_table(E_TABLE_SCROLLED(table)), "double_click", - G_CALLBACK(table_double_click), view); - g_signal_connect(e_table_scrolled_get_table(E_TABLE_SCROLLED(table)), "right_click", - G_CALLBACK(table_right_click), view); - g_signal_connect(e_table_scrolled_get_table(E_TABLE_SCROLLED(table)), "white_space_event", - G_CALLBACK(table_white_space_event), view); - g_signal_connect(e_table_scrolled_get_table(E_TABLE_SCROLLED(table)), "selection_change", - G_CALLBACK(selection_changed), view); - - /* drag & drop signals */ - e_table_drag_source_set (E_TABLE(E_TABLE_SCROLLED(table)->table), GDK_BUTTON1_MASK, - drag_types, num_drag_types, GDK_ACTION_MOVE | GDK_ACTION_COPY); - - g_signal_connect (E_TABLE_SCROLLED(table)->table, - "table_drag_data_get", - G_CALLBACK (table_drag_data_get), - view); - - gtk_paned_add1 (GTK_PANED (view->paned), table); - - gtk_widget_show( GTK_WIDGET(table) ); + return view->priv->shell_view; } -static void -change_view_type (EABView *view, EABViewType view_type) +ESource * +e_addressbook_view_get_source (EAddressbookView *view) { - if (view_type == view->view_type) - return; - - if (view->widget) { - gtk_container_remove (GTK_CONTAINER (view->paned), view->widget); - view->widget = NULL; - } - view->object = NULL; - - switch (view_type) { - case EAB_VIEW_TABLE: - create_table_view (view); - break; - case EAB_VIEW_MINICARD: - create_minicard_view (view); - break; - default: - g_warning ("view_type not recognized."); - return; - } - - view->view_type = view_type; + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); - command_state_change (view); + return view->priv->source; } - - static void -search_activated (ESearchBar *esb, EABView *v) -{ - GList *master_list; - char *search_word, *search_query, *view_sexp; - const char *category_name; - int search_type, subid; - - g_object_get(esb, - "text", &search_word, - "item_id", &search_type, - NULL); - - if (search_type == E_FILTERBAR_ADVANCED_ID) { - /* rebuild view immediately */ - query_changed (esb, v); - } - else { - if ((search_word && strlen (search_word))) { - GString *s = g_string_new (""); - e_sexp_encode_string (s, search_word); - switch (search_type) { - case ESB_ANY: - search_query = g_strdup_printf ("(contains \"x-evolution-any-field\" %s)", - s->str); - break; - case ESB_FULL_NAME: - search_query = g_strdup_printf ("(contains \"full_name\" %s)", - s->str); - break; - case ESB_EMAIL: - search_query = g_strdup_printf ("(beginswith \"email\" %s)", - s->str); - break; - default: - search_query = g_strdup ("(contains \"x-evolution-any-field\" \"\")"); - break; - } - g_string_free (s, TRUE); - - } else - search_query = g_strdup ("(contains \"x-evolution-any-field\" \"\")"); - - /* Merge view and sexp */ - subid = e_search_bar_get_viewitem_id (esb); - - if (subid) { - master_list = get_master_list (FALSE); - if (subid < 3) { - view_sexp = g_strdup ("(not (and (exists \"CATEGORIES\") (not (is \"CATEGORIES\" \"\"))))"); - } else { - category_name = g_list_nth_data (master_list, subid-3); - view_sexp = g_strdup_printf ("(is \"category_list\" \"%s\")", category_name); - } - search_query = g_strconcat ("(and ", view_sexp, search_query, ")", NULL); - g_free (view_sexp); +status_message (EAddressbookView *view, + const gchar *status) +{ + EActivity *activity; + EShellView *shell_view; + EShellModule *shell_module; + + activity = view->priv->activity; + shell_view = e_addressbook_view_get_shell_view (view); + shell_module = e_shell_view_get_shell_module (shell_view); + + if (status == NULL || *status == '\0') { + if (activity != NULL) { + e_activity_complete (activity); + g_object_unref (activity); + view->priv->activity = NULL; } - if (search_query) - g_object_set (v, - "query", search_query, - NULL); - - g_free (search_query); - } + } else if (activity == NULL) { + activity = e_activity_new (status); + view->priv->activity = activity; + e_shell_module_add_activity (shell_module, activity); - g_free (search_word); - v->displayed_contact = -1; - eab_contact_display_render (EAB_CONTACT_DISPLAY (v->contact_display), NULL, - EAB_CONTACT_DISPLAY_RENDER_NORMAL); + } else + e_activity_set_primary_text (activity, status); } static void -search_menu_activated (ESearchBar *esb, int id, EABView *view) +search_result (EAddressbookView *view, + EBookViewStatus status) { - if (id == E_FILTERBAR_ADVANCED_ID) - e_search_bar_set_item_id (esb, id); -} + EShellView *shell_view; + EShellWindow *shell_window; -static void -query_changed (ESearchBar *esb, EABView *view) -{ - int search_type; - char *query; - - search_type = e_search_bar_get_item_id(esb); - if (search_type == E_FILTERBAR_ADVANCED_ID) { - g_object_get (esb, "query", &query, NULL); - g_object_set (view, "query", query, NULL); - g_free (query); - } + shell_view = e_addressbook_view_get_shell_view (view); + shell_window = e_shell_view_get_shell_window (shell_view); + eab_search_result_dialog (GTK_WIDGET (shell_window), status); } -static int -compare_subitems (const void *a, const void *b) -{ - const ESearchBarItem *subitem_a = a; - const ESearchBarItem *subitem_b = b; - char *collate_a, *collate_b; - int ret; - - collate_a = g_utf8_collate_key (subitem_a->text, -1); - collate_b = g_utf8_collate_key (subitem_b->text, -1); - - ret = strcmp (collate_a, collate_b); - - g_free (collate_a); - g_free (collate_b); - - return ret; -} - -static GtkWidget * -generate_viewoption_menu (EABSearchBarItem *subitems) +static void +folder_bar_message (EAddressbookView *view, + const gchar *message) { - GtkWidget *menu, *menu_item; - gint i = 0; - - menu = gtk_menu_new (); - - for (i = 0; subitems[i].search.id != -1; ++i) { - if (subitems[i].search.text) { - char *str = NULL; - str = e_str_without_underscores (subitems[i].search.text); - menu_item = gtk_image_menu_item_new_with_label (str); - if (subitems[i].image) { - GtkWidget *image; - - image = gtk_image_new_from_file ( - subitems[i].image); - gtk_image_menu_item_set_image ( - GTK_IMAGE_MENU_ITEM (menu_item), - image); - } - g_free (str); - } else { - menu_item = gtk_menu_item_new (); - gtk_widget_set_sensitive (menu_item, FALSE); - } + EShellView *shell_view; + EShellSidebar *shell_sidebar; + const gchar *name; - g_object_set_data (G_OBJECT (menu_item), "EsbItemId", - GINT_TO_POINTER (subitems[i].search.id)); + shell_view = e_addressbook_view_get_shell_view (view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - gtk_widget_show (menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - } + if (view->priv->source == NULL) + return; - return menu; + name = e_source_peek_name (view->priv->source); + e_shell_sidebar_set_primary_text (shell_sidebar, name); + e_shell_sidebar_set_secondary_text (shell_sidebar, message); } static void -categories_changed_cb (gpointer object, gpointer user_data) +stop_state_changed (GtkObject *object, EAddressbookView *view) { - get_master_list (TRUE); - make_suboptions (user_data); + command_state_change (view); } static void -make_suboptions (EABView *view) +command_state_change (EAddressbookView *view) { - EABSearchBarItem *subitems, *s; - GList *master_list; - gint i, N; - GtkWidget *menu; - - master_list = get_master_list (FALSE); - N = g_list_length (master_list); - subitems = g_new (EABSearchBarItem, N+4); - - subitems[0].search.id = 0; - subitems[0].search.text = g_strdup (_("Any Category")); - subitems[0].image = NULL; - - subitems[1].search.text = g_strdup (_("Unmatched")); - subitems[1].search.id = 1; - subitems[1].image = NULL; - - subitems[2].search.text = NULL; - subitems[2].search.id = 0; - subitems[2].image = NULL; - - for (i=0; i<N; ++i) { - const char *category = g_list_nth_data (master_list, i); - subitems[i+3].search.id = i+3; - subitems[i+3].search.text = g_strdup (category); - subitems[i+3].image = (char *)e_categories_get_icon_file_for (category); - } - - subitems[N+3].search.id = -1; - subitems[N+3].search.text = NULL; - subitems[N+3].image = NULL; - - qsort (subitems + 3, N, sizeof (subitems[0]), compare_subitems); - menu = generate_viewoption_menu (subitems); - e_search_bar_set_viewoption_menu ((ESearchBar *)view->search, menu); - - for (s = subitems; ((ESearchBarItem *)s)->id != -1; s++) { - if (((ESearchBarItem *)s)->text) - g_free (((ESearchBarItem *)s)->text); - } - g_free (subitems); + g_signal_emit (view, signals[COMMAND_STATE_CHANGE], 0); } -static GList * -get_master_list (gboolean force_rebuild) +static void +backend_died (EAddressbookView *view) { - static GList *category_list = NULL; - - if (force_rebuild) { - g_list_free (category_list); - category_list = NULL; - } - - if (category_list == NULL) { - GList *l, *p = e_categories_get_list (); - - for (l = p; l; l = l->next) { - if (e_categories_is_searchable ((const char *) l->data)) - category_list = g_list_prepend (category_list, l->data); - } + EShellView *shell_view; + EShellWindow *shell_window; + EAddressbookModel *model; + EBook *book; - category_list = g_list_reverse (category_list); + shell_view = e_addressbook_view_get_shell_view (view); + shell_window = e_shell_view_get_shell_window (shell_view); - g_list_free (p); - } + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); - return category_list; + e_error_run ( + GTK_WINDOW (shell_window), + "addressbook:backend-died", + e_book_get_uri (book), NULL); } static void @@ -1626,78 +1038,27 @@ e_contact_print_button (EPrintable *printable, GtkPrintOperationAction action) } void -eab_view_show_contact_preview (EABView *view, gboolean show) +e_addressbook_view_print (EAddressbookView *view, + GtkPrintOperationAction action) { - g_return_if_fail (view && E_IS_ADDRESSBOOK_VIEW (view)); + GalView *gal_view; + GalViewInstance *view_instance; - if (show) - gtk_widget_show (view->contact_display_window); - else - gtk_widget_hide (view->contact_display_window); -} - -void -eab_view_setup_menus (EABView *view, - BonoboUIComponent *uic) -{ - - g_return_if_fail (view != NULL); g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - g_return_if_fail (uic != NULL); - g_return_if_fail (BONOBO_IS_UI_COMPONENT (uic)); - - init_collection (); - view->uic = uic; + view_instance = e_addressbook_view_get_view_instance (view); + gal_view = gal_view_instance_get_current_view (view_instance); - setup_menus (view); - - /* XXX toshok - yeah this really doesn't belong here, but it - needs to happen at the same time and takes the uic */ - e_search_bar_set_ui_component ( (ESearchBar *)view->search, uic); -} - -/** - * eab_view_discard_menus: - * @view: An addressbook view. - * - * Makes an addressbook view discard its GAL view menus and its views instance - * objects. This should be called when the corresponding Bonobo component is - * deactivated. - **/ -void -eab_view_discard_menus (EABView *view) -{ - g_return_if_fail (view != NULL); - g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - - if (view->view_menus) { - gal_view_menus_unmerge (view->view_menus, NULL); - - g_object_unref (view->view_menus); - view->view_menus = NULL; - } - - if (view->view_instance) { - g_object_unref (view->view_instance); - view->view_instance = NULL; - } - - view->uic = NULL; -} - -void -eab_view_print (EABView *view, GtkPrintOperationAction action) -{ - if (view->view_type == EAB_VIEW_MINICARD) { + if (GAL_IS_VIEW_MINICARD (gal_view)) { + EAddressbookModel *model; EBook *book; EBookQuery *query; gchar *query_string; GList *contact_list; - g_object_get ( - view->model, "query", &query_string, - "book", &book, NULL); + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); + query_string = e_addressbook_model_get_query (model); if (query_string != NULL) query = e_book_query_from_string (query_string); @@ -1705,7 +1066,7 @@ eab_view_print (EABView *view, GtkPrintOperationAction action) query = NULL; g_free (query_string); - contact_list = get_selected_contacts (view); + contact_list = e_addressbook_view_get_selected (view); e_contact_print (book, query, contact_list, action); g_list_foreach (contact_list, (GFunc) g_object_unref, NULL); g_list_free (contact_list); @@ -1713,11 +1074,11 @@ eab_view_print (EABView *view, GtkPrintOperationAction action) if (query != NULL) e_book_query_unref (query); - } else if (view->view_type == EAB_VIEW_TABLE) { + } else if (GAL_IS_VIEW_ETABLE (gal_view)) { EPrintable *printable; ETable *table; - g_object_get (view->widget, "table", &table, NULL); + g_object_get (view->priv->widget, "table", &table, NULL); printable = e_table_get_printable (table); g_object_ref_sink (printable); g_object_unref (table); @@ -1731,7 +1092,8 @@ eab_view_print (EABView *view, GtkPrintOperationAction action) /* callback function to handle removal of contacts for * which a user doesnt have write permission */ -static void delete_contacts_cb (EBook *book, EBookStatus status, gpointer closure) +static void +delete_contacts_cb (EBook *book, EBookStatus status, gpointer closure) { switch(status) { case E_BOOK_ERROR_OK : @@ -1747,19 +1109,85 @@ static void delete_contacts_cb (EBook *book, EBookStatus status, gpointer clos } } +static gboolean +addressbook_view_confirm_delete (GtkWindow *parent, + gboolean plural, + gboolean is_list, + const gchar *name) +{ + GtkWidget *dialog; + gchar *message; + gint response; + + if (is_list) { + if (plural) { + message = g_strdup ( + _("Are you sure you want to " + "delete these contact lists?")); + } else if (name == NULL) { + message = g_strdup ( + _("Are you sure you want to " + "delete this contact list?")); + } else { + message = g_strdup_printf ( + _("Are you sure you want to delete " + "this contact list (%s)?"), name); + } + } else { + if (plural) { + message = g_strdup ( + _("Are you sure you want to " + "delete these contacts?")); + } else if (name == NULL) { + message = g_strdup ( + _("Are you sure you want to " + "delete this contact?")); + } else { + message = g_strdup_printf ( + _("Are you sure you want to delete " + "this contact (%s)?"), name); + } + } + + dialog = gtk_message_dialog_new ( + parent, 0, GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, "%s", message); + gtk_dialog_add_buttons ( + GTK_DIALOG (dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT, + NULL); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + g_free (message); + + return (response == GTK_RESPONSE_ACCEPT); +} + void -eab_view_delete_selection(EABView *view, gboolean is_delete) +e_addressbook_view_delete_selection(EAddressbookView *view, gboolean is_delete) { GList *list, *l; gboolean plural = FALSE, is_list = FALSE; EContact *contact; ETable *etable = NULL; + EAddressbookModel *model; + EBook *book; EMinicardView *card_view; ESelectionModel *selection_model = NULL; + GalViewInstance *view_instance; + GalView *gal_view; char *name = NULL; gint row = 0, select; - list = get_selected_contacts (view); + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); + + view_instance = e_addressbook_view_get_view_instance (view); + gal_view = gal_view_instance_get_current_view (view_instance); + + list = e_addressbook_view_get_selected (view); contact = list->data; if (g_list_next(list)) @@ -1770,28 +1198,29 @@ eab_view_delete_selection(EABView *view, gboolean is_delete) if (e_contact_get (contact, E_CONTACT_IS_LIST)) is_list = TRUE; - if (view->view_type == EAB_VIEW_MINICARD) { - card_view = e_minicard_view_widget_get_view (E_MINICARD_VIEW_WIDGET(view->object)); - selection_model = get_selection_model (view); + if (GAL_IS_VIEW_MINICARD (gal_view)) { + card_view = e_minicard_view_widget_get_view (E_MINICARD_VIEW_WIDGET(view->priv->object)); + selection_model = e_addressbook_view_get_selection_model (view); row = e_selection_model_cursor_row (selection_model); } - else if (view->view_type == EAB_VIEW_TABLE) { - etable = e_table_scrolled_get_table(E_TABLE_SCROLLED(view->widget)); + else if (GAL_IS_VIEW_ETABLE (gal_view)) { + etable = e_table_scrolled_get_table ( + E_TABLE_SCROLLED(view->priv->widget)); row = e_table_get_cursor_row (E_TABLE (etable)); } /* confirm delete */ - if (is_delete && - !eab_editor_confirm_delete(GTK_WINDOW(gtk_widget_get_toplevel(view->widget)), - plural, is_list, name)) { + if (is_delete && !addressbook_view_confirm_delete ( + GTK_WINDOW (gtk_widget_get_toplevel ( + view->priv->widget)), plural, is_list, name)) { g_free (name); g_list_foreach (list, (GFunc) g_object_unref, NULL); g_list_free (list); return; } - if (e_book_check_static_capability (view->book, "bulk-remove")) { + if (e_book_check_static_capability (book, "bulk-remove")) { GList *ids = NULL; for (l=list;l;l=g_list_next(l)) { @@ -1801,7 +1230,7 @@ eab_view_delete_selection(EABView *view, gboolean is_delete) } /* Remove the cards all at once. */ - e_book_async_remove_contacts (view->book, + e_book_async_remove_contacts (book, ids, delete_contacts_cb, NULL); @@ -1812,7 +1241,7 @@ eab_view_delete_selection(EABView *view, gboolean is_delete) for (l=list;l;l=g_list_next(l)) { contact = l->data; /* Remove the card. */ - e_book_async_remove_contact (view->book, + e_book_async_remove_contact (book, contact, delete_contacts_cb, NULL); @@ -1820,7 +1249,7 @@ eab_view_delete_selection(EABView *view, gboolean is_delete) } /* Sets the cursor, at the row after the deleted row */ - if (view->view_type == EAB_VIEW_MINICARD && row!=0) { + if (GAL_IS_VIEW_MINICARD (gal_view) && row != 0) { select = e_sorter_model_to_sorted (selection_model->sorter, row); /* Sets the cursor, before the deleted row if its the last row */ @@ -1834,7 +1263,7 @@ eab_view_delete_selection(EABView *view, gboolean is_delete) } /* Sets the cursor, at the row after the deleted row */ - else if (view->view_type == EAB_VIEW_TABLE && row!=0) { + else if (GAL_IS_VIEW_ETABLE (gal_view) && row != 0) { select = e_table_model_to_view_row (E_TABLE (etable), row); /* Sets the cursor, before the deleted row if its the last row */ @@ -1850,234 +1279,149 @@ eab_view_delete_selection(EABView *view, gboolean is_delete) g_list_free (list); } -static void -invisible_destroyed (gpointer data, GObject *where_object_was) -{ - EABView *view = data; - view->invisible = NULL; -} - -static void -selection_get (GtkWidget *invisible, - GtkSelectionData *selection_data, - guint info, - guint time_stamp, - EABView *view) -{ - char *value; - - value = eab_contact_list_to_string (view->clipboard_contacts); - - gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING, - 8, (guchar *)value, strlen (value)); - g_free (value); -} - -static void -selection_clear_event (GtkWidget *invisible, - GdkEventSelection *event, - EABView *view) +void +e_addressbook_view_save_as (EAddressbookView *view, + gboolean all) { - if (view->clipboard_contacts) { - g_list_foreach (view->clipboard_contacts, (GFunc)g_object_unref, NULL); - g_list_free (view->clipboard_contacts); - view->clipboard_contacts = NULL; - } -} + GList *list = NULL; + EBook *book; -static void -selection_received (GtkWidget *invisible, - GtkSelectionData *selection_data, - guint time, - EABView *view) -{ - if (selection_data->length <= 0 || selection_data->type != GDK_SELECTION_TYPE_STRING) { - return; - } else { - GList *contact_list; - GList *l; - char *str = NULL; + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - if (selection_data->data [selection_data->length - 1] != 0) { - str = g_malloc0 (selection_data->length + 1); - memcpy (str, selection_data->data, selection_data->length); - contact_list = eab_contact_list_from_string (str); - } else - contact_list = eab_contact_list_from_string ((char *)selection_data->data); + book = e_addressbook_model_get_book (view->priv->model); - for (l = contact_list; l; l = l->next) { - EContact *contact = l->data; + if (all) { + EBookQuery *query; - /* XXX NULL for a callback /sigh */ - eab_merging_book_add_contact (view->book, contact, NULL /* XXX */, NULL); - } + query = e_book_query_any_field_contains (""); + e_book_get_contacts (book, query, &list, NULL); + e_book_query_unref (query); + } else + list = e_addressbook_view_get_selected (view); - g_list_foreach (contact_list, (GFunc)g_object_unref, NULL); - g_list_free (contact_list); - g_free (str); + if (list != NULL) { + eab_contact_list_save (_("Save as vCard..."), list, NULL); + g_list_foreach (list, (GFunc) g_object_unref, NULL); + g_list_free (list); } } -static void -add_to_list (int model_row, gpointer closure) -{ - GList **list = closure; - *list = g_list_prepend (*list, GINT_TO_POINTER (model_row)); -} - -static GList * -get_selected_contacts (EABView *view) -{ - GList *list; - GList *iterator; - ESelectionModel *selection = get_selection_model (view); - - list = NULL; - e_selection_model_foreach (selection, add_to_list, &list); - - for (iterator = list; iterator; iterator = iterator->next) { - iterator->data = eab_model_get_contact (view->model, GPOINTER_TO_INT (iterator->data)); - } - list = g_list_reverse (list); - return list; -} - void -eab_view_save_as (EABView *view, gboolean all) +e_addressbook_view_view (EAddressbookView *view) { - GList *list = NULL; - EBook *book ; + EAddressbookModel *model; + EBook *book; + GList *list, *iter; + gboolean editable; + gint response; + guint length; - g_object_get(view->model, - "book", &book, - NULL); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - if (all) { - EBookQuery *query = e_book_query_any_field_contains(""); - e_book_get_contacts(book, query, &list, NULL); - e_book_query_unref(query); - } - else { - list = get_selected_contacts(view); + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); + editable = e_addressbook_model_get_editable (model); + + list = e_addressbook_view_get_selected (view); + length = g_list_length (list); + response = GTK_RESPONSE_YES; + + if (length > 5) { + GtkWidget *dialog; + + /* XXX Use e_error_new(). */ + /* XXX Provide a parent window. */ + dialog = gtk_message_dialog_new ( + NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, + _("Opening %d contacts will open %d new windows as " + "well.\nDo you really want to display all of these " + "contacts?"), length, length); + gtk_dialog_add_buttons ( + GTK_DIALOG (dialog), + _("_Don't Display"), GTK_RESPONSE_NO, + _("Display _All Contacts"), GTK_RESPONSE_YES, + NULL); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); } - if (list) - eab_contact_list_save (_("Save as vCard..."), list, NULL); - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); -} -void -eab_view_view (EABView *view) -{ - GList *list = get_selected_contacts (view); - eab_show_multiple_contacts (view->book, list, view->editable); - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); -} + if (response == GTK_RESPONSE_YES) + for (iter = list; iter != NULL; iter = iter->next) + addressbook_view_emit_open_contact ( + view, iter->data, FALSE); -void -eab_view_send (EABView *view) -{ - GList *list = get_selected_contacts (view); - if (list) - eab_send_contact_list (list, EAB_DISPOSITION_AS_ATTACHMENT); g_list_foreach (list, (GFunc) g_object_unref, NULL); g_list_free (list); } void -eab_view_send_to (EABView *view) +e_addressbook_view_cut (EAddressbookView *view) { - GList *list = get_selected_contacts (view); - if (list) - eab_send_contact_list (list, EAB_DISPOSITION_AS_TO); - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); -} + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); -void -eab_view_cut (EABView *view) -{ - eab_view_copy (view); - eab_view_delete_selection (view, FALSE); + e_addressbook_view_copy (view); + e_addressbook_view_delete_selection (view, FALSE); } -static gboolean -contact_display_has_selection (EABContactDisplay *display) +void +e_addressbook_view_copy (EAddressbookView *view) { - gchar *string; - gint selection_length; - gboolean has_selection; - - string = gtk_html_get_selection_html (GTK_HTML (display), &selection_length); - - has_selection = string ? TRUE : FALSE; + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - if (string) - g_free (string); + view->priv->clipboard_contacts = e_addressbook_view_get_selected (view); - return has_selection; + gtk_selection_owner_set ( + view->priv->invisible, + clipboard_atom, GDK_CURRENT_TIME); } void -eab_view_copy (EABView *view) +e_addressbook_view_paste (EAddressbookView *view) { - if (GTK_WIDGET_HAS_FOCUS (view->contact_display) && - contact_display_has_selection (EAB_CONTACT_DISPLAY (view->contact_display))) - { - gtk_html_copy (GTK_HTML (view->contact_display)); - } - else - { - view->clipboard_contacts = get_selected_contacts (view); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - gtk_selection_owner_set (view->invisible, clipboard_atom, GDK_CURRENT_TIME); - } + gtk_selection_convert ( + view->priv->invisible, clipboard_atom, + GDK_SELECTION_TYPE_STRING, GDK_CURRENT_TIME); } void -eab_view_paste (EABView *view) +e_addressbook_view_select_all (EAddressbookView *view) { - gtk_selection_convert (view->invisible, clipboard_atom, - GDK_SELECTION_TYPE_STRING, - GDK_CURRENT_TIME); -} + ESelectionModel *model; -void -eab_view_select_all (EABView *view) -{ - ESelectionModel *model = get_selection_model (view); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); + model = e_addressbook_view_get_selection_model (view); g_return_if_fail (model); e_selection_model_select_all (model); } void -eab_view_show_all(EABView *view) +e_addressbook_view_show_all (EAddressbookView *view) { - g_object_set(view, - "query", NULL, - NULL); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); + + e_addressbook_model_set_query (view->priv->model, ""); } void -eab_view_stop(EABView *view) +e_addressbook_view_stop (EAddressbookView *view) { - if (view) - eab_model_stop (view->model); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); + + e_addressbook_model_stop (view->priv->model); } static void -view_transfer_contacts (EABView *view, gboolean delete_from_source, gboolean all) +view_transfer_contacts (EAddressbookView *view, gboolean delete_from_source, gboolean all) { EBook *book; GList *contacts = NULL; GtkWindow *parent_window; - g_object_get(view->model, - "book", &book, - NULL); + book = e_addressbook_model_get_book (view->priv->model); if (all) { EBookQuery *query = e_book_query_any_field_contains(""); @@ -2085,7 +1429,7 @@ view_transfer_contacts (EABView *view, gboolean delete_from_source, gboolean all e_book_query_unref(query); } else { - contacts = get_selected_contacts (view); + contacts = e_addressbook_view_get_selected (view); } parent_window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))); @@ -2094,132 +1438,13 @@ view_transfer_contacts (EABView *view, gboolean delete_from_source, gboolean all } void -eab_view_copy_to_folder (EABView *view, gboolean all) +e_addressbook_view_copy_to_folder (EAddressbookView *view, gboolean all) { view_transfer_contacts (view, FALSE, all); } void -eab_view_move_to_folder (EABView *view, gboolean all) +e_addressbook_view_move_to_folder (EAddressbookView *view, gboolean all) { view_transfer_contacts (view, TRUE, all); } - - -static gboolean -eab_view_selection_nonempty (EABView *view) -{ - ESelectionModel *selection_model; - - selection_model = get_selection_model (view); - if (selection_model == NULL) - return FALSE; - - return e_selection_model_selected_count (selection_model) != 0; -} - -gboolean -eab_view_can_create (EABView *view) -{ - return view ? eab_model_editable (view->model) : FALSE; -} - -gboolean -eab_view_can_print (EABView *view) -{ - return view && view->model ? eab_model_contact_count (view->model) : FALSE; -} - -gboolean -eab_view_can_save_as (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) : FALSE; -} - -gboolean -eab_view_can_view (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) : FALSE; -} - -gboolean -eab_view_can_send (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) : FALSE; -} - -gboolean -eab_view_can_send_to (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) : FALSE; -} - -gboolean -eab_view_can_delete (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) && eab_model_editable (view->model) : FALSE; -} - -gboolean -eab_view_can_cut (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) && eab_model_editable (view->model) : FALSE; -} - -gboolean -eab_view_can_copy (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) : FALSE; -} - -gboolean -eab_view_can_paste (EABView *view) -{ - return view ? eab_model_editable (view->model) : FALSE; -} - -gboolean -eab_view_can_select_all (EABView *view) -{ - return view ? eab_model_contact_count (view->model) != 0 : FALSE; -} - -gboolean -eab_view_can_stop (EABView *view) -{ - return view ? eab_model_can_stop (view->model) : FALSE; -} - -gboolean -eab_view_can_copy_to_folder (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) : FALSE; -} - -gboolean -eab_view_can_move_to_folder (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) && eab_model_editable (view->model) : FALSE; -} - -EABMenuTargetSelect * -eab_view_get_menu_target (EABView *view, EABMenu *menu) -{ - GPtrArray *cards = g_ptr_array_new(); - ESelectionModel *selection_model; - EABMenuTargetSelect *t; - - selection_model = get_selection_model (view); - if (selection_model) { - ContactAndBook cab; - - cab.view = view; - cab.closure = cards; - e_selection_model_foreach(selection_model, get_card_1, &cab); - } - - t = eab_menu_target_new_select(menu, view->book, !eab_model_editable(view->model), cards); - t->target.widget = (GtkWidget *)view; - - return t; -} diff --git a/addressbook/gui/widgets/e-addressbook-view.h b/addressbook/gui/widgets/e-addressbook-view.h index c9ac35d2fa..4e4e7c8178 100644 --- a/addressbook/gui/widgets/e-addressbook-view.h +++ b/addressbook/gui/widgets/e-addressbook-view.h @@ -20,145 +20,105 @@ * */ -#ifndef __EAB_VIEW_H__ -#define __EAB_VIEW_H__ +#ifndef E_ADDRESSBOOK_VIEW_H +#define E_ADDRESSBOOK_VIEW_H -#include <gtk/gtk.h> -#include <bonobo/bonobo-ui-component.h> -#include <widgets/menus/gal-view-instance.h> +#include <e-shell-view.h> #include <libebook/e-book.h> +#include <libebook/e-contact.h> +#include <widgets/menus/gal-view-instance.h> +#include <widgets/misc/e-selection-model.h> + #include "e-addressbook-model.h" #include "eab-contact-display.h" -#include "widgets/menus/gal-view-menus.h" -#include "misc/e-search-bar.h" -#include "misc/e-filter-bar.h" - -G_BEGIN_DECLS - -struct _EABMenu; -struct _EABMenuTargetSelect; - -/* EABView - A card displaying information about a contact. - * - * The following arguments are available: - * - * name type read/write description - * -------------------------------------------------------------------------------- - */ - -#define E_TYPE_AB_VIEW (eab_view_get_type ()) -#define EAB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_AB_VIEW, EABView)) -#define EAB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_AB_VIEW, EABViewClass)) -#define E_IS_ADDRESSBOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_AB_VIEW)) -#define E_IS_ADDRESSBOOK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_AB_VIEW)) -typedef enum { - EAB_VIEW_NONE, /* initialized to this */ - EAB_VIEW_MINICARD, - EAB_VIEW_TABLE, -} EABViewType; +/* Standard GObject macros */ +#define E_TYPE_ADDRESSBOOK_VIEW \ + (e_addressbook_view_get_type ()) +#define E_ADDRESSBOOK_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW, EAddressbookView)) +#define E_ADDRESSBOOK_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ADDRESSBOOK_VIEW, EAddressbookViewClass)) +#define E_IS_ADDRESSBOOK_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW)) +#define E_IS_ADDRESSBOOK_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW)) +#define E_ADDRESSBOOK_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW, EAddressbookViewClass)) +G_BEGIN_DECLS -typedef struct _EABView EABView; -typedef struct _EABViewClass EABViewClass; +typedef struct _EAddressbookView EAddressbookView; +typedef struct _EAddressbookViewClass EAddressbookViewClass; +typedef struct _EAddressbookViewPrivate EAddressbookViewPrivate; -struct _EABView -{ +struct _EAddressbookView { GtkVBox parent; - - /* item specific fields */ - EABViewType view_type; - - EABModel *model; - - GtkWidget *invisible; - GList *clipboard_contacts; - - EBook *book; - ESource *source; - char *query; - guint editable : 1; - - gint displayed_contact; - - GObject *object; - GtkWidget *widget; - - GtkWidget *contact_display_window; - GtkWidget *contact_display; - GtkWidget *paned; - - /* Menus handler and the view instance */ - GalViewInstance *view_instance; - GalViewMenus *view_menus; - GalView *current_view; - BonoboUIComponent *uic; - - /* the search bar and related machinery */ - EFilterBar *search; - gint ecml_changed_id; - RuleContext *search_context; - FilterRule *search_rule; + EAddressbookViewPrivate *priv; }; -struct _EABViewClass -{ +struct _EAddressbookViewClass { GtkVBoxClass parent_class; - /* - * Signals - */ - void (*status_message) (EABView *view, const gchar *message); - void (*search_result) (EABView *view, EBookViewStatus status); - void (*folder_bar_message) (EABView *view, const gchar *message); - void (*command_state_change) (EABView *view); + /* Signals */ + void (*open_contact) (EAddressbookView *view, + EContact *contact, + gboolean is_new_contact); + void (*popup_event) (EAddressbookView *view, + GdkEvent *event); + void (*status_message) (EAddressbookView *view, + const gchar *message); + void (*command_state_change) (EAddressbookView *view); + void (*selection_change) (EAddressbookView *view); }; -GtkWidget *eab_view_new (void); -GType eab_view_get_type (void); - -void eab_view_show_contact_preview (EABView *view, gboolean show); - -void eab_view_setup_menus (EABView *view, - BonoboUIComponent *uic); -void eab_view_discard_menus (EABView *view); - -RuleContext *eab_view_peek_search_context (EABView *view); -FilterRule *eab_view_peek_search_rule (EABView *view); - -void eab_view_save_as (EABView *view, gboolean all); -void eab_view_view (EABView *view); -void eab_view_send (EABView *view); -void eab_view_send_to (EABView *view); -void eab_view_print (EABView *view, - GtkPrintOperationAction action); -void eab_view_delete_selection (EABView *view, gboolean is_delete); -void eab_view_cut (EABView *view); -void eab_view_copy (EABView *view); -void eab_view_paste (EABView *view); -void eab_view_select_all (EABView *view); -void eab_view_show_all (EABView *view); -void eab_view_stop (EABView *view); -void eab_view_copy_to_folder (EABView *view, gboolean all); -void eab_view_move_to_folder (EABView *view, gboolean all); - -gboolean eab_view_can_create (EABView *view); -gboolean eab_view_can_print (EABView *view); -gboolean eab_view_can_save_as (EABView *view); -gboolean eab_view_can_view (EABView *view); -gboolean eab_view_can_send (EABView *view); -gboolean eab_view_can_send_to (EABView *view); -gboolean eab_view_can_delete (EABView *view); -gboolean eab_view_can_cut (EABView *view); -gboolean eab_view_can_copy (EABView *view); -gboolean eab_view_can_paste (EABView *view); -gboolean eab_view_can_select_all (EABView *view); -gboolean eab_view_can_stop (EABView *view); -gboolean eab_view_can_copy_to_folder (EABView *view); -gboolean eab_view_can_move_to_folder (EABView *view); - -struct _EABMenuTargetSelect *eab_view_get_menu_target (EABView *view, struct _EABMenu *menu); +GType e_addressbook_view_get_type (void); +GtkWidget * e_addressbook_view_new (EShellView *shell_view, + ESource *source); +EAddressbookModel * + e_addressbook_view_get_model (EAddressbookView *view); +GalViewInstance * + e_addressbook_view_get_view_instance + (EAddressbookView *view); +GObject * e_addressbook_view_get_view_object + (EAddressbookView *view); +GtkWidget * e_addressbook_view_get_view_widget + (EAddressbookView *view); +GList * e_addressbook_view_get_selected (EAddressbookView *view); +ESelectionModel * + e_addressbook_view_get_selection_model + (EAddressbookView *view); +EShellView * e_addressbook_view_get_shell_view + (EAddressbookView *view); +ESource * e_addressbook_view_get_source (EAddressbookView *view); +void e_addressbook_view_save_as (EAddressbookView *view, + gboolean all); +void e_addressbook_view_view (EAddressbookView *view); +void e_addressbook_view_print (EAddressbookView *view, + GtkPrintOperationAction action); +void e_addressbook_view_delete_selection + (EAddressbookView *view, + gboolean is_delete); +void e_addressbook_view_cut (EAddressbookView *view); +void e_addressbook_view_copy (EAddressbookView *view); +void e_addressbook_view_paste (EAddressbookView *view); +void e_addressbook_view_select_all (EAddressbookView *view); +void e_addressbook_view_show_all (EAddressbookView *view); +void e_addressbook_view_stop (EAddressbookView *view); +void e_addressbook_view_copy_to_folder + (EAddressbookView *view, + gboolean all); +void e_addressbook_view_move_to_folder + (EAddressbookView *view, + gboolean all); + +gboolean e_addressbook_view_can_create (EAddressbookView *view); G_END_DECLS -#endif /* __EAB_VIEW_H__ */ +#endif /* E_ADDRESSBOOK_VIEW_H */ diff --git a/addressbook/gui/widgets/e-minicard-view-widget.c b/addressbook/gui/widgets/e-minicard-view-widget.c index 0f9ae7c143..3ad49cf2b3 100644 --- a/addressbook/gui/widgets/e-minicard-view-widget.c +++ b/addressbook/gui/widgets/e-minicard-view-widget.c @@ -53,6 +53,8 @@ enum { }; enum { + CREATE_CONTACT, + CREATE_CONTACT_LIST, SELECTION_CHANGE, COLUMN_WIDTH_CHANGED, RIGHT_CLICK, @@ -140,6 +142,24 @@ e_minicard_view_widget_class_init (EMinicardViewWidgetClass *class) 0.0, G_MAXDOUBLE, 150.0, G_PARAM_READWRITE)); + signals [CREATE_CONTACT] = + g_signal_new ("create-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardViewWidgetClass, create_contact), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals [CREATE_CONTACT_LIST] = + g_signal_new ("create-contact-list", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardViewWidgetClass, create_contact_list), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals [SELECTION_CHANGE] = g_signal_new ("selection_change", G_OBJECT_CLASS_TYPE (object_class), @@ -315,6 +335,18 @@ column_width_changed (ESelectionModel *esm, double width, EMinicardViewWidget *w signals [COLUMN_WIDTH_CHANGED], 0, width); } +static void +create_contact (EMinicardView *view, EMinicardViewWidget *widget) +{ + g_signal_emit (widget, signals[CREATE_CONTACT], 0); +} + +static void +create_contact_list (EMinicardView *view, EMinicardViewWidget *widget) +{ + g_signal_emit (widget, signals[CREATE_CONTACT_LIST], 0); +} + static guint right_click (EMinicardView *view, GdkEvent *event, EMinicardViewWidget *widget) { @@ -370,6 +402,12 @@ e_minicard_view_widget_realize (GtkWidget *widget) "column_width_changed", G_CALLBACK (column_width_changed), view); g_signal_connect (view->emv, + "create-contact", + G_CALLBACK (create_contact), view); + g_signal_connect (view->emv, + "create-contact-list", + G_CALLBACK (create_contact_list), view); + g_signal_connect (view->emv, "right_click", G_CALLBACK (right_click), view); diff --git a/addressbook/gui/widgets/e-minicard-view-widget.h b/addressbook/gui/widgets/e-minicard-view-widget.h index 1c4323523f..917d1b588a 100644 --- a/addressbook/gui/widgets/e-minicard-view-widget.h +++ b/addressbook/gui/widgets/e-minicard-view-widget.h @@ -58,6 +58,8 @@ struct _EMinicardViewWidget struct _EMinicardViewWidgetClass { ECanvasClass parent_class; + void (*create_contact) (EMinicardViewWidget *emvw); + void (*create_contact_list) (EMinicardViewWidget *emvw); void (*selection_change) (EMinicardViewWidget *emvw); void (*column_width_changed) (EMinicardViewWidget *emvw, double width); guint (*right_click) (EMinicardViewWidget *emvw); diff --git a/addressbook/gui/widgets/e-minicard-view.c b/addressbook/gui/widgets/e-minicard-view.c index ccf3ecc6f9..32957fdf33 100644 --- a/addressbook/gui/widgets/e-minicard-view.c +++ b/addressbook/gui/widgets/e-minicard-view.c @@ -33,6 +33,7 @@ #include <misc/e-canvas.h> #include <glib/gi18n.h> #include <string.h> +#include "e-util/e-util.h" #include "a11y/addressbook/ea-addressbook.h" static void e_minicard_view_drag_data_get(GtkWidget *widget, @@ -56,6 +57,8 @@ enum { enum { + CREATE_CONTACT, + CREATE_CONTACT_LIST, RIGHT_CLICK, LAST_SIGNAL }; @@ -160,7 +163,7 @@ set_empty_message (EMinicardView *view) EBook *book; if (view->adapter) { - EABModel *model = NULL; + EAddressbookModel *model = NULL; g_object_get (view->adapter, "editable", &editable, @@ -171,7 +174,7 @@ set_empty_message (EMinicardView *view) if (!e_book_check_static_capability (book, "do-initial-query")) perform_initial_query = TRUE; - searching = model && eab_model_can_stop (model); + searching = model && e_addressbook_model_can_stop (model); } if (searching) { @@ -196,13 +199,13 @@ set_empty_message (EMinicardView *view) } static void -writable_status_change (EABModel *model, gboolean writable, EMinicardView *view) +writable_status_change (EAddressbookModel *model, gboolean writable, EMinicardView *view) { set_empty_message (view); } static void -stop_state_changed (EABModel *model, EMinicardView *view) +stop_state_changed (EAddressbookModel *model, EMinicardView *view) { set_empty_message (view); } @@ -230,7 +233,7 @@ e_minicard_view_set_property (GObject *object, case PROP_ADAPTER: if (view->adapter) { if (view->writable_status_id || view->stop_state_id) { - EABModel *model; + EAddressbookModel *model; g_object_get (view->adapter, "model", &model, NULL); @@ -253,7 +256,7 @@ e_minicard_view_set_property (GObject *object, "model", view->adapter, NULL); if (view->adapter) { - EABModel *model; + EAddressbookModel *model; g_object_get (view->adapter, "model", &model, NULL); @@ -338,7 +341,7 @@ e_minicard_view_dispose (GObject *object) if (view->adapter) { if (view->writable_status_id || view->stop_state_id) { - EABModel *model; + EAddressbookModel *model; g_object_get (view->adapter, "model", &model, NULL); @@ -383,13 +386,8 @@ e_minicard_view_event (GnomeCanvasItem *item, GdkEvent *event) g_object_get(view->adapter, "editable", &editable, NULL); - if (editable) { - EBook *book; - g_object_get(view, "book", &book, NULL); - - if (book && E_IS_BOOK (book)) - eab_show_contact_editor (book, e_contact_new(), TRUE, editable); - } + if (editable) + e_minicard_view_create_contact (view); return TRUE; } case GDK_BUTTON_PRESS: @@ -547,6 +545,22 @@ e_minicard_view_class_init (EMinicardViewClass *klass) FALSE, G_PARAM_READWRITE)); + signals [CREATE_CONTACT] = + g_signal_new ("create-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals [CREATE_CONTACT_LIST] = + g_signal_new ("create-contact-list", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals [RIGHT_CLICK] = g_signal_new ("right_click", G_OBJECT_CLASS_TYPE (object_class), @@ -655,3 +669,19 @@ e_minicard_view_get_card_list (EMinicardView *view) mal.list = g_list_reverse (mal.list); return mal.list; } + +void +e_minicard_view_create_contact (EMinicardView *view) +{ + g_return_if_fail (E_IS_MINICARD_VIEW (view)); + + g_signal_emit (view, signals[CREATE_CONTACT], 0); +} + +void +e_minicard_view_create_contact_list (EMinicardView *view) +{ + g_return_if_fail (E_IS_MINICARD_VIEW (view)); + + g_signal_emit (view, signals[CREATE_CONTACT_LIST], 0); +} diff --git a/addressbook/gui/widgets/e-minicard-view.h b/addressbook/gui/widgets/e-minicard-view.h index 7d0a5b1842..4cdf9be7be 100644 --- a/addressbook/gui/widgets/e-minicard-view.h +++ b/addressbook/gui/widgets/e-minicard-view.h @@ -91,6 +91,8 @@ void e_minicard_view_remove_selection (EMinicardView *view, void e_minicard_view_jump_to_letter (EMinicardView *view, gunichar letter); GList *e_minicard_view_get_card_list (EMinicardView *view); +void e_minicard_view_create_contact (EMinicardView *view); +void e_minicard_view_create_contact_list (EMinicardView *view); G_END_DECLS diff --git a/addressbook/gui/widgets/e-minicard.c b/addressbook/gui/widgets/e-minicard.c index cbbcc80d5c..3e5e8ec3bf 100644 --- a/addressbook/gui/widgets/e-minicard.c +++ b/addressbook/gui/widgets/e-minicard.c @@ -35,7 +35,6 @@ #include "e-minicard.h" #include "e-minicard-label.h" #include "e-minicard-view.h" -#include "e-contact-editor.h" #include <e-util/e-html-utils.h> #include <e-util/e-icon-factory.h> #include <libebook/e-destination.h> @@ -86,6 +85,7 @@ enum { enum { SELECTED, DRAG_BEGIN, + OPEN_CONTACT, STYLE_SET, LAST_SIGNAL }; @@ -101,7 +101,7 @@ common_location [] = { "OTHER", N_ ("Other Email") } }; -static guint e_minicard_signals [LAST_SIGNAL] = {0, }; +static guint signals [LAST_SIGNAL] = {0, }; GType e_minicard_get_type (void) @@ -200,7 +200,7 @@ e_minicard_class_init (EMinicardClass *class) E_TYPE_CONTACT, G_PARAM_READWRITE)); - e_minicard_signals [SELECTED] = + signals [SELECTED] = g_signal_new ("selected", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, @@ -209,7 +209,7 @@ e_minicard_class_init (EMinicardClass *class) e_marshal_INT__POINTER, G_TYPE_INT, 1, G_TYPE_POINTER); - e_minicard_signals [DRAG_BEGIN] = + signals [DRAG_BEGIN] = g_signal_new ("drag_begin", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, @@ -218,7 +218,17 @@ e_minicard_class_init (EMinicardClass *class) e_marshal_INT__POINTER, G_TYPE_INT, 1, G_TYPE_POINTER); - e_minicard_signals [STYLE_SET] = + signals [OPEN_CONTACT] = + g_signal_new ("open-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardClass, open_contact), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CONTACT); + + signals [STYLE_SET] = g_signal_new ("style_set", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, @@ -249,8 +259,6 @@ e_minicard_init (EMinicard *minicard) minicard->list_icon_pixbuf = e_icon_factory_get_icon (LIST_ICON_NAME, E_ICON_SIZE_MENU); minicard->list_icon_size = gdk_pixbuf_get_height (minicard->list_icon_pixbuf); - minicard->editor = NULL; - minicard->changed = FALSE; e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(minicard), e_minicard_reflow); @@ -528,50 +536,12 @@ e_minicard_unrealize (GnomeCanvasItem *item) (* GNOME_CANVAS_ITEM_CLASS(parent_class)->unrealize) (item); } -/* Callback used when the contact editor is closed */ -static void -editor_closed_cb (GtkObject *editor, gpointer data) -{ - EMinicard *minicard = data; - g_object_unref (editor); - minicard->editor = NULL; -} - -gboolean -e_minicard_activate_editor(EMinicard *minicard) +void +e_minicard_activate_editor (EMinicard *minicard) { - GnomeCanvasItem *item = (GnomeCanvasItem *)minicard; - - if (minicard->editor) { - eab_editor_raise (minicard->editor); - } - else { - EBook *book = NULL; - if (E_IS_MINICARD_VIEW(item->parent)) { - g_object_get(item->parent, "book", &book, NULL); - } - - if (book != NULL) { - if (e_contact_get (minicard->contact, E_CONTACT_IS_LIST)) { - EContactListEditor *editor = eab_show_contact_list_editor (book, minicard->contact, - FALSE, e_book_is_writable (book)); - minicard->editor = EAB_EDITOR (editor); - } - else { - EContactEditor *editor = eab_show_contact_editor (book, minicard->contact, - FALSE, e_book_is_writable (book)); - minicard->editor = EAB_EDITOR (editor); - } - - g_object_ref (minicard->editor); - g_signal_connect (minicard->editor, "editor_closed", - G_CALLBACK (editor_closed_cb), minicard); - - g_object_unref (book); - } - } + g_return_if_fail (E_IS_MINICARD (minicard)); - return TRUE; + g_signal_emit (minicard, signals[OPEN_CONTACT], 0, minicard->contact); } static gboolean @@ -655,7 +625,8 @@ e_minicard_event (GnomeCanvasItem *item, GdkEvent *event) break; case GDK_2BUTTON_PRESS: if (event->button.button == 1 && E_IS_MINICARD_VIEW (item->parent)) { - return e_minicard_activate_editor (e_minicard); + e_minicard_activate_editor (e_minicard); + return TRUE; } break; case GDK_KEY_PRESS: @@ -725,7 +696,8 @@ e_minicard_event (GnomeCanvasItem *item, GdkEvent *event) } else if (event->key.keyval == GDK_Return || event->key.keyval == GDK_KP_Enter) { - return e_minicard_activate_editor (e_minicard); + e_minicard_activate_editor (e_minicard); + return TRUE; } break; default: @@ -1154,7 +1126,7 @@ e_minicard_drag_begin (EMinicard *minicard, GdkEvent *event) gint ret_val = 0; GnomeCanvasItem *parent; g_signal_emit (minicard, - e_minicard_signals[DRAG_BEGIN], 0, + signals[DRAG_BEGIN], 0, event, &ret_val); parent = GNOME_CANVAS_ITEM (minicard)->parent; diff --git a/addressbook/gui/widgets/e-minicard.h b/addressbook/gui/widgets/e-minicard.h index 71c976745f..98a4629ad9 100644 --- a/addressbook/gui/widgets/e-minicard.h +++ b/addressbook/gui/widgets/e-minicard.h @@ -24,7 +24,6 @@ #define __E_MINICARD_H__ #include <gtk/gtk.h> -#include "addressbook/gui/contact-editor/eab-editor.h" #include <libgnomecanvas/gnome-canvas.h> #include <libebook/e-contact.h> @@ -75,8 +74,6 @@ struct _EMinicard GdkPixbuf *list_icon_pixbuf; double list_icon_size; - EABEditor *editor; - GList *fields; /* Of type EMinicardField */ guint needs_remodeling : 1; @@ -105,6 +102,7 @@ struct _EMinicardClass gint (* selected) (EMinicard *minicard, GdkEvent *event); gint (* drag_begin) (EMinicard *minicard, GdkEvent *event); + void (* open_contact) (EMinicard *minicard, EContact *contact); void (* style_set) (EMinicard *minicard, GtkStyle *previous_style); }; @@ -125,7 +123,7 @@ int e_minicard_compare (EMinicard *minicard1, int e_minicard_selected (EMinicard *minicard, GdkEvent *event); -gboolean e_minicard_activate_editor (EMinicard *minicard); +void e_minicard_activate_editor (EMinicard *minicard); #ifdef __cplusplus } diff --git a/addressbook/gui/widgets/eab-contact-display.c b/addressbook/gui/widgets/eab-contact-display.c index 4e7418dc5c..42cc65294f 100644 --- a/addressbook/gui/widgets/eab-contact-display.c +++ b/addressbook/gui/widgets/eab-contact-display.c @@ -25,27 +25,46 @@ #endif #include "eab-contact-display.h" -#include "eab-popup.h" #include "eab-gui-util.h" #include "e-util/e-util.h" #include "e-util/e-html-utils.h" #include "e-util/e-icon-factory.h" +#include "e-util/e-plugin-ui.h" #include <string.h> #include <glib/gi18n.h> #include <gtkhtml/gtkhtml.h> #include <gtkhtml/gtkhtml-stream.h> -#define HANDLE_MAILTO_INTERNALLY 1 +#define EAB_CONTACT_DISPLAY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplayPrivate)) -#define PARENT_TYPE (GTK_TYPE_HTML) +#define HANDLE_MAILTO_INTERNALLY 1 struct _EABContactDisplayPrivate { EContact *contact; + EABContactDisplayMode mode; + GtkUIManager *ui_manager; + GtkActionGroup *email_actions; + GtkActionGroup *uri_actions; GtkWidget *invisible; - char *selection_uri; + + gchar *selected_uri; + gchar *clipboard_uri; +}; + +enum { + PROP_0, + PROP_CONTACT, + PROP_MODE +}; + +enum { + SEND_MESSAGE, + LAST_SIGNAL }; static struct { @@ -77,151 +96,154 @@ common_location [] = #define MAX_COMPACT_IMAGE_DIMENSION 48 -static void -eab_uri_popup_link_open(EPopup *ep, EPopupItem *item, void *data) -{ - EABPopupTargetURI *t = (EABPopupTargetURI *)ep->target; - - /* FIXME Pass a parent window. */ - e_show_uri (NULL, t->uri); -} +static const gchar *ui = +"<ui>" +" <popup>" +" <menuitem action='open-link'/>" +" <menuitem action='copy-link'/>" +" <menuitem action='send-message'/>" +" <menuitem action='copy-address'/>" +" </popup>" +"</ui>"; -static void -eab_uri_popup_email_address_copy(EPopup *ep, EPopupItem *item, void *data) -{ - EABContactDisplay *display = data; - struct _EABContactDisplayPrivate *p = display->priv; - EABPopupTargetURI *t = (EABPopupTargetURI *)ep->target; - const char *url = t->uri; - char *html=NULL; - int i=0; - GList *email_list, *l; - int email_num = atoi (url + strlen ("internal-mailto:")); - - email_list = e_contact_get (p->contact, E_CONTACT_EMAIL); - for (l = email_list; l; l=l->next) { - if(i==email_num) - html = e_text_to_html (l->data, 0); - i++; - } - - g_free(p->selection_uri); - p->selection_uri = g_strdup(html); - g_free (html); - - gtk_selection_owner_set(p->invisible, GDK_SELECTION_PRIMARY, gtk_get_current_event_time()); - gtk_selection_owner_set(p->invisible, GDK_SELECTION_CLIPBOARD, gtk_get_current_event_time()); -} +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; static void -eab_uri_popup_link_copy(EPopup *ep, EPopupItem *pitem, void *data) +action_copy_address_cb (GtkAction *action, + EABContactDisplay *display) { - EABContactDisplay *display = data; - struct _EABContactDisplayPrivate *p = display->priv; - - g_free(p->selection_uri); - p->selection_uri = g_strdup(pitem->user_data); - - gtk_selection_owner_set(p->invisible, GDK_SELECTION_PRIMARY, gtk_get_current_event_time()); - gtk_selection_owner_set(p->invisible, GDK_SELECTION_CLIPBOARD, gtk_get_current_event_time()); + EContact *contact; + GList *list; + const gchar *uri; + gchar *html; + gint index; + + uri = display->priv->selected_uri; + index = atoi (uri + strlen ("internal-mailto:")); + contact = eab_contact_display_get_contact (display); + + list = e_contact_get (contact, E_CONTACT_EMAIL); + html = e_text_to_html (g_list_nth_data (list, index), 0); + g_list_foreach (list, (GFunc) g_free, NULL); + g_list_free (list); + + display->priv->clipboard_uri = html; + display->priv->selected_uri = NULL; + + gtk_selection_owner_set ( + display->priv->invisible, GDK_SELECTION_PRIMARY, + gtk_get_current_event_time ()); + gtk_selection_owner_set ( + display->priv->invisible, GDK_SELECTION_CLIPBOARD, + gtk_get_current_event_time ()); } static void -eab_uri_popup_address_send(EPopup *ep, EPopupItem *item, void *data) +action_copy_link_cb (GtkAction *action, + EABContactDisplay *display) { - EABPopupTargetURI *t = (EABPopupTargetURI *)ep->target; - const char *url = t->uri; - EABContactDisplay *display = data; - struct _EABContactDisplayPrivate *p = display->priv; - - int mail_num = atoi (url + strlen ("internal-mailto:")); - - if (mail_num == -1) - return; - - eab_send_contact (p->contact, mail_num, EAB_DISPOSITION_AS_TO); - + display->priv->clipboard_uri = display->priv->selected_uri; + display->priv->selected_uri = NULL; + + gtk_selection_owner_set ( + display->priv->invisible, GDK_SELECTION_PRIMARY, + gtk_get_current_event_time ()); + gtk_selection_owner_set ( + display->priv->invisible, GDK_SELECTION_CLIPBOARD, + gtk_get_current_event_time ()); } static void -eab_selection_get(GtkWidget *widget, GtkSelectionData *data, guint info, guint time_stamp, EABContactDisplay *display) +action_open_link_cb (GtkAction *action, + EABContactDisplay *display) { - struct _EABContactDisplayPrivate *p = display->priv; - - if (p->selection_uri == NULL) - return; - - gtk_selection_data_set(data, data->target, 8, (guchar *)p->selection_uri, strlen(p->selection_uri)); + /* XXX Pass a parent window. */ + e_show_uri (NULL, display->priv->selected_uri); } static void -eab_selection_clear_event(GtkWidget *widget, GdkEventSelection *event, EABContactDisplay *display) +action_send_message_cb (GtkAction *action, + EABContactDisplay *display) { -#if 0 - struct _EABContactDisplayPrivate *p = display->priv; - - g_free(p->selection_uri); - p->selection_uri = NULL; -#endif + EDestination *destination; + EContact *contact; + const gchar *uri; + gint row; + + uri = display->priv->selected_uri; + row = atoi (uri + strlen ("internal-mailto:")); + g_return_if_fail (row >= 0); + + destination = e_destination_new (); + contact = eab_contact_display_get_contact (display); + e_destination_set_contact (destination, contact, row); + g_signal_emit (display, signals[SEND_MESSAGE], 0, destination); + g_object_unref (destination); } -static EPopupItem eab_uri_popups[] = { - { E_POPUP_ITEM, "05.open", N_("_Open Link in Browser"), eab_uri_popup_link_open, NULL, NULL, EAB_POPUP_URI_NOT_MAILTO }, - { E_POPUP_ITEM, "10.copy", N_("_Copy Link Location"), eab_uri_popup_link_copy, NULL, "edit-copy", EAB_POPUP_URI_NOT_MAILTO }, - { E_POPUP_ITEM, "15.send", N_("_Send New Message To..."), eab_uri_popup_address_send, NULL, "mail-message-new", EAB_POPUP_URI_MAILTO}, - { E_POPUP_ITEM, "20.copy", N_("Copy _Email Address"), eab_uri_popup_email_address_copy, NULL, "edit-copy", EAB_POPUP_URI_MAILTO}, - }; +static GtkActionEntry email_entries[] = { + + { "copy-address", + NULL, + N_("Copy _Email Address"), + NULL, + NULL, + G_CALLBACK (action_copy_address_cb) }, + + { "send-message", + NULL, + N_("_Send New Message To..."), + NULL, + NULL, + G_CALLBACK (action_send_message_cb) } +}; +static GtkActionEntry uri_entries[] = { + + { "copy-link", + NULL, + N_("_Copy Link Location"), + NULL, + NULL, + G_CALLBACK (action_copy_link_cb) }, + + { "open-link", + NULL, + N_("_Open Link in Browser"), + NULL, + NULL, + G_CALLBACK (action_open_link_cb) } +}; static void -eab_uri_popup_free(EPopup *ep, GSList *list, void *data) +contact_display_selection_get (EABContactDisplay *display, + GtkSelectionData *data, + guint info, + guint time_stamp) { - while (list){ - GSList *n = list->next; - struct _EPopupItem *item = list->data; - - g_free(item->user_data); - item->user_data = NULL; - g_slist_free_1(list); + if (display->priv->clipboard_uri == NULL) + return; - list = n; - } + gtk_selection_data_set ( + data, data->target, 8, + (guchar *) display->priv->clipboard_uri, + strlen (display->priv->clipboard_uri)); } -static int -eab_uri_popup_event(EABContactDisplay *display, GdkEvent *event, const char *uri) +static void +contact_display_selection_clear_event (EABContactDisplay *display, + GdkEventSelection *event) { - EABPopup *emp; - EABPopupTargetURI *t ; - GtkMenu *menu; - GSList *menus = NULL; - int i; - - emp = eab_popup_new("org.gnome.evolution.addressbook.contactdisplay.popup"); - - t = eab_popup_target_new_uri(emp, uri); - t->target.widget = (GtkWidget *)display; - - for (i=0;i<sizeof(eab_uri_popups)/sizeof(eab_uri_popups[0]);i++) { - eab_uri_popups[i].user_data = g_strdup(t->uri); - menus = g_slist_prepend(menus, &eab_uri_popups[i]); - } - e_popup_add_items((EPopup *)emp, menus, NULL, eab_uri_popup_free, display); - - menu = e_popup_create_menu_once((EPopup *)emp,(EPopupTarget*)t, 0); - - if (event == NULL) { - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); - } else { - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button.button, event->button.time); - } - - return TRUE; + g_free (display->priv->clipboard_uri); + display->priv->clipboard_uri = NULL; } static void -on_url_requested (GtkHTML *html, const char *url, GtkHTMLStream *handle, - EABContactDisplay *display) +contact_display_on_url_requested (GtkHTML *html, + const gchar *url, + GtkHTMLStream *handle, + EABContactDisplay *display) { if (!strcmp (url, "internal-contact-photo:")) { EContactPhoto *photo; @@ -254,16 +276,25 @@ on_url_requested (GtkHTML *html, const char *url, GtkHTMLStream *handle, } static void -on_link_clicked (GtkHTML *html, const char *uri, EABContactDisplay *display) +contact_display_on_link_clicked (GtkHTML *html, + const gchar *uri, + EABContactDisplay *display) { #ifdef HANDLE_MAILTO_INTERNALLY if (!strncmp (uri, "internal-mailto:", strlen ("internal-mailto:"))) { - int mail_num = atoi (uri + strlen ("internal-mailto:")); + EDestination *destination; + EContact *contact; + gint email_num; - if (mail_num == -1) + email_num = atoi (uri + strlen ("internal-mailto:")); + if (email_num == -1) return; - eab_send_contact (display->priv->contact, mail_num, EAB_DISPOSITION_AS_TO); + destination = e_destination_new (); + contact = eab_contact_display_get_contact (display); + e_destination_set_contact (destination, contact, email_num); + g_signal_emit (display, signals[SEND_MESSAGE], 0, destination); + g_object_unref (destination); return; } @@ -273,44 +304,6 @@ on_link_clicked (GtkHTML *html, const char *uri, EABContactDisplay *display) e_show_uri (NULL, uri); } -#if 0 -static void -render_address (GtkHTMLStream *html_stream, EContact *contact, const char *html_label, EContactField adr_field, EContactField label_field) -{ - EContactAddress *adr; - const char *label; - - label = e_contact_get_const (contact, label_field); - if (label) { - char *html = e_text_to_html (label, E_TEXT_TO_HTML_CONVERT_NL); - - gtk_html_stream_printf (html_stream, "<tr><td valign=\"top\" width=\"" IMAGE_COL_WIDTH "\"></td><td valign=\"top\" width=\"100\"><font color=" HEADER_COLOR ">%s:</font><br><a href=\"http://www.mapquest.com/\">%s</a></td><td valign=\"top\">%s</td></tr>", html_label, _("(map)"), html); - -This shoul g_free (html); - return; - } - - adr = e_contact_get (contact, adr_field); - if (adr && - (adr->po || adr->ext || adr->street || adr->locality || adr->region || adr->code || adr->country)) { - - gtk_html_stream_printf (html_stream, "<tr><td valign=\"top\" width=\"" IMAGE_COL_WIDTH "\"></td><td valign=\"top\" width=\"100\"><font color=" HEADER_COLOR ">%s:</font><br><a href=\"http://www.mapquest.com/\">%s</a></td><td valign=\"top\">", html_label, _("map")); - - if (adr->po && *adr->po) gtk_html_stream_printf (html_stream, "%s<br>", adr->po); - if (adr->ext && *adr->ext) gtk_html_stream_printf (html_stream, "%s<br>", adr->ext); - if (adr->street && *adr->street) gtk_html_stream_printf (html_stream, "%s<br>", adr->street); - if (adr->locality && *adr->locality) gtk_html_stream_printf (html_stream, "%s<br>", adr->locality); - if (adr->region && *adr->region) gtk_html_stream_printf (html_stream, "%s<br>", adr->region); - if (adr->code && *adr->code) gtk_html_stream_printf (html_stream, "%s<br>", adr->code); - if (adr->country && *adr->country) gtk_html_stream_printf (html_stream, "%s<br>", adr->country); - - gtk_html_stream_printf (html_stream, "</td></tr>"); - } - if (adr) - e_contact_address_free (adr); -} -#endif - static void render_name_value (GtkHTMLStream *html_stream, const char *label, const char *str, const char *icon, unsigned int html_flags) { @@ -669,12 +662,6 @@ eab_contact_display_render_normal (EABContactDisplay *display, EContact *contact GtkHTMLStream *html_stream; gboolean is_rtl = (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL); - if (display->priv->contact) - g_object_unref (display->priv->contact); - display->priv->contact = contact; - if (display->priv->contact) - g_object_ref (display->priv->contact); - html_stream = gtk_html_begin (GTK_HTML (display)); gtk_html_stream_write (html_stream, HTML_HEADER, sizeof (HTML_HEADER) - 1); gtk_html_stream_printf (html_stream, "<body><table width=\"100%%\"><tr><td %s>\n", is_rtl ? " align=\"right\" " : ""); @@ -725,16 +712,11 @@ eab_contact_display_render_normal (EABContactDisplay *display, EContact *contact } static void -eab_contact_display_render_compact (EABContactDisplay *display, EContact *contact) +eab_contact_display_render_compact (EABContactDisplay *display, + EContact *contact) { GtkHTMLStream *html_stream; - if (display->priv->contact) - g_object_unref (display->priv->contact); - display->priv->contact = contact; - if (display->priv->contact) - g_object_ref (display->priv->contact); - html_stream = gtk_html_begin (GTK_HTML (display)); gtk_html_stream_write (html_stream, HTML_HEADER, sizeof (HTML_HEADER) - 1); gtk_html_stream_write (html_stream, "<body>\n", 7); @@ -908,98 +890,266 @@ eab_contact_display_render_compact (EABContactDisplay *display, EContact *contac gtk_html_end (GTK_HTML (display), html_stream, GTK_HTML_STREAM_OK); } -void -eab_contact_display_render (EABContactDisplay *display, EContact *contact, - EABContactDisplayRenderMode mode) +static int +contact_display_button_press_event (GtkWidget *widget, + GdkEvent *event, + EABContactDisplay *display) { - switch (mode) { - case EAB_CONTACT_DISPLAY_RENDER_NORMAL: - eab_contact_display_render_normal (display, contact); - break; - case EAB_CONTACT_DISPLAY_RENDER_COMPACT: - eab_contact_display_render_compact (display, contact); - break; + GtkUIManager *ui_manager; + GtkActionGroup *action_group; + GtkWidget *menu; + gboolean has_email; + gchar *uri; + + if (event->button.button != 3) + return FALSE; + + uri = gtk_html_get_url_at ( + GTK_HTML (widget), + event->button.x, event->button.y); + + if (uri == NULL) + return FALSE; + + g_free (display->priv->selected_uri); + display->priv->selected_uri = uri; + + ui_manager = display->priv->ui_manager; + menu = gtk_ui_manager_get_widget (ui_manager, "/popup"); + g_return_val_if_fail (GTK_IS_MENU (menu), FALSE); + + has_email = (g_ascii_strncasecmp (uri, "internal-mailto:", 16) == 0); + + /* Show the appropriate actions. */ + action_group = display->priv->email_actions; + gtk_action_group_set_visible (action_group, has_email); + action_group = display->priv->uri_actions; + gtk_action_group_set_visible (action_group, !has_email); + + if (event != NULL) + gtk_menu_popup ( + GTK_MENU (menu), NULL, NULL, NULL, NULL, + event->button.button, event->button.time); + else + gtk_menu_popup ( + GTK_MENU (menu), NULL, NULL, NULL, NULL, + 0, gtk_get_current_event_time ()); + + return TRUE; +} + +static void +contact_display_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CONTACT: + eab_contact_display_set_contact ( + EAB_CONTACT_DISPLAY (object), + g_value_get_object (value)); + return; + + case PROP_MODE: + eab_contact_display_set_mode ( + EAB_CONTACT_DISPLAY (object), + g_value_get_int (value)); + return; } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } -static int -eab_html_press_event (GtkWidget *widget, GdkEvent *event,EABContactDisplay *display) +static void +contact_display_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - char *uri; - gboolean res = FALSE; + switch (property_id) { + case PROP_CONTACT: + g_value_set_object ( + value, eab_contact_display_get_contact ( + EAB_CONTACT_DISPLAY (object))); + return; + case PROP_MODE: + g_value_set_int ( + value, eab_contact_display_get_mode ( + EAB_CONTACT_DISPLAY (object))); + return; + } - if (event->button.button!= 3 ) - return FALSE; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +contact_display_dispose (GObject *object) +{ + EABContactDisplayPrivate *priv; + + priv = EAB_CONTACT_DISPLAY_GET_PRIVATE (object); + + if (priv->contact != NULL) { + g_object_unref (priv->contact); + priv->contact = NULL; + } + + if (priv->ui_manager != NULL) { + g_object_unref (priv->ui_manager); + priv->ui_manager = NULL; + } + + if (priv->email_actions != NULL) { + g_object_unref (priv->email_actions); + priv->email_actions = NULL; + } - uri = gtk_html_get_url_at (GTK_HTML (widget), event->button.x, event->button.y); - if (uri){ - eab_uri_popup_event(display,event,uri); - } + if (priv->uri_actions != NULL) { + g_object_unref (priv->uri_actions); + priv->uri_actions = NULL; + } - g_free(uri); + if (priv->invisible != NULL) { + g_object_unref (priv->invisible); + priv->invisible = NULL; + } - return res; + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } -GtkWidget* -eab_contact_display_new (void) +static void +contact_display_finalize (GObject *object) { - EABContactDisplay *display; - - struct _EABContactDisplayPrivate *p; - - display = g_object_new (EAB_TYPE_CONTACT_DISPLAY, NULL); - p=display->priv = g_new0 (EABContactDisplayPrivate, 1); - - gtk_html_set_default_content_type (GTK_HTML (display), "text/html; charset=utf-8"); - - gtk_html_set_editable (GTK_HTML (display), FALSE); - - g_signal_connect (display, "url_requested", - G_CALLBACK (on_url_requested), - display); - g_signal_connect (display, "link_clicked", - G_CALLBACK (on_link_clicked), - display); - g_signal_connect(display, "button_press_event", - G_CALLBACK(eab_html_press_event), - display); - p->invisible = gtk_invisible_new(); - g_signal_connect(p->invisible, "selection_get", G_CALLBACK(eab_selection_get), display); - g_signal_connect(p->invisible, "selection_clear_event", G_CALLBACK(eab_selection_clear_event), display); - gtk_selection_add_target(p->invisible, GDK_SELECTION_PRIMARY, GDK_SELECTION_TYPE_STRING, 0); - gtk_selection_add_target(p->invisible, GDK_SELECTION_CLIPBOARD, GDK_SELECTION_TYPE_STRING, 1); - -#if 0 - g_signal_connect (display, "object_requested", - G_CALLBACK (on_object_requested), - mail_display); - g_signal_connect (display, "button_press_event", - G_CALLBACK (html_button_press_event), mail_display); - g_signal_connect (display, "motion_notify_event", - G_CALLBACK (html_motion_notify_event), mail_display); - g_signal_connect (display, "enter_notify_event", - G_CALLBACK (html_enter_notify_event), mail_display); - g_signal_connect (display, "iframe_created", - G_CALLBACK (html_iframe_created), mail_display); - g_signal_connect (display, "on_url", - G_CALLBACK (html_on_url), mail_display); -#endif + EABContactDisplayPrivate *priv; - return GTK_WIDGET (display); + priv = EAB_CONTACT_DISPLAY_GET_PRIVATE (object); + + g_free (priv->selected_uri); + g_free (priv->clipboard_uri); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); } static void -eab_contact_display_init (GObject *object) +eab_contact_display_class_init (EABContactDisplayClass *class) { - gtk_html_construct ((GtkHTML *)object); + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EABContactDisplayPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = contact_display_set_property; + object_class->get_property = contact_display_get_property; + object_class->dispose = contact_display_dispose; + object_class->finalize = contact_display_finalize; + + g_object_class_install_property ( + object_class, + PROP_CONTACT, + g_param_spec_object ( + "contact", + NULL, + NULL, + E_TYPE_CONTACT, + G_PARAM_READWRITE)); + + /* XXX Make this a real enum property. */ + g_object_class_install_property ( + object_class, + PROP_MODE, + g_param_spec_int ( + "mode", + NULL, + NULL, + EAB_CONTACT_DISPLAY_RENDER_NORMAL, + EAB_CONTACT_DISPLAY_RENDER_COMPACT, + EAB_CONTACT_DISPLAY_RENDER_NORMAL, + G_PARAM_READWRITE)); + + signals[SEND_MESSAGE] = g_signal_new ( + "send-message", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EABContactDisplayClass, send_message), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_DESTINATION); } static void -eab_contact_display_class_init (GtkObjectClass *object_class) +eab_contact_display_init (EABContactDisplay *display) { - /* object_class->destroy = mail_display_destroy;*/ + GtkActionGroup *action_group; + GtkHTML *html; + const gchar *id; + + display->priv = EAB_CONTACT_DISPLAY_GET_PRIVATE (display); + display->priv->mode = EAB_CONTACT_DISPLAY_RENDER_NORMAL; + display->priv->ui_manager = gtk_ui_manager_new (); + display->priv->invisible = gtk_invisible_new (); + + g_object_ref_sink (display->priv->invisible); + + action_group = gtk_action_group_new ("email"); + gtk_action_group_set_translation_domain ( + action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions ( + action_group, email_entries, + G_N_ELEMENTS (email_entries), display); + gtk_ui_manager_insert_action_group ( + display->priv->ui_manager, action_group, 0); + display->priv->email_actions = action_group; + + action_group = gtk_action_group_new ("uri"); + gtk_action_group_set_translation_domain ( + action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions ( + action_group, uri_entries, + G_N_ELEMENTS (uri_entries), display); + gtk_ui_manager_insert_action_group ( + display->priv->ui_manager, action_group, 0); + display->priv->uri_actions = action_group; + + gtk_ui_manager_add_ui_from_string ( + display->priv->ui_manager, ui, -1, NULL); + + html = GTK_HTML (display); + gtk_html_construct (html); + gtk_html_set_editable (html, FALSE); + gtk_html_set_default_content_type (html, "text/html; charset=utf-8"); + + g_signal_connect ( + display, "url-requested", + G_CALLBACK (contact_display_on_url_requested), display); + g_signal_connect ( + display, "link-clicked", + G_CALLBACK (contact_display_on_link_clicked), display); + g_signal_connect ( + display, "button-press-event", + G_CALLBACK (contact_display_button_press_event), display); + + g_signal_connect_swapped ( + display->priv->invisible, "selection-get", + G_CALLBACK (contact_display_selection_get), display); + g_signal_connect_swapped ( + display->priv->invisible, "selection-clear-event", + G_CALLBACK (contact_display_selection_clear_event), display); + gtk_selection_add_target ( + display->priv->invisible, + GDK_SELECTION_PRIMARY, GDK_SELECTION_TYPE_STRING, 0); + gtk_selection_add_target ( + display->priv->invisible, + GDK_SELECTION_CLIPBOARD, GDK_SELECTION_TYPE_STRING, 1); + + id = "org.gnome.evolution.contact-display"; + e_plugin_ui_register_manager (display->priv->ui_manager, id, display); + e_plugin_ui_enable_manager (display->priv->ui_manager, id); } GType @@ -1007,21 +1157,98 @@ eab_contact_display_get_type (void) { static GType type = 0; - if (!type) { - static const GTypeInfo info = { + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { sizeof (EABContactDisplayClass), - NULL, /* base_init */ - NULL, /* base_finalize */ + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, (GClassInitFunc) eab_contact_display_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ sizeof (EABContactDisplay), - 0, /* n_preallocs */ + 0, /* n_preallocs */ (GInstanceInitFunc) eab_contact_display_init, + NULL /* value_table */ }; - type = g_type_register_static (PARENT_TYPE, "EABContactDisplay", &info, 0); + type = g_type_register_static ( + GTK_TYPE_HTML, "EABContactDisplay", &type_info, 0); } return type; } + +GtkWidget * +eab_contact_display_new (void) +{ + return g_object_new (EAB_TYPE_CONTACT_DISPLAY, NULL); +} + +EContact * +eab_contact_display_get_contact (EABContactDisplay *display) +{ + g_return_val_if_fail (EAB_IS_CONTACT_DISPLAY (display), NULL); + + return display->priv->contact; +} + +void +eab_contact_display_set_contact (EABContactDisplay *display, + EContact *contact) +{ + EABContactDisplayMode mode; + + g_return_if_fail (EAB_IS_CONTACT_DISPLAY (display)); + + mode = eab_contact_display_get_mode (display); + + if (contact != NULL) + g_object_ref (contact); + if (display->priv->contact != NULL) + g_object_unref (display->priv->contact); + display->priv->contact = contact; + + switch (mode) { + case EAB_CONTACT_DISPLAY_RENDER_NORMAL: + eab_contact_display_render_normal (display, contact); + break; + + case EAB_CONTACT_DISPLAY_RENDER_COMPACT: + eab_contact_display_render_compact (display, contact); + break; + } + + g_object_notify (G_OBJECT (display), "contact"); +} + +EABContactDisplayMode +eab_contact_display_get_mode (EABContactDisplay *display) +{ + g_return_val_if_fail (EAB_IS_CONTACT_DISPLAY (display), 0); + + return display->priv->mode; +} + +void +eab_contact_display_set_mode (EABContactDisplay *display, + EABContactDisplayMode mode) +{ + EContact *contact; + + g_return_if_fail (EAB_IS_CONTACT_DISPLAY (display)); + + display->priv->mode = mode; + contact = eab_contact_display_get_contact (display); + + switch (mode) { + case EAB_CONTACT_DISPLAY_RENDER_NORMAL: + eab_contact_display_render_normal (display, contact); + break; + + case EAB_CONTACT_DISPLAY_RENDER_COMPACT: + eab_contact_display_render_compact (display, contact); + break; + } + + g_object_notify (G_OBJECT (display), "mode"); +} diff --git a/addressbook/gui/widgets/eab-contact-display.h b/addressbook/gui/widgets/eab-contact-display.h index c7b7f1a476..096a910f2f 100644 --- a/addressbook/gui/widgets/eab-contact-display.h +++ b/addressbook/gui/widgets/eab-contact-display.h @@ -20,41 +20,68 @@ * */ -#ifndef _EAB_CONTACT_DISPLAY_H_ -#define _EAB_CONTACT_DISPLAY_H_ +#ifndef EAB_CONTACT_DISPLAY_H +#define EAB_CONTACT_DISPLAY_H #include <gtkhtml/gtkhtml.h> #include <libebook/e-contact.h> +#include <libebook/e-destination.h> -#define EAB_TYPE_CONTACT_DISPLAY (eab_contact_display_get_type ()) -#define EAB_CONTACT_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplay)) -#define EAB_CONTACT_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplayClass)) -#define IS_EAB_CONTACT_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EAB_TYPE_CONTACT_DISPLAY)) -#define IS_EAB_CONTACT_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EAB_TYPE_CONTACT_DISPLAY)) +/* Standard GObject macros */ +#define EAB_TYPE_CONTACT_DISPLAY \ + (eab_contact_display_get_type ()) +#define EAB_CONTACT_DISPLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplay)) +#define EAB_CONTACT_DISPLAY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplayClass)) +#define EAB_IS_CONTACT_DISPLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EAB_TYPE_CONTACT_DISPLAY)) +#define EAB_IS_CONTACT_DISPLAY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EAB_TYPE_CONTACT_DISPLAY)) +#define EAB_CONTACT_DISPLAY_GET_CLASS(obj) \ + (G_TYPE_ISNTANCE_GET_CLASS \ + ((obj), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplayClass)) + +G_BEGIN_DECLS typedef struct _EABContactDisplay EABContactDisplay; -typedef struct _EABContactDisplayPrivate EABContactDisplayPrivate; typedef struct _EABContactDisplayClass EABContactDisplayClass; +typedef struct _EABContactDisplayPrivate EABContactDisplayPrivate; typedef enum { EAB_CONTACT_DISPLAY_RENDER_NORMAL, /* for use in the preview pane */ EAB_CONTACT_DISPLAY_RENDER_COMPACT /* for use with embedded vcards (e.g, the EABVCardControl) */ -} EABContactDisplayRenderMode; +} EABContactDisplayMode; struct _EABContactDisplay { GtkHTML parent; - EABContactDisplayPrivate *priv; }; struct _EABContactDisplayClass { GtkHTMLClass parent_class; + + /* Signals */ + void (*send_message) (EABContactDisplay *display, + EDestination *destination); }; -GType eab_contact_display_get_type (void); -GtkWidget * eab_contact_display_new (void); +GType eab_contact_display_get_type (void); +GtkWidget * eab_contact_display_new (void); + +EContact * eab_contact_display_get_contact (EABContactDisplay *display); +void eab_contact_display_set_contact (EABContactDisplay *display, + EContact *contact); +EABContactDisplayMode + eab_contact_display_get_mode (EABContactDisplay *display); +void eab_contact_display_set_mode (EABContactDisplay *display, + EABContactDisplayMode mode); + -void eab_contact_display_render (EABContactDisplay *display, EContact *contact, - EABContactDisplayRenderMode render_mode); +G_END_DECLS -#endif /* _EAB_CONTACT_DISPLAY_H_ */ +#endif /* EAB_CONTACT_DISPLAY_H */ diff --git a/addressbook/gui/widgets/eab-gui-util.c b/addressbook/gui/widgets/eab-gui-util.c index 168c0bb7fa..9db9630b72 100644 --- a/addressbook/gui/widgets/eab-gui-util.c +++ b/addressbook/gui/widgets/eab-gui-util.c @@ -40,17 +40,11 @@ #include "misc/e-image-chooser.h" #include <e-util/e-icon-factory.h> #include "eab-contact-merging.h" -#include <composer/e-msg-composer.h> -#include <mail/em-composer-utils.h> /* we link to camel for decoding quoted printable email addresses */ #include <camel/camel-mime-utils.h> -#include "addressbook/gui/contact-editor/eab-editor.h" -#include "addressbook/gui/contact-editor/e-contact-editor.h" -#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h" -#include "addressbook/gui/component/addressbook-component.h" -#include "addressbook/gui/component/addressbook.h" +#include "addressbook/util/addressbook.h" /* the NULL's in this table correspond to the status codes that should *never* be generated by a backend */ @@ -201,140 +195,6 @@ eab_prompt_save_dialog (GtkWindow *parent) return e_error_run (parent, "addressbook:prompt-save", NULL); } -static void -added_cb (EBook* book, EBookStatus status, EContact *contact, - gpointer data) -{ - gboolean is_list = GPOINTER_TO_INT (data); - - if (status != E_BOOK_ERROR_OK && status != E_BOOK_ERROR_CANCELLED) { - eab_error_dialog (is_list ? _("Error adding list") : _("Error adding contact"), status); - } -} - -static void -modified_cb (EBook* book, EBookStatus status, EContact *contact, - gpointer data) -{ - gboolean is_list = GPOINTER_TO_INT (data); - - if (status != E_BOOK_ERROR_OK && status != E_BOOK_ERROR_CANCELLED) { - eab_error_dialog (is_list ? _("Error modifying list") : _("Error modifying contact"), - status); - } -} - -static void -deleted_cb (EBook* book, EBookStatus status, EContact *contact, - gpointer data) -{ - gboolean is_list = GPOINTER_TO_INT (data); - - if (status != E_BOOK_ERROR_OK) { - eab_error_dialog (is_list ? _("Error removing list") : _("Error removing contact"), - status); - } -} - -static void -editor_closed_cb (GtkObject *editor, gpointer data) -{ - g_object_unref (editor); -} - -EContactEditor * -eab_show_contact_editor (EBook *book, EContact *contact, - gboolean is_new_contact, - gboolean editable) -{ - EContactEditor *ce; - - ce = e_contact_editor_new (book, contact, is_new_contact, editable); - - g_signal_connect (ce, "contact_added", - G_CALLBACK (added_cb), GINT_TO_POINTER (FALSE)); - g_signal_connect (ce, "contact_modified", - G_CALLBACK (modified_cb), GINT_TO_POINTER (FALSE)); - g_signal_connect (ce, "contact_deleted", - G_CALLBACK (deleted_cb), GINT_TO_POINTER (FALSE)); - g_signal_connect (ce, "editor_closed", - G_CALLBACK (editor_closed_cb), NULL); - - return ce; -} - -EContactListEditor * -eab_show_contact_list_editor (EBook *book, EContact *contact, - gboolean is_new_contact, - gboolean editable) -{ - EContactListEditor *ce; - - ce = e_contact_list_editor_new (book, contact, is_new_contact, editable); - - g_signal_connect (ce, "contact_added", - G_CALLBACK (added_cb), GINT_TO_POINTER (TRUE)); - g_signal_connect (ce, "contact_modified", - G_CALLBACK (modified_cb), GINT_TO_POINTER (TRUE)); - g_signal_connect (ce, "contact_deleted", - G_CALLBACK (deleted_cb), GINT_TO_POINTER (TRUE)); - g_signal_connect (ce, "editor_closed", - G_CALLBACK (editor_closed_cb), GINT_TO_POINTER (TRUE)); - - eab_editor_show (EAB_EDITOR (ce)); - - return ce; -} - -static void -view_contacts (EBook *book, GList *list, gboolean editable) -{ - for (; list; list = list->next) { - EContact *contact = list->data; - if (e_contact_get (contact, E_CONTACT_IS_LIST)) - eab_show_contact_list_editor (book, contact, FALSE, editable); - else - eab_show_contact_editor (book, contact, FALSE, editable); - } -} - -void -eab_show_multiple_contacts (EBook *book, - GList *list, - gboolean editable) -{ - if (list) { - int length = g_list_length (list); - if (length > 5) { - GtkWidget *dialog; - gint response; - - dialog = gtk_message_dialog_new (NULL, - 0, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_NONE, - ngettext("Opening %d contact will open %d new window as well.\n" - "Do you really want to display this contact?", - "Opening %d contacts will open %d new windows as well.\n" - "Do you really want to display all of these contacts?", - length), - length, - length); - gtk_dialog_add_buttons (GTK_DIALOG (dialog), - _("_Don't Display"), GTK_RESPONSE_NO, - _("Display _All Contacts"), GTK_RESPONSE_YES, - NULL); - response = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - if (response == GTK_RESPONSE_YES) - view_contacts (book, list, editable); - } else { - view_contacts (book, list, editable); - } - } -} - - static gint file_exists(GtkWindow *window, const char *filename) { @@ -629,16 +489,6 @@ struct ContactCopyProcess_ { ContactCopyDone done_cb; }; -#if 0 -static void -contact_deleted_cb (EBook* book, EBookStatus status, gpointer user_data) -{ - if (status != E_BOOK_ERROR_OK) { - eab_error_dialog (_("Error removing contact"), status); - } -} -#endif - static void do_delete (gpointer data, gpointer user_data) { @@ -783,232 +633,6 @@ eab_transfer_contacts (EBook *source, GList *contacts /* adopted */, gboolean de addressbook_load (dest, got_book_cb, process); } -typedef struct { - EContact *contact; - int email_num; /* if the contact is a person (not a list), the email address to use */ -} ContactAndEmailNum; - -static void -eab_send_to_contact_and_email_num_list (GList *contact_list) -{ - EMsgComposer *composer; - EComposerHeaderTable *table; - GPtrArray *to_array; - GPtrArray *bcc_array; - - union { - gpointer *pdata; - EDestination **destinations; - } convert; - - if (contact_list == NULL) - return; - - composer = e_msg_composer_new (); - table = e_msg_composer_get_header_table (composer); - em_composer_utils_setup_default_callbacks (composer); - - to_array = g_ptr_array_new (); - bcc_array = g_ptr_array_new (); - - /* Sort contacts into "To" and "Bcc" destinations. */ - while (contact_list != NULL) { - ContactAndEmailNum *ce = contact_list->data; - EContact *contact = ce->contact; - EDestination *destination; - - destination = e_destination_new (); - e_destination_set_contact (destination, contact, 0); - - if (e_destination_is_evolution_list (destination)) { - if (e_destination_list_show_addresses (destination)) - g_ptr_array_add (to_array, destination); - else - g_ptr_array_add (bcc_array, destination); - } else - g_ptr_array_add (to_array, destination); - - contact_list = g_list_next (contact_list); - } - - /* Add sentinels to each array. */ - g_ptr_array_add (to_array, NULL); - g_ptr_array_add (bcc_array, NULL); - - /* XXX Acrobatics like this make me question whether NULL-terminated - * arrays are really the best argument type for passing a list of - * destinations to the header table. */ - - /* Add "To" destinations. */ - convert.pdata = to_array->pdata; - e_composer_header_table_set_destinations_to ( - table, convert.destinations); - g_ptr_array_free (to_array, FALSE); - e_destination_freev (convert.destinations); - - /* Add "Bcc" destinations. */ - convert.pdata = bcc_array->pdata; - e_composer_header_table_set_destinations_bcc ( - table, convert.destinations); - g_ptr_array_free (bcc_array, FALSE); - e_destination_freev (convert.destinations); - - gtk_widget_show (GTK_WIDGET (composer)); -} - -static const char * -get_email (EContact *contact, EContactField field_id, gchar **to_free) -{ - char *name = NULL, *mail = NULL; - const char *value = e_contact_get_const (contact, field_id); - - *to_free = NULL; - - if (eab_parse_qp_email (value, &name, &mail)) { - *to_free = g_strdup_printf ("%s <%s>", name, mail); - value = *to_free; - } - - g_free (name); - g_free (mail); - - return value; -} - -static void -eab_send_contact_list_as_attachment (GList *contacts) -{ - EMsgComposer *composer; - EComposerHeaderTable *table; - CamelMimePart *attachment; - gchar *data; - - if (contacts == NULL) - return; - - composer = e_msg_composer_new (); - table = e_msg_composer_get_header_table (composer); - em_composer_utils_setup_default_callbacks (composer); - - attachment = camel_mime_part_new (); - data = eab_contact_list_to_string (contacts); - - camel_mime_part_set_content ( - attachment, data, strlen (data), "text/x-vcard"); - - if (contacts->next != NULL) - camel_mime_part_set_description ( - attachment, _("Multiple vCards")); - else { - EContact *contact = contacts->data; - const gchar *file_as; - gchar *description; - - file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS); - description = g_strdup_printf (_("vCard for %s"), file_as); - camel_mime_part_set_description (attachment, description); - g_free (description); - } - - camel_mime_part_set_disposition (attachment, "attachment"); - - e_msg_composer_attach (composer, attachment); - camel_object_unref (attachment); - - if (contacts->next != NULL) - e_composer_header_table_set_subject ( - table, _("Contact information")); - else { - EContact *contact = contacts->data; - gchar *tempstr; - const gchar *tempstr2; - gchar *tempfree = NULL; - - tempstr2 = e_contact_get_const (contact, E_CONTACT_FILE_AS); - if (!tempstr2 || !*tempstr2) - tempstr2 = e_contact_get_const (contact, E_CONTACT_FULL_NAME); - if (!tempstr2 || !*tempstr2) - tempstr2 = e_contact_get_const (contact, E_CONTACT_ORG); - if (!tempstr2 || !*tempstr2) { - g_free (tempfree); - tempstr2 = get_email (contact, E_CONTACT_EMAIL_1, &tempfree); - } - if (!tempstr2 || !*tempstr2) { - g_free (tempfree); - tempstr2 = get_email (contact, E_CONTACT_EMAIL_2, &tempfree); - } - if (!tempstr2 || !*tempstr2) { - g_free (tempfree); - tempstr2 = get_email (contact, E_CONTACT_EMAIL_3, &tempfree); - } - - if (!tempstr2 || !*tempstr2) - tempstr = g_strdup_printf (_("Contact information")); - else - tempstr = g_strdup_printf (_("Contact information for %s"), tempstr2); - - e_composer_header_table_set_subject (table, tempstr); - - g_free (tempstr); - g_free (tempfree); - } - - gtk_widget_show (GTK_WIDGET (composer)); -} - -void -eab_send_contact_list (GList *contacts, EABDisposition disposition) -{ - switch (disposition) { - case EAB_DISPOSITION_AS_TO: { - GList *list = NULL, *l; - - for (l = contacts; l; l = l->next) { - ContactAndEmailNum *ce = g_new (ContactAndEmailNum, 1); - ce->contact = l->data; - ce->email_num = 0; /* hardcode this */ - - list = g_list_append (list, ce); - } - - eab_send_to_contact_and_email_num_list (list); - - g_list_foreach (list, (GFunc)g_free, NULL); - g_list_free (list); - break; - } - case EAB_DISPOSITION_AS_ATTACHMENT: - eab_send_contact_list_as_attachment (contacts); - break; - } -} - -void -eab_send_contact (EContact *contact, int email_num, EABDisposition disposition) -{ - GList *list = NULL; - - switch (disposition) { - case EAB_DISPOSITION_AS_TO: { - ContactAndEmailNum ce; - - ce.contact = contact; - ce.email_num = email_num; - - list = g_list_prepend (NULL, &ce); - eab_send_to_contact_and_email_num_list (list); - break; - } - case EAB_DISPOSITION_AS_ATTACHMENT: { - list = g_list_prepend (NULL, contact); - eab_send_contact_list_as_attachment (list); - break; - } - } - - g_list_free (list); -} - GtkWidget * eab_create_image_chooser_widget(gchar *name, gchar *string1, gchar *string2, diff --git a/addressbook/gui/widgets/eab-gui-util.h b/addressbook/gui/widgets/eab-gui-util.h index 79dbe5493a..8d878cff14 100644 --- a/addressbook/gui/widgets/eab-gui-util.h +++ b/addressbook/gui/widgets/eab-gui-util.h @@ -26,8 +26,6 @@ #include <gtk/gtk.h> #include <libebook/e-book.h> -#include "addressbook/gui/contact-editor/e-contact-editor.h" -#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h" G_BEGIN_DECLS @@ -40,17 +38,6 @@ void eab_search_result_dialog (GtkWidget *parent, EBookViewStatus status); gint eab_prompt_save_dialog (GtkWindow *parent); -EContactEditor *eab_show_contact_editor (EBook *book, - EContact *contact, - gboolean is_new_contact, - gboolean editable); -EContactListEditor *eab_show_contact_list_editor (EBook *book, - EContact *contact, - gboolean is_new_contact, - gboolean editable); -void eab_show_multiple_contacts (EBook *book, - GList *list, - gboolean editable); void eab_transfer_contacts (EBook *source, GList *contacts, /* adopted */ gboolean delete_from_source, @@ -64,26 +51,17 @@ void eab_contact_list_save (char *title, GList *list, GtkWindow *parent_window); -typedef enum { - EAB_DISPOSITION_AS_ATTACHMENT, - EAB_DISPOSITION_AS_TO, -} EABDisposition; - -void eab_send_contact (EContact *contact, - int email_num, - EABDisposition disposition); -void eab_send_contact_list (GList *contacts, - EABDisposition disposition); - GtkWidget *eab_create_image_chooser_widget (gchar *name, gchar *string1, gchar *string2, gint int1, gint int2); ESource *eab_select_source (const gchar *title, const gchar *message, const gchar *select_uid, GtkWindow *parent); -/* To parse quoted printable address & return email & name fields */ -gboolean eab_parse_qp_email (const gchar *string, gchar **name, gchar **email); -char *eab_parse_qp_email_to_html (const gchar *string); +/* To parse quoted printable address & return email & name fields */ +gboolean eab_parse_qp_email (const gchar *string, + gchar **name, + gchar **email); +gchar * eab_parse_qp_email_to_html (const gchar *string); G_END_DECLS diff --git a/addressbook/gui/widgets/eab-menu.c b/addressbook/gui/widgets/eab-menu.c deleted file mode 100644 index 603e93893c..0000000000 --- a/addressbook/gui/widgets/eab-menu.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <stdlib.h> - -#include <glib.h> - -#include <libebook/e-contact.h> - -#include "eab-menu.h" - -static void eabm_standard_menu_factory(EMenu *emp, void *data); - -static GObjectClass *eabm_parent; - -static void -eabm_init(GObject *o) -{ - /*EABMenu *emp = (EABMenu *)o; */ -} - -static void -eabm_finalise(GObject *o) -{ - ((GObjectClass *)eabm_parent)->finalize(o); -} - -static void -eabm_target_free(EMenu *ep, EMenuTarget *t) -{ - switch (t->type) { - case EAB_MENU_TARGET_SELECT: { - EABMenuTargetSelect *s = (EABMenuTargetSelect *)t; - int i; - - for (i=0;i<s->cards->len;i++) - g_object_unref(s->cards->pdata[i]); - g_ptr_array_free(s->cards, TRUE); - if (s->book) - g_object_unref(s->book); - break; } - } - - ((EMenuClass *)eabm_parent)->target_free(ep, t); -} - -static void -eabm_class_init(GObjectClass *klass) -{ - klass->finalize = eabm_finalise; - ((EMenuClass *)klass)->target_free = eabm_target_free; - - e_menu_class_add_factory((EMenuClass *)klass, NULL, (EMenuFactoryFunc)eabm_standard_menu_factory, NULL); -} - -GType -eab_menu_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - static const GTypeInfo info = { - sizeof(EABMenuClass), - NULL, NULL, - (GClassInitFunc)eabm_class_init, - NULL, NULL, - sizeof(EABMenu), 0, - (GInstanceInitFunc)eabm_init - }; - eabm_parent = g_type_class_ref(e_menu_get_type()); - type = g_type_register_static(e_menu_get_type(), "EABMenu", &info, 0); - } - - return type; -} - -EABMenu *eab_menu_new(const char *menuid) -{ - EABMenu *emp = g_object_new(eab_menu_get_type(), NULL); - - e_menu_construct(&emp->menu, menuid); - - return emp; -} - -/** - * eab_menu_target_new_select - create a menu target of the current selection. - * @eabp: Address book menu. - * @book: Book the cards belong to. May be NULL in which case cards must be an empty GPtrArray. - * @readonly: Book is read-only mode. FIXME: Why can't we just get this off the book? - * @cards: Cards selected. This will be freed on completion and the array indices unreferenced. - * - * Create a new selection menu target. - * - * Return value: - **/ -EABMenuTargetSelect * -eab_menu_target_new_select(EABMenu *eabp, struct _EBook *book, int readonly, GPtrArray *cards) -{ - EABMenuTargetSelect *t = e_menu_target_new(&eabp->menu, EAB_MENU_TARGET_SELECT, sizeof(*t)); - guint32 mask = ~0; - int has_email = FALSE, i; - - /* FIXME: duplicated in eab-popup.c */ - - t->book = book; - if (book) - g_object_ref(book); - t->cards = cards; - - for (i=0;i<cards->len && !has_email;i++) { - EContact *contact = cards->pdata[i]; - GList *email; - - email = e_contact_get(E_CONTACT(contact), E_CONTACT_EMAIL); - if (email) { - has_email = TRUE; - - g_list_foreach(email, (GFunc)g_free, NULL); - g_list_free(email); - } - } - - if (has_email) - mask &= ~EAB_MENU_SELECT_EMAIL; - - if (!readonly) - mask &= ~EAB_MENU_SELECT_EDITABLE; - - if (cards->len == 1) - mask &= ~EAB_MENU_SELECT_ONE; - - if (cards->len > 1) - mask &= ~EAB_MENU_SELECT_MANY; - - if (cards->len >= 1) - mask &= ~EAB_MENU_SELECT_ANY; - - t->target.mask = mask; - - return t; -} - -static void -eabm_standard_menu_factory(EMenu *emp, void *data) -{ - /* noop */ -} - -/* ********************************************************************** */ - -/* menu plugin handler */ - -/* -<e-plugin - class="org.gnome.mail.plugin.popup:1.0" - id="org.gnome.mail.plugin.popup.item:1.0" - type="shlib" - location="/opt/gnome2/lib/camel/1.0/libcamelimap.so" - name="imap" - description="IMAP4 and IMAP4v1 mail store"> - <hook class="org.gnome.mail.popupMenu:1.0" - handler="HandlePopup"> - <menu id="any" target="select"> - <item - type="item|toggle|radio|image|submenu|bar" - active - path="foo/bar" - label="label" - icon="foo" - mask="select_one" - activate="eabm_view_emacs"/> - </menu> - </extension> - -*/ - -static void *eabmph_parent_class; -#define eabmph ((EABMenuHook *)eph) - -static const EMenuHookTargetMask eabmph_select_masks[] = { - { "one", EAB_MENU_SELECT_ONE }, - { "many", EAB_MENU_SELECT_MANY }, - { "any", EAB_MENU_SELECT_ANY }, - { "editable", EAB_MENU_SELECT_EDITABLE }, - { "email", EAB_MENU_SELECT_EMAIL }, - { NULL } -}; - -static const EMenuHookTargetMap eabmph_targets[] = { - { "select", EAB_MENU_TARGET_SELECT, eabmph_select_masks }, - { NULL } -}; - -static void -eabmph_finalise(GObject *o) -{ - /*EPluginHook *eph = (EPluginHook *)o;*/ - - ((GObjectClass *)eabmph_parent_class)->finalize(o); -} - -static void -eabmph_class_init(EPluginHookClass *klass) -{ - int i; - - ((GObjectClass *)klass)->finalize = eabmph_finalise; - ((EPluginHookClass *)klass)->id = "org.gnome.evolution.addressbook.bonobomenu:1.0"; - - for (i=0;eabmph_targets[i].type;i++) - e_menu_hook_class_add_target_map((EMenuHookClass *)klass, &eabmph_targets[i]); - - /* FIXME: leaks parent set class? */ - ((EMenuHookClass *)klass)->menu_class = g_type_class_ref(eab_menu_get_type()); -} - -GType -eab_menu_hook_get_type(void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof(EABMenuHookClass), NULL, NULL, (GClassInitFunc) eabmph_class_init, NULL, NULL, - sizeof(EABMenuHook), 0, (GInstanceInitFunc) NULL, - }; - - eabmph_parent_class = g_type_class_ref(e_menu_hook_get_type()); - type = g_type_register_static(e_menu_hook_get_type(), "EABMenuHook", &info, 0); - } - - return type; -} diff --git a/addressbook/gui/widgets/eab-menu.h b/addressbook/gui/widgets/eab-menu.h deleted file mode 100644 index 7da05c133b..0000000000 --- a/addressbook/gui/widgets/eab-menu.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michel Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EAB_MENU_H__ -#define __EAB_MENU_H__ - -#include <glib-object.h> - -#include "e-util/e-menu.h" - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -struct _EBook; - -typedef struct _EABMenu EABMenu; -typedef struct _EABMenuClass EABMenuClass; - -/* Current target description */ -enum _eab_menu_target_t { - EAB_MENU_TARGET_SELECT, -}; - -/** - * enum _eab_menu_target_select_t - EABMenuTargetSelect qualifiers. - * - * @EAB_MENU_SELECT_ONE: Only one item is selected. - * @EAB_MENU_SELECT_MANY: More than one item selected. - * @EAB_MENU_SELECT_ANY: One or more items selected. - * @EAB_MENU_SELECT_EDITABLE: Editable addressbook. - * @EAB_MENU_SELECT_EMAIL: Has an email address. - **/ -enum _eab_menu_target_select_t { - EAB_MENU_SELECT_ONE = 1<<0, - EAB_MENU_SELECT_MANY = 1<<1, - EAB_MENU_SELECT_ANY = 1<<2, - EAB_MENU_SELECT_EDITABLE = 1<<3, - EAB_MENU_SELECT_EMAIL = 1<<4, -}; - -typedef struct _EABMenuTargetSelect EABMenuTargetSelect; - -struct _EABMenuTargetSelect { - EMenuTarget target; - - struct _EBook *book; - GPtrArray *cards; -}; - -typedef struct _EMenuItem EABMenuItem; - -/* The object */ -struct _EABMenu { - EMenu menu; - - struct _EABMenuPrivate *priv; -}; - -struct _EABMenuClass { - EMenuClass menu_class; -}; - -GType eab_menu_get_type(void); - -EABMenu *eab_menu_new(const char *menuid); - -EABMenuTargetSelect *eab_menu_target_new_select(EABMenu *eabp, struct _EBook *book, int readonly, GPtrArray *cards); - -/* ********************************************************************** */ - -typedef struct _EABMenuHook EABMenuHook; -typedef struct _EABMenuHookClass EABMenuHookClass; - -struct _EABMenuHook { - EMenuHook hook; -}; - -struct _EABMenuHookClass { - EMenuHookClass hook_class; -}; - -GType eab_menu_hook_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __EAB_MENU_H__ */ diff --git a/addressbook/gui/widgets/eab-popup-control.c b/addressbook/gui/widgets/eab-popup-control.c deleted file mode 100644 index 6a702f3941..0000000000 --- a/addressbook/gui/widgets/eab-popup-control.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * This file is too big and this widget is too complicated. Forgive me. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * Authors: - * Jon Trowbridge <trow@ximian.com> - * Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - */ - -#include <config.h> -#include <string.h> -#include "addressbook.h" -#include "eab-popup-control.h" -#include <bonobo/bonobo-control.h> -#include <bonobo/bonobo-property-bag.h> -#include <bonobo/bonobo-generic-factory.h> -#include <addressbook/util/eab-book-util.h> -#include <addressbook/gui/contact-editor/e-contact-editor.h> -#include <addressbook/gui/contact-editor/e-contact-quick-add.h> -#include <addressbook/gui/widgets/eab-contact-display.h> -#include <addressbook/gui/widgets/eab-gui-util.h> - -static void eab_popup_control_set_name (EABPopupControl *pop, const gchar *name); -static void eab_popup_control_set_email (EABPopupControl *pop, const gchar *email); -static void eab_popup_control_set_vcard (EABPopupControl *pop, const gchar *vcard); - -static GtkObjectClass *parent_class; - -static void eab_popup_control_dispose (GObject *); -static void eab_popup_control_query (EABPopupControl *); - - -static void -eab_popup_control_class_init (EABPopupControlClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - object_class->dispose = eab_popup_control_dispose; -} - -static void -eab_popup_control_init (EABPopupControl *pop) -{ - pop->transitory = TRUE; -} - -static void -eab_popup_control_cleanup (EABPopupControl *pop) -{ - if (pop->contact) { - g_object_unref (pop->contact); - pop->contact = NULL; - } - - if (pop->scheduled_refresh) { - g_source_remove (pop->scheduled_refresh); - pop->scheduled_refresh = 0; - } - - if (pop->query_tag) { -#ifdef notyet - e_book_simple_query_cancel (pop->book, pop->query_tag); -#endif - pop->query_tag = 0; - } - - if (pop->book) { - g_object_unref (pop->book); - pop->book = NULL; - } - - g_free (pop->name); - pop->name = NULL; - - g_free (pop->email); - pop->email = NULL; - - g_free (pop->vcard); - pop->vcard = NULL; -} - -static void -eab_popup_control_dispose (GObject *obj) -{ - EABPopupControl *pop = EAB_POPUP_CONTROL (obj); - - eab_popup_control_cleanup (pop); - - if (G_OBJECT_CLASS (parent_class)->dispose) - G_OBJECT_CLASS (parent_class)->dispose (obj); -} - -GType -eab_popup_control_get_type (void) -{ - static GType pop_type = 0; - - if (!pop_type) { - static const GTypeInfo pop_info = { - sizeof (EABPopupControlClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) eab_popup_control_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EABPopupControl), - 0, /* n_preallocs */ - (GInstanceInitFunc) eab_popup_control_init, - }; - - pop_type = g_type_register_static (gtk_event_box_get_type (), "EABPopupControl", &pop_info, 0); - } - - return pop_type; -} - -static void -eab_popup_control_refresh_names (EABPopupControl *pop) -{ - if (pop->name_widget) { - if (pop->name && *pop->name) { - gtk_label_set_text (GTK_LABEL (pop->name_widget), pop->name); - gtk_widget_show (pop->name_widget); - } else { - gtk_widget_hide (pop->name_widget); - } - } - - if (pop->email_widget) { - if (pop->email && *pop->email) { - gtk_label_set_text (GTK_LABEL (pop->email_widget), pop->email); - gtk_widget_show (pop->email_widget); - } else { - gtk_widget_hide (pop->email_widget); - } - } - - eab_popup_control_query (pop); -} - -static gint -refresh_timeout_cb (gpointer ptr) -{ - EABPopupControl *pop = EAB_POPUP_CONTROL (ptr); - eab_popup_control_refresh_names (pop); - pop->scheduled_refresh = 0; - return 0; -} - -static void -eab_popup_control_schedule_refresh (EABPopupControl *pop) -{ - if (pop->scheduled_refresh == 0) - pop->scheduled_refresh = g_timeout_add (20, refresh_timeout_cb, pop); -} - -/* If we are handed something of the form "Foo <bar@bar.com>", - do the right thing. */ -static gboolean -eab_popup_control_set_free_form (EABPopupControl *pop, const gchar *txt) -{ - gchar *lt, *gt = NULL; - - g_return_val_if_fail (pop && EAB_IS_POPUP_CONTROL (pop), FALSE); - - if (txt == NULL) - return FALSE; - - lt = strchr (txt, '<'); - if (lt) - gt = strchr (txt, '>'); - - if (lt && gt && lt+1 < gt) { - gchar *name = g_strndup (txt, lt-txt); - gchar *email = g_strndup (lt+1, gt-lt-1); - eab_popup_control_set_name (pop, name); - eab_popup_control_set_email (pop, email); - g_free(name); - g_free(email); - - return TRUE; - } - - return FALSE; -} - -static void -eab_popup_control_set_name (EABPopupControl *pop, const gchar *name) -{ - g_return_if_fail (pop && EAB_IS_POPUP_CONTROL (pop)); - - /* We only allow the name to be set once. */ - if (pop->name) - return; - - if (!eab_popup_control_set_free_form (pop, name)) { - pop->name = g_strdup (name); - if (pop->name) - g_strstrip (pop->name); - } - - eab_popup_control_schedule_refresh (pop); -} - -static void -eab_popup_control_set_email (EABPopupControl *pop, const gchar *email) -{ - g_return_if_fail (pop && EAB_IS_POPUP_CONTROL (pop)); - - /* We only allow the e-mail to be set once. */ - if (pop->email) - return; - - if (!eab_popup_control_set_free_form (pop, email)) { - pop->email = g_strdup (email); - if (pop->email) - g_strstrip (pop->email); - } - - eab_popup_control_schedule_refresh (pop); -} - -static void -eab_popup_control_set_vcard (EABPopupControl *pop, const gchar *vcard) -{ - g_return_if_fail (pop && EAB_IS_POPUP_CONTROL (pop)); - - /* We only allow the vcard to be set once. */ - if (pop->vcard) - return; - - g_free (pop->name); - g_free (pop->email); - - pop->name = NULL; - pop->email = NULL; - - pop->vcard = g_strdup (vcard); - - eab_popup_control_schedule_refresh (pop); -} - -void -eab_popup_control_construct (EABPopupControl *pop) -{ - GtkWidget *vbox, *name_holder; - GdkColor color = { 0x0, 0xffff, 0xffff, 0xffff }; - - g_return_if_fail (pop && EAB_IS_POPUP_CONTROL (pop)); - - pop->main_vbox = gtk_vbox_new (FALSE, 0); - - /* Build Generic View */ - - name_holder = gtk_event_box_new (); - vbox = gtk_vbox_new (FALSE, 2); - pop->name_widget = gtk_label_new (""); - pop->email_widget = gtk_label_new (""); - - gtk_box_pack_start (GTK_BOX (vbox), pop->name_widget, TRUE, TRUE, 2); - gtk_box_pack_start (GTK_BOX (vbox), pop->email_widget, TRUE, TRUE, 2); - gtk_container_add (GTK_CONTAINER (name_holder), GTK_WIDGET (vbox)); - - if (gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (name_holder)), &color, FALSE, TRUE)) { - GtkStyle *style = gtk_style_copy (gtk_widget_get_style (GTK_WIDGET (name_holder))); - style->bg[0] = color; - gtk_widget_set_style (GTK_WIDGET (name_holder), style); - g_object_unref (style); - } - - pop->generic_view = gtk_frame_new (NULL); - gtk_container_add (GTK_CONTAINER (pop->generic_view), name_holder); - gtk_box_pack_start (GTK_BOX (pop->main_vbox), pop->generic_view, TRUE, TRUE, 0); - gtk_widget_show_all (pop->generic_view); - - pop->query_msg = gtk_label_new (_("Querying Address Book...")); - gtk_box_pack_start (GTK_BOX (pop->main_vbox), pop->query_msg, TRUE, TRUE, 0); - gtk_widget_show (pop->query_msg); - - /* Build ContactDisplay */ - pop->contact_display = eab_contact_display_new (); - gtk_box_pack_start (GTK_BOX (pop->main_vbox), pop->contact_display, TRUE, TRUE, 0); - - - /* Final assembly */ - - gtk_container_add (GTK_CONTAINER (pop), pop->main_vbox); - gtk_widget_show (pop->main_vbox); - - gtk_container_set_border_width (GTK_CONTAINER (vbox), 3); - gtk_container_set_border_width (GTK_CONTAINER (pop), 2); -} - -static GtkWidget * -eab_popup_new (void) -{ - EABPopupControl *pop = g_object_new (EAB_TYPE_POPUP_CONTROL, NULL); - eab_popup_control_construct (pop); - return GTK_WIDGET (pop); -} - -static void -emit_event (EABPopupControl *pop, const char *event) -{ - if (pop->es) { - BonoboArg *arg; - - arg = bonobo_arg_new (BONOBO_ARG_BOOLEAN); - BONOBO_ARG_SET_BOOLEAN (arg, TRUE); - bonobo_event_source_notify_listeners_full (pop->es, - "GNOME/Evolution/Addressbook/AddressPopup", - "Event", - event, - arg, NULL); - bonobo_arg_release (arg); - } -} - -static void -eab_popup_control_no_matches (EABPopupControl *pop) -{ - if (pop->vcard && *pop->vcard) - e_contact_quick_add_vcard (pop->vcard, NULL, NULL); - else if (pop->email && *pop->email) { - if (pop->name && *pop->name) - e_contact_quick_add (pop->name, pop->email, NULL, NULL); - else - e_contact_quick_add_free_form (pop->email, NULL, NULL); - - } - eab_popup_control_cleanup (pop); - emit_event (pop, "Destroy"); -} - -static void -eab_popup_control_query (EABPopupControl *pop) -{ - g_return_if_fail (pop && EAB_IS_POPUP_CONTROL (pop)); - - g_object_ref (pop); - - eab_popup_control_no_matches (pop) ; - - g_object_unref (pop); - -} - -/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ - -enum { - PROPERTY_NAME, - PROPERTY_EMAIL, - PROPERTY_TRANSITORY, - PROPERTY_VCARD -}; - -static void -set_prop (BonoboPropertyBag *bag, const BonoboArg *arg, guint arg_id, CORBA_Environment *ev, gpointer user_data) -{ - EABPopupControl *pop = EAB_POPUP_CONTROL (user_data); - - switch (arg_id) { - - case PROPERTY_NAME: - eab_popup_control_set_name (pop, BONOBO_ARG_GET_STRING (arg)); - break; - - case PROPERTY_EMAIL: - eab_popup_control_set_email (pop, BONOBO_ARG_GET_STRING (arg)); - break; - - case PROPERTY_VCARD: - eab_popup_control_set_vcard (pop, BONOBO_ARG_GET_STRING (arg)); - break; - - default: - g_return_if_reached (); - } -} - -static void -get_prop (BonoboPropertyBag *bag, BonoboArg *arg, guint arg_id, CORBA_Environment *ev, gpointer user_data) -{ - EABPopupControl *pop = EAB_POPUP_CONTROL (user_data); - - switch (arg_id) { - - case PROPERTY_NAME: - BONOBO_ARG_SET_STRING (arg, pop->name); - break; - - case PROPERTY_EMAIL: - BONOBO_ARG_SET_STRING (arg, pop->email); - break; - - case PROPERTY_TRANSITORY: - BONOBO_ARG_SET_BOOLEAN (arg, pop->transitory); - break; - - case PROPERTY_VCARD: - BONOBO_ARG_SET_STRING (arg, pop->vcard); - break; - - default: - g_return_if_reached (); - } -} - -BonoboControl * -eab_popup_control_new (void) -{ - BonoboControl *control; - BonoboPropertyBag *bag; - EABPopupControl *addy; - GtkWidget *w; - - w = eab_popup_new (); - addy = EAB_POPUP_CONTROL (w); - - control = bonobo_control_new (w); - gtk_widget_show (w); - - bag = bonobo_property_bag_new (get_prop, set_prop, w); - bonobo_property_bag_add (bag, "name", PROPERTY_NAME, - BONOBO_ARG_STRING, NULL, NULL, - BONOBO_PROPERTY_WRITEABLE | BONOBO_PROPERTY_READABLE); - - bonobo_property_bag_add (bag, "email", PROPERTY_EMAIL, - BONOBO_ARG_STRING, NULL, NULL, - BONOBO_PROPERTY_WRITEABLE | BONOBO_PROPERTY_READABLE); - - bonobo_property_bag_add (bag, "transitory", PROPERTY_TRANSITORY, - BONOBO_ARG_BOOLEAN, NULL, NULL, - BONOBO_PROPERTY_READABLE); - - bonobo_property_bag_add (bag, "vcard", PROPERTY_VCARD, - BONOBO_ARG_STRING, NULL, NULL, - BONOBO_PROPERTY_WRITEABLE | BONOBO_PROPERTY_READABLE); - - bonobo_control_set_properties (control, bonobo_object_corba_objref (BONOBO_OBJECT (bag)), NULL); - bonobo_object_unref (BONOBO_OBJECT (bag)); - - addy->es = bonobo_event_source_new (); - bonobo_object_add_interface (BONOBO_OBJECT (control), - BONOBO_OBJECT (addy->es)); - - return control; -} diff --git a/addressbook/gui/widgets/eab-popup-control.h b/addressbook/gui/widgets/eab-popup-control.h deleted file mode 100644 index e8031a7fec..0000000000 --- a/addressbook/gui/widgets/eab-popup-control.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Jon Trowbridge <trow@ximian.com> - * Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EAB_POPUP_CONTROL_H__ -#define __EAB_POPUP_CONTROL_H__ - -#include <bonobo/bonobo-event-source.h> -#include <libebook/e-book.h> -#include <libebook/e-contact.h> - -#include <gtk/gtk.h> - -G_BEGIN_DECLS - -#define EAB_TYPE_POPUP_CONTROL (eab_popup_control_get_type ()) -#define EAB_POPUP_CONTROL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EAB_TYPE_POPUP_CONTROL, EABPopupControl)) -#define EAB_POPUP_CONTROL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EAB_TYPE_POPUP_CONTROL, EABPopupControlClass)) -#define EAB_IS_POPUP_CONTROL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EAB_TYPE_POPUP_CONTROL)) -#define EAB_IS_POPUP_CONTROL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EAB_TYPE_POPUP_CONTROL)) - -typedef struct _EABPopupControl EABPopupControl; -typedef struct _EABPopupControlClass EABPopupControlClass; - -struct _EABPopupControl { - GtkEventBox parent; - - gchar *name; - gchar *email; - gchar *vcard; - - GtkWidget *name_widget; - GtkWidget *email_widget; - GtkWidget *query_msg; - - GtkWidget *main_vbox; - GtkWidget *generic_view; - GtkWidget *contact_display; - - gboolean transitory; - - guint scheduled_refresh; - EBook *book; - guint query_tag; - gboolean multiple_matches; - EContact *contact; - - BonoboEventSource *es; -}; - -struct _EABPopupControlClass { - GtkEventBoxClass parent_class; -}; - -GType eab_popup_control_get_type (void); - -void eab_popup_control_construct (EABPopupControl *); - -BonoboControl *eab_popup_control_new (void); - -G_END_DECLS - -#endif /* __EAB_POPUP_CONTROL_H__ */ - diff --git a/addressbook/gui/widgets/eab-popup.c b/addressbook/gui/widgets/eab-popup.c deleted file mode 100644 index 17f979734b..0000000000 --- a/addressbook/gui/widgets/eab-popup.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <stdlib.h> - -#include <glib.h> - -#include "eab-popup.h" -#include <libedataserverui/e-source-selector.h> -#include <libebook/e-contact.h> - -static GObjectClass *eabp_parent; - -static void -eabp_init(GObject *o) -{ - /*EABPopup *eabp = (EABPopup *)o; */ -} - -static void -eabp_finalise(GObject *o) -{ - ((GObjectClass *)eabp_parent)->finalize(o); -} - -static void -eabp_target_free(EPopup *ep, EPopupTarget *t) -{ - switch (t->type) { - case EAB_POPUP_TARGET_SELECT: { - EABPopupTargetSelect *s = (EABPopupTargetSelect *)t; - int i; - - for (i=0;i<s->cards->len;i++) - g_object_unref(s->cards->pdata[i]); - g_ptr_array_free(s->cards, TRUE); - g_object_unref(s->book); - - break; } - case EAB_POPUP_TARGET_URI: { - EABPopupTargetURI *s = (EABPopupTargetURI *)t; - - g_free(s->uri); - break; } - case EAB_POPUP_TARGET_SOURCE: { - EABPopupTargetSource *s = (EABPopupTargetSource *)t; - - g_object_unref(s->selector); - break; } - -#ifdef ADAPTED_TO_E_NAME_SELECTOR - - case EAB_POPUP_TARGET_SELECT_NAMES: { - EABPopupTargetSelectNames *s = (EABPopupTargetSelectNames *)t; - - g_object_unref(s->model); - break; } - -#endif - - } - - ((EPopupClass *)eabp_parent)->target_free(ep, t); -} - -static void -eabp_class_init(GObjectClass *klass) -{ - klass->finalize = eabp_finalise; - ((EPopupClass *)klass)->target_free = eabp_target_free; -} - -GType -eab_popup_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - static const GTypeInfo info = { - sizeof(EABPopupClass), - NULL, NULL, - (GClassInitFunc)eabp_class_init, - NULL, NULL, - sizeof(EABPopup), 0, - (GInstanceInitFunc)eabp_init - }; - eabp_parent = g_type_class_ref(e_popup_get_type()); - type = g_type_register_static(e_popup_get_type(), "EABPopup", &info, 0); - } - - return type; -} - -EABPopup *eab_popup_new(const char *menuid) -{ - EABPopup *eabp = g_object_new(eab_popup_get_type(), NULL); - - e_popup_construct(&eabp->popup, menuid); - - return eabp; -} - -/** - * eab_popup_target_new_select: - * @eabp: Address book popup. - * @book: Book the cards belong to. - * @readonly: Book is read-only mode. FIXME: Why can't we just get this off the book? - * @cards: Cards selected. This will be freed on completion. - * - * Create a new selection popup target. - * - * Return value: - **/ - - -EABPopupTargetURI * -eab_popup_target_new_uri(EABPopup *emp, const char *uri) -{ - EABPopupTargetURI *t = e_popup_target_new(&emp->popup, EAB_POPUP_TARGET_URI, sizeof(*t)); - guint32 mask = ~0; - - t->uri = g_strdup(uri); - - if (g_ascii_strncasecmp(uri, "http:", 5) == 0 - || g_ascii_strncasecmp(uri, "https:", 6) == 0) - mask &= ~EAB_POPUP_URI_HTTP; - if (g_ascii_strncasecmp(uri, "internal-mailto:", 16) == 0) - mask &= ~EAB_POPUP_URI_MAILTO; - else - mask &= ~EAB_POPUP_URI_NOT_MAILTO; - - t->target.mask = mask; - - return t; -} - - - - -EABPopupTargetSelect * -eab_popup_target_new_select(EABPopup *eabp, struct _EBook *book, int readonly, GPtrArray *cards) -{ - EABPopupTargetSelect *t = e_popup_target_new(&eabp->popup, EAB_POPUP_TARGET_SELECT, sizeof(*t)); - guint32 mask = ~0; - int has_email = FALSE, i; - - /* FIXME: duplicated in eab-menu.c */ - - t->book = book; - g_object_ref(book); - t->cards = cards; - - for (i=0;i<cards->len && !has_email;i++) { - EContact *contact = cards->pdata[i]; - GList *email; - - email = e_contact_get(E_CONTACT(contact), E_CONTACT_EMAIL); - if (email) { - has_email = TRUE; - - g_list_foreach(email, (GFunc)g_free, NULL); - g_list_free(email); - } - } - - if (cards->len == 1) { - if (e_contact_get (E_CONTACT(cards->pdata[0]), E_CONTACT_IS_LIST)) - mask &= ~EAB_POPUP_LIST; - else - mask &= ~EAB_POPUP_CONTACT; - } - - if (has_email) - mask &= ~EAB_POPUP_SELECT_EMAIL; - - if (!readonly) - mask &= ~EAB_POPUP_SELECT_EDITABLE; - - if (cards->len == 1) - mask &= ~EAB_POPUP_SELECT_ONE; - - if (cards->len > 1) - mask &= ~EAB_POPUP_SELECT_MANY; - - if (cards->len >= 1) - mask &= ~EAB_POPUP_SELECT_ANY; - - t->target.mask = mask; - - return t; -} - -EABPopupTargetSource * -eab_popup_target_new_source(EABPopup *eabp, ESourceSelector *selector) -{ - EABPopupTargetSource *t = e_popup_target_new(&eabp->popup, EAB_POPUP_TARGET_SOURCE, sizeof(*t)); - guint32 mask = ~0; - const char *source_uri; - ESource *source; - - /* TODO: this is duplicated for calendar and tasks too */ - - t->selector = selector; - g_object_ref(selector); - - /* TODO: perhaps we need to copy this so it doesn't change during the lifecycle */ - source = e_source_selector_peek_primary_selection(selector); - if (source) - mask &= ~EAB_POPUP_SOURCE_PRIMARY; - - /* FIXME Gross hack, should have a property or something */ - source_uri = e_source_peek_relative_uri(source); - if (source_uri && !strcmp("system", source_uri)) - mask &= ~EAB_POPUP_SOURCE_SYSTEM; - else - mask &= ~EAB_POPUP_SOURCE_USER; - - t->target.mask = mask; - - return t; -} - -#ifdef ADAPTED_TO_E_NAME_SELECTOR - -EABPopupTargetSelectNames * -eab_popup_target_new_select_names(EABPopup *eabp, struct _ESelectNamesModel *model, int row) -{ - EABPopupTargetSelectNames *t = e_popup_target_new(&eabp->popup, EAB_POPUP_TARGET_SELECT_NAMES, sizeof(*t)); - - /* TODO: this is sort of not very useful, maybe the popup which uses it doesn't - need to be pluggable */ - - t->model = model; - g_object_ref(model); - t->row = row; - - return t; -} - -#endif - -/* ********************************************************************** */ -/* Popup menu plugin handler */ - -/* -<e-plugin - class="org.gnome.mail.plugin.popup:1.0" - id="org.gnome.mail.plugin.popup.iteab:1.0" - type="shlib" - location="/opt/gnome2/lib/camel/1.0/libcamelimap.so" - name="imap" - description="IMAP4 and IMAP4v1 mail store"> - <hook class="org.gnome.mail.popupMenu:1.0" - handler="HandlePopup"> - <menu id="any" target="select"> - <iteab - type="iteab|toggle|radio|image|submenu|bar" - active - path="foo/bar" - label="label" - icon="foo" - mask="select_one" - activate="eabp_view_eabacs"/> - </menu> - </extension> - -*/ - -static void *eabph_parent_class; -#define eabph ((EABPopupHook *)eph) - -static const EPopupHookTargetMask eabph_select_masks[] = { - { "one", EAB_POPUP_SELECT_ONE }, - { "many", EAB_POPUP_SELECT_MANY }, - { "any", EAB_POPUP_SELECT_ANY }, - { "editable", EAB_POPUP_SELECT_EDITABLE }, - { "email", EAB_POPUP_SELECT_EMAIL }, - { NULL } -}; - -static const EPopupHookTargetMask eabph_source_masks[] = { - { "primary", EAB_POPUP_SOURCE_PRIMARY }, - { "system", EAB_POPUP_SOURCE_SYSTEM }, - { NULL } -}; - -static const EPopupHookTargetMask eabph_uri_masks[] = { - { "http", EAB_POPUP_URI_HTTP }, - { "internal-mailto", EAB_POPUP_URI_MAILTO }, - { "notmailto", EAB_POPUP_URI_NOT_MAILTO }, - { NULL } -}; - -static const EPopupHookTargetMask eabph_select_names_masks[] = { - { NULL } -}; - -static const EPopupHookTargetMap eabph_targets[] = { - { "select", EAB_POPUP_TARGET_SELECT, eabph_select_masks }, - { "uri", EAB_POPUP_TARGET_URI, eabph_uri_masks }, - { "source", EAB_POPUP_TARGET_SOURCE, eabph_source_masks }, - { "select-names", EAB_POPUP_TARGET_SELECT_NAMES, eabph_select_names_masks }, - { NULL } -}; - -static void -eabph_finalise(GObject *o) -{ - /*EPluginHook *eph = (EPluginHook *)o;*/ - - ((GObjectClass *)eabph_parent_class)->finalize(o); -} - -static void -eabph_class_init(EPluginHookClass *klass) -{ - int i; - - ((GObjectClass *)klass)->finalize = eabph_finalise; - ((EPluginHookClass *)klass)->id = "org.gnome.evolution.addressbook.popup:1.0"; - - for (i=0;eabph_targets[i].type;i++) - e_popup_hook_class_add_target_map((EPopupHookClass *)klass, &eabph_targets[i]); - - ((EPopupHookClass *)klass)->popup_class = g_type_class_ref(eab_popup_get_type()); -} - -GType -eab_popup_hook_get_type(void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof(EABPopupHookClass), NULL, NULL, (GClassInitFunc) eabph_class_init, NULL, NULL, - sizeof(EABPopupHook), 0, (GInstanceInitFunc) NULL, - }; - - eabph_parent_class = g_type_class_ref(e_popup_hook_get_type()); - type = g_type_register_static(e_popup_hook_get_type(), "EABPopupHook", &info, 0); - } - - return type; -} diff --git a/addressbook/gui/widgets/eab-popup.h b/addressbook/gui/widgets/eab-popup.h deleted file mode 100644 index 933c815af8..0000000000 --- a/addressbook/gui/widgets/eab-popup.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EAB_POPUP_H__ -#define __EAB_POPUP_H__ - -#include <glib-object.h> - -#include "e-util/e-popup.h" - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define ADAPTED_TO_E_NAME_SELECTOR 1 - -typedef struct _EABPopup EABPopup; -typedef struct _EABPopupClass EABPopupClass; - -/** - * enum _eab_popup_target_t - A list of mail popup target types. - * - * @EAB_POPUP_TARGET_SELECT: A selection of cards - * @EAB_POPUP_TARGET_SOURCE: A source selection. - * - * Defines the value of the targetid for all EABPopup target types. - **/ -enum _eab_popup_target_t { - EAB_POPUP_TARGET_SELECT, - EAB_POPUP_TARGET_URI, - EAB_POPUP_TARGET_SOURCE, - EAB_POPUP_TARGET_SELECT_NAMES, -}; - -/** - * enum _eab_popup_target_select_t - EABPopupTargetSelect qualifiers. - * - * @EAB_POPUP_SELECT_ONE: Only one item is selected. - * @EAB_POPUP_SELECT_MANY: Two or more items are selected. - * @EAB_POPUP_SELECT_ANY: One or more items are selected. - * @EAB_POPUP_SELECT_EDITABLE: Read/writable source. - * @EAB_POPUP_SELECT_EMAIL: Has an email address. - **/ -enum _eab_popup_target_select_t { - EAB_POPUP_SELECT_ONE = 1<<0, - EAB_POPUP_SELECT_MANY = 1<<1, - EAB_POPUP_SELECT_ANY = 1<<2, - EAB_POPUP_SELECT_EDITABLE = 1<<3, - EAB_POPUP_SELECT_EMAIL = 1<<4, - EAB_POPUP_LIST = 1<<5, - EAB_POPUP_CONTACT = 1<<6, -}; - -enum _eab_popup_target_uri_t { - EAB_POPUP_URI_HTTP = 1<<0, - EAB_POPUP_URI_MAILTO = 1<<1, - EAB_POPUP_URI_NOT_MAILTO = 1<<2, -}; -/** - * enum _eab_popup_target_source_t - EABPopupTargetSource qualifiers. - * - * @EAB_POPUP_SOURCE_PRIMARY: Has a primary selection. - * @EAB_POPUP_SOURCE_SYSTEM: Is a 'system' folder. - * - **/ -enum _eab_popup_target_source_t { - EAB_POPUP_SOURCE_PRIMARY = 1<<0, - EAB_POPUP_SOURCE_SYSTEM = 1<<1, /* system folder */ - EAB_POPUP_SOURCE_USER = 1<<2, /* user folder (!system) */ -}; - -typedef struct _EABPopupTargetSelect EABPopupTargetSelect; -typedef struct _EABPopupTargetSource EABPopupTargetSource; -typedef struct _EABPopupTargetSelectNames EABPopupTargetSelectNames; -typedef struct _EABPopupTargetURI EABPopupTargetURI; -/** - * struct _EABPopupTargetSelect - A list of address cards. - * - * @target: Superclass. - * @book: Book the cards belong to. - * @cards: All selected cards. - * - * Used to represent a selection of cards as context for a popup - * menu. - **/ -struct _EABPopupTargetSelect { - EPopupTarget target; - - struct _EBook *book; - GPtrArray *cards; -}; - - -struct _EABPopupTargetURI { - EPopupTarget target; - char *uri; -}; - -/** - * struct _EABPopupTargetSource - A source target. - * - * @target: Superclass. - * @selector: Selector holding the source selection. - * - * This target is used to represent a source selection. - **/ -struct _EABPopupTargetSource { - EPopupTarget target; - - struct _ESourceSelector *selector; -}; - -#ifdef ADAPTED_TO_E_NAME_SELECTOR - -/** - * struct _EABPopupTargetSelectNames - A select names target. - * - * @target: Superclass. - * @model: Select names model. - * @row: Row of item selected. - * - * This target is used to represent an item selected in an - * ESelectNames model. - **/ -struct _EABPopupTargetSelectNames { - EPopupTarget target; - - struct _ESelectNamesModel *model; - int row; -}; - -#endif - -typedef struct _EPopupItem EABPopupItem; - -/* The object */ -struct _EABPopup { - EPopup popup; - - struct _EABPopupPrivate *priv; -}; - -struct _EABPopupClass { - EPopupClass popup_class; -}; - -GType eab_popup_get_type(void); - -EABPopup *eab_popup_new(const char *menuid); - -EABPopupTargetSelect *eab_popup_target_new_select(EABPopup *eabp, struct _EBook *book, int readonly, GPtrArray *cards); -EABPopupTargetURI *eab_popup_target_new_uri(EABPopup *emp, const char *uri); -EABPopupTargetSource *eab_popup_target_new_source(EABPopup *eabp, struct _ESourceSelector *selector); - -#ifdef ADAPTED_TO_E_NAME_SELECTOR - -EABPopupTargetSelectNames *eab_popup_target_new_select_names(EABPopup *eabp, struct _ESelectNamesModel *model, int row); - -#endif - -/* ********************************************************************** */ - -typedef struct _EABPopupHook EABPopupHook; -typedef struct _EABPopupHookClass EABPopupHookClass; - -struct _EABPopupHook { - EPopupHook hook; -}; - -struct _EABPopupHookClass { - EPopupHookClass hook_class; -}; - -GType eab_popup_hook_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __EAB_POPUP_H__ */ diff --git a/addressbook/gui/widgets/eab-vcard-control.c b/addressbook/gui/widgets/eab-vcard-control.c deleted file mode 100644 index 1e890167f6..0000000000 --- a/addressbook/gui/widgets/eab-vcard-control.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include <config.h> -#include <string.h> - -#include <gtk/gtk.h> -#include <bonobo/bonobo-generic-factory.h> -#include <bonobo/bonobo-persist.h> -#include <bonobo/bonobo-persist-stream.h> -#include <bonobo/bonobo-stream-client.h> -#include <e-util/e-util.h> - -#include <libebook/e-book.h> -#include <libebook/e-contact.h> -#include <addressbook/gui/component/addressbook.h> -#include <addressbook/gui/widgets/eab-contact-display.h> -#include <addressbook/util/eab-book-util.h> - -#include "eab-vcard-control.h" -#include "eab-contact-merging.h" - -typedef struct { - EABContactDisplay *display; - GList *card_list; - GtkWidget *label; - EABContactDisplayRenderMode render_mode; -} EABVCardControl; - -#define VCARD_CONTROL_ID "OAFIID:GNOME_Evolution_Addressbook_VCard_Control:" BASE_VERSION - -/* - * Bonobo::PersistStream - * - * These two functions implement the Bonobo::PersistStream load and - * save methods which allow data to be loaded into and out of the - * BonoboObject. - */ -static char * -stream_read (Bonobo_Stream stream) -{ - Bonobo_Stream_iobuf *buffer; - CORBA_Environment ev; - char *data = NULL; - gint length = 0; - - CORBA_exception_init (&ev); - do { -#define READ_CHUNK_SIZE 65536 - Bonobo_Stream_read (stream, READ_CHUNK_SIZE, - &buffer, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - CORBA_exception_free (&ev); - return NULL; - } - - if (buffer->_length <= 0) - break; - - data = g_realloc (data, length + buffer->_length + 1); - - memcpy (data + length, buffer->_buffer, buffer->_length); - - length += buffer->_length; - - CORBA_free (buffer); - } while (1); - - CORBA_free (buffer); - CORBA_exception_free (&ev); - - if (data) - data[length] = '\0'; - else - data = g_strdup(""); - - return data; -} /* stream_read */ - -/* - * This function implements the Bonobo::PersistStream:load method. - */ -static void -pstream_load (BonoboPersistStream *ps, const Bonobo_Stream stream, - Bonobo_Persist_ContentType type, void *data, - CORBA_Environment *ev) -{ - GList *list; - char *vcard; - EABVCardControl *vcard_control = data; - - if (type && g_ascii_strcasecmp (type, "text/vCard") != 0 && - g_ascii_strcasecmp (type, "text/x-vCard") != 0) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_Bonobo_Persist_WrongDataType, NULL); - return; - } - - if ((vcard = stream_read (stream)) == NULL) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_Bonobo_Persist_FileNotFound, NULL); - return; - } - - g_list_foreach ( - vcard_control->card_list, - (GFunc) g_object_unref, NULL); - g_list_free (vcard_control->card_list); - - list = eab_contact_list_from_string (vcard); - g_free(vcard); - vcard_control->card_list = list; - if (list) { - eab_contact_display_render (vcard_control->display, E_CONTACT (list->data), - vcard_control->render_mode); - } - if (list && list->next) { - char *message; - int length = g_list_length (list) - 1; - message = g_strdup_printf (ngettext("There is one other contact.", - "There are %d other contacts.", length), - length); - gtk_label_set_text (GTK_LABEL (vcard_control->label), message); - g_free (message); - gtk_widget_show (vcard_control->label); - } else { - gtk_widget_hide (vcard_control->label); - } -} /* pstream_load */ - -/* - * This function implements the Bonobo::PersistStream:save method. - */ -static void -pstream_save (BonoboPersistStream *ps, const Bonobo_Stream stream, - Bonobo_Persist_ContentType type, void *data, - CORBA_Environment *ev) -{ - EABVCardControl *vcard_control = data; - char *vcard; - int length; - - if (type && g_ascii_strcasecmp (type, "text/vCard") != 0 && - g_ascii_strcasecmp (type, "text/x-vCard") != 0) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_Bonobo_Persist_WrongDataType, NULL); - return; - } - - vcard = eab_contact_list_to_string (vcard_control->card_list); - length = strlen (vcard); - bonobo_stream_client_write (stream, vcard, length, ev); - g_free (vcard); -} /* pstream_save */ - -static Bonobo_Persist_ContentTypeList * -pstream_get_content_types (BonoboPersistStream *ps, void *closure, - CORBA_Environment *ev) -{ - return bonobo_persist_generate_content_types (2, "text/vCard", "text/x-vCard"); -} - -static void -book_open_cb (EBook *book, EBookStatus status, gpointer closure) -{ - GList *list = closure; - if (status == E_BOOK_ERROR_OK) { - GList *p; - for (p = list; p; p = p->next) { - /* XXX argh, more passing of NULL's for callbacks */ - eab_merging_book_add_contact (book, E_CONTACT (p->data), NULL, NULL); - } - } - if (book) - g_object_unref (book); - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); -} - -static void -save_in_addressbook(GtkWidget *button, gpointer data) -{ - EABVCardControl *vcard_control = data; - GList *list, *p; - - list = g_list_copy (vcard_control->card_list); - - for (p = list; p; p = p->next) - g_object_ref (p->data); - - addressbook_load_default_book (book_open_cb, list); -} - -static void -toggle_full_vcard(GtkWidget *button, gpointer data) -{ - EABVCardControl *vcard_control = data; - char *label; - - if (!vcard_control->card_list) - return; - - if (vcard_control->render_mode == EAB_CONTACT_DISPLAY_RENDER_NORMAL) { - vcard_control->render_mode = EAB_CONTACT_DISPLAY_RENDER_COMPACT; - label = _("Show Full vCard"); - } - else { - vcard_control->render_mode = EAB_CONTACT_DISPLAY_RENDER_NORMAL; - label = _("Show Compact vCard"); - } - - gtk_button_set_label (GTK_BUTTON (button), label); - eab_contact_display_render (vcard_control->display, E_CONTACT (vcard_control->card_list->data), - vcard_control->render_mode); -} - -static void -free_struct (gpointer data, GObject *where_object_was) -{ - EABVCardControl *vcard_control = data; - - g_list_foreach ( - vcard_control->card_list, - (GFunc) g_object_unref, NULL); - g_list_free (vcard_control->card_list); - g_free (vcard_control); -} - -BonoboControl * -eab_vcard_control_new (void) -{ - BonoboControl *control; - BonoboPersistStream *stream; - GtkWidget *display; - GtkWidget *button1, *button2; - GtkWidget *bbox; - GtkWidget *vbox; - - EABVCardControl *vcard_control = g_new (EABVCardControl, 1); - - vcard_control->card_list = NULL; - vcard_control->display = NULL; - vcard_control->label = NULL; - - vcard_control->render_mode = EAB_CONTACT_DISPLAY_RENDER_COMPACT; - - /* Create the control. */ - - display = eab_contact_display_new (); - vcard_control->display = EAB_CONTACT_DISPLAY (display); - - bbox = gtk_hbutton_box_new (); - gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_START); - gtk_box_set_spacing (GTK_BOX (bbox), 12); - - button1 = gtk_button_new_with_label(_("Show Full vCard")); - g_signal_connect (button1, "clicked", - G_CALLBACK (toggle_full_vcard), vcard_control); - gtk_box_pack_start (GTK_BOX (bbox), button1, FALSE, FALSE, 0); - - button2 = gtk_button_new_with_label(_("Save in address book")); - g_signal_connect (button2, "clicked", - G_CALLBACK (save_in_addressbook), vcard_control); - gtk_box_pack_start (GTK_BOX (bbox), button2, FALSE, FALSE, 0); - - /* This is intentionally not shown. */ - vcard_control->label = gtk_label_new (""); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), display, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (vbox), vcard_control->label, TRUE, TRUE, 0); - gtk_widget_show_all (bbox); - gtk_widget_show (display); - gtk_widget_show (vbox); - - control = bonobo_control_new (vbox); - - g_object_weak_ref (G_OBJECT (control), free_struct, vcard_control); - - stream = bonobo_persist_stream_new (pstream_load, pstream_save, - pstream_get_content_types, - VCARD_CONTROL_ID, - vcard_control); - - if (stream == NULL) { - bonobo_object_unref (BONOBO_OBJECT (control)); - return NULL; - } - - bonobo_object_add_interface (BONOBO_OBJECT (control), - BONOBO_OBJECT (stream)); - - return control; -} diff --git a/addressbook/gui/widgets/eab-vcard-control.h b/addressbook/gui/widgets/eab-vcard-control.h deleted file mode 100644 index 06ca62727a..0000000000 --- a/addressbook/gui/widgets/eab-vcard-control.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EAB_VCARD_CONTROL_H__ -#define __EAB_VCARD_CONTROL_H__ - -#include <bonobo/bonobo-control.h> - -BonoboControl *eab_vcard_control_new (void); - -#endif /* __EAB_VCARD_CONTROL_H__ */ diff --git a/addressbook/gui/widgets/gal-view-minicard.c b/addressbook/gui/widgets/gal-view-minicard.c index 4645517bfc..cb2f52f4ff 100644 --- a/addressbook/gui/widgets/gal-view-minicard.c +++ b/addressbook/gui/widgets/gal-view-minicard.c @@ -26,115 +26,172 @@ #include <config.h> #include <libxml/parser.h> - -#include <libedataserver/e-xml-utils.h> - #include <e-util/e-xml-utils.h> +#include <libedataserver/e-xml-utils.h> #include "gal-view-minicard.h" -#define PARENT_TYPE gal_view_get_type () -#define d(x) +static gpointer parent_class; + +static void +view_minicard_column_width_changed (EAddressbookView *address_view, + gdouble width) +{ + GalView *view; + GalViewInstance *view_instance; + GalViewMinicard *view_minicard; + GtkScrolledWindow *scrolled_window; + GtkAdjustment *adjustment; + GtkWidget *widget; + gdouble value, lower, upper; + gdouble page_increment, page_size; + + view_instance = e_addressbook_view_get_view_instance (address_view); + view = gal_view_instance_get_current_view (view_instance); + view_minicard = GAL_VIEW_MINICARD (view); + + if (view_minicard->column_width != width) { + view_minicard->column_width = width; + gal_view_changed (view); + } + + widget = e_addressbook_view_get_view_widget (address_view); + scrolled_window = GTK_SCROLLED_WINDOW (widget); + adjustment = gtk_scrolled_window_get_hadjustment (scrolled_window); + + value = gtk_adjustment_get_value (adjustment); + lower = gtk_adjustment_get_lower (adjustment); + upper = gtk_adjustment_get_upper (adjustment); + page_increment = gtk_adjustment_get_page_increment (adjustment); + page_size = gtk_adjustment_get_page_size (adjustment); + + adjustment = GTK_ADJUSTMENT (gtk_adjustment_new ( + value, lower, upper, page_size, page_increment, page_size)); + gtk_scrolled_window_set_hadjustment (scrolled_window, adjustment); +} + +static void +view_minicard_finalize (GObject *object) +{ + GalViewMinicard *view = GAL_VIEW_MINICARD (object); + + if (view->title != NULL) { + gal_view_minicard_detach (view); + g_free (view->title); + view->title = NULL; + } -static GalViewClass *gal_view_minicard_parent_class; + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} static void -gal_view_minicard_load (GalView *view, - const char *filename) +view_minicard_load (GalView *view, + const gchar *filename) { + GalViewMinicard *view_minicard; xmlDoc *doc; + xmlNode *root; + + view_minicard = GAL_VIEW_MINICARD (view); doc = e_xml_parse_file (filename); - if (doc) { - xmlNode *root = xmlDocGetRootElement(doc); - GAL_VIEW_MINICARD (view)->column_width = e_xml_get_double_prop_by_name_with_default (root, (const unsigned char *)"column_width", 150); - xmlFreeDoc(doc); - } + g_return_if_fail (doc != NULL); + + root = xmlDocGetRootElement (doc); + view_minicard->column_width = + e_xml_get_double_prop_by_name_with_default ( + root, (guchar *) "column_width", 150); + xmlFreeDoc (doc); } static void -gal_view_minicard_save (GalView *view, - const char *filename) +view_minicard_save (GalView *view, + const gchar *filename) { + GalViewMinicard *view_minicard; xmlDoc *doc; xmlNode *root; - doc = xmlNewDoc((const unsigned char *)"1.0"); - root = xmlNewNode (NULL, (const unsigned char *)"EMinicardViewState"); - e_xml_set_double_prop_by_name (root, (const unsigned char *)"column_width", GAL_VIEW_MINICARD (view)->column_width); - xmlDocSetRootElement(doc, root); + view_minicard = GAL_VIEW_MINICARD (view); + + doc = xmlNewDoc ((guchar *) "1.0"); + root = xmlNewNode (NULL, (guchar *) "EMinicardViewState"); + e_xml_set_double_prop_by_name ( + root, (guchar *) "column_width", + view_minicard->column_width); + xmlDocSetRootElement (doc, root); e_xml_save_file (filename, doc); - xmlFreeDoc(doc); + xmlFreeDoc (doc); } -static const char * -gal_view_minicard_get_title (GalView *view) +static const gchar * +view_minicard_get_title (GalView *view) { - return GAL_VIEW_MINICARD(view)->title; + GalViewMinicard *view_minicard; + + view_minicard = GAL_VIEW_MINICARD (view); + + return view_minicard->title; } static void -gal_view_minicard_set_title (GalView *view, - const char *title) +view_minicard_set_title (GalView *view, + const char *title) { - g_free(GAL_VIEW_MINICARD(view)->title); - GAL_VIEW_MINICARD(view)->title = g_strdup(title); + GalViewMinicard *view_minicard; + + view_minicard = GAL_VIEW_MINICARD (view); + + g_free (view_minicard->title); + view_minicard->title = g_strdup (title); } -static const char * -gal_view_minicard_get_type_code (GalView *view) +static const gchar * +view_minicard_get_type_code (GalView *view) { return "minicard"; } static GalView * -gal_view_minicard_clone (GalView *view) +view_minicard_clone (GalView *view) { - GalViewMinicard *gvm, *new; + GalViewMinicard *view_minicard; + GalViewMinicard *clone; - gvm = GAL_VIEW_MINICARD(view); + view_minicard = GAL_VIEW_MINICARD(view); - new = g_object_new (GAL_TYPE_VIEW_MINICARD, NULL); - new->title = g_strdup (gvm->title); - new->column_width = gvm->column_width; + clone = g_object_new (GAL_TYPE_VIEW_MINICARD, NULL); + clone->column_width = view_minicard->column_width; + clone->title = g_strdup (view_minicard->title); - return GAL_VIEW(new); + return GAL_VIEW (clone); } static void -gal_view_minicard_dispose (GObject *object) +gal_view_minicard_class_init (GalViewMinicardClass *class) { - GalViewMinicard *view = GAL_VIEW_MINICARD(object); + GObjectClass *object_class; + GalViewClass *gal_view_class; - if (view->title != NULL) { - gal_view_minicard_detach (view); - g_free(view->title); - view->title = NULL; - } + parent_class = g_type_class_peek_parent (class); - if (G_OBJECT_CLASS (gal_view_minicard_parent_class)->dispose) - (* G_OBJECT_CLASS (gal_view_minicard_parent_class)->dispose) (object); -} + object_class = G_OBJECT_CLASS (class); + object_class->dispose = view_minicard_finalize; + + gal_view_class = GAL_VIEW_CLASS (class); + gal_view_class->edit = NULL; + gal_view_class->load = view_minicard_load; + gal_view_class->save = view_minicard_save; + gal_view_class->get_title = view_minicard_get_title; + gal_view_class->set_title = view_minicard_set_title; + gal_view_class->get_type_code = view_minicard_get_type_code; + gal_view_class->clone = view_minicard_clone; -static void -gal_view_minicard_class_init (GObjectClass *object_class) -{ - GalViewClass *gal_view_class = GAL_VIEW_CLASS(object_class); - gal_view_minicard_parent_class = g_type_class_ref (PARENT_TYPE); - - gal_view_class->edit = NULL ; - gal_view_class->load = gal_view_minicard_load ; - gal_view_class->save = gal_view_minicard_save ; - gal_view_class->get_title = gal_view_minicard_get_title ; - gal_view_class->set_title = gal_view_minicard_set_title ; - gal_view_class->get_type_code = gal_view_minicard_get_type_code; - gal_view_class->clone = gal_view_minicard_clone ; - - object_class->dispose = gal_view_minicard_dispose ; } static void -gal_view_minicard_init (GalViewMinicard *gvm) +gal_view_minicard_init (GalViewMinicard *gvm) { gvm->title = NULL; gvm->column_width = 150.0; @@ -143,6 +200,32 @@ gal_view_minicard_init (GalViewMinicard *gvm) gvm->emvw_column_width_changed_id = 0; } +GType +gal_view_minicard_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (GalViewMinicardClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_view_minicard_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalViewMinicard), + 0, /* n_preallocs */ + (GInstanceInitFunc) gal_view_minicard_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GAL_VIEW_TYPE, "GalViewMinicard", &type_info, 0); + } + + return type; +} + /** * gal_view_minicard_new * @title: The name of the new view. @@ -155,7 +238,8 @@ gal_view_minicard_init (GalViewMinicard *gvm) GalView * gal_view_minicard_new (const gchar *title) { - return gal_view_minicard_construct (g_object_new (GAL_TYPE_VIEW_MINICARD, NULL), title); + return gal_view_minicard_construct ( + g_object_new (GAL_TYPE_VIEW_MINICARD, NULL), title); } /** @@ -163,7 +247,7 @@ gal_view_minicard_new (const gchar *title) * @view: The view to construct. * @title: The name of the new view. * - * constructs the GalViewMinicard. To be used by subclasses and + * Constructs the GalViewMinicard. To be used by subclasses and * language bindings. * * Returns: The GalViewMinicard. @@ -172,85 +256,49 @@ GalView * gal_view_minicard_construct (GalViewMinicard *view, const gchar *title) { - view->title = g_strdup(title); - return GAL_VIEW(view); -} - -GType -gal_view_minicard_get_type (void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (GalViewMinicardClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) gal_view_minicard_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GalViewMinicard), - 0, /* n_preallocs */ - (GInstanceInitFunc) gal_view_minicard_init, - }; + view->title = g_strdup (title); - type = g_type_register_static (PARENT_TYPE, "GalViewMinicard", &info, 0); - } - - return type; + return GAL_VIEW (view); } -static void -column_width_changed (EMinicardViewWidget *w, double width, EABView *address_view) +void +gal_view_minicard_attach (GalViewMinicard *view, + EAddressbookView *address_view) { - GalViewMinicard *view = GAL_VIEW_MINICARD (gal_view_instance_get_current_view (address_view->view_instance)); - GtkScrolledWindow *scrolled_window; - GtkAdjustment *adj; - GtkAdjustment *adj_new; + GObject *object; - d(g_print("%s: Old width = %f, New width = %f\n", G_STRFUNC, view->column_width, width)); - if (view->column_width != width) { - view->column_width = width; - gal_view_changed(GAL_VIEW(view)); - } + g_return_if_fail (GAL_IS_VIEW_MINICARD (view)); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (address_view)); - scrolled_window = GTK_SCROLLED_WINDOW (address_view->widget); - adj = gtk_scrolled_window_get_hadjustment (scrolled_window); - adj_new = GTK_ADJUSTMENT (gtk_adjustment_new (adj->value, adj->lower, adj->upper, - adj->page_size, adj->page_increment, - adj->page_size)); - gtk_scrolled_window_set_hadjustment (scrolled_window, adj_new); -} + object = e_addressbook_view_get_view_object (address_view); + g_return_if_fail (E_IS_MINICARD_VIEW_WIDGET (object)); -void -gal_view_minicard_attach (GalViewMinicard *view, EABView *address_view) -{ - EMinicardViewWidget *emvw = E_MINICARD_VIEW_WIDGET (address_view->object); gal_view_minicard_detach (view); + view->emvw = g_object_ref (object); - view->emvw = emvw; - - g_object_ref (view->emvw); - - g_object_set (view->emvw, - "column_width", view->column_width, - NULL); + g_object_set (view->emvw, "column-width", view->column_width, NULL); view->emvw_column_width_changed_id = - g_signal_connect(view->emvw, "column_width_changed", - G_CALLBACK (column_width_changed), address_view); + g_signal_connect_swapped ( + view->emvw, "column-width-changed", + G_CALLBACK (view_minicard_column_width_changed), + address_view); } void gal_view_minicard_detach (GalViewMinicard *view) { + g_return_if_fail (GAL_IS_VIEW_MINICARD (view)); + if (view->emvw == NULL) return; - if (view->emvw_column_width_changed_id) { - g_signal_handler_disconnect (view->emvw, - view->emvw_column_width_changed_id); + + if (view->emvw_column_width_changed_id > 0) { + g_signal_handler_disconnect ( + view->emvw, view->emvw_column_width_changed_id); view->emvw_column_width_changed_id = 0; } + g_object_unref (view->emvw); view->emvw = NULL; } diff --git a/addressbook/gui/widgets/gal-view-minicard.h b/addressbook/gui/widgets/gal-view-minicard.h index bb22cf8a57..6e1a0ca68e 100644 --- a/addressbook/gui/widgets/gal-view-minicard.h +++ b/addressbook/gui/widgets/gal-view-minicard.h @@ -22,40 +22,59 @@ * */ -#ifndef _GAL_VIEW_MINICARD_H_ -#define _GAL_VIEW_MINICARD_H_ +#ifndef GAL_VIEW_MINICARD_H +#define GAL_VIEW_MINICARD_H #include <widgets/menus/gal-view.h> #include <e-minicard-view-widget.h> #include "e-addressbook-view.h" -#define GAL_TYPE_VIEW_MINICARD (gal_view_minicard_get_type ()) -#define GAL_VIEW_MINICARD(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GAL_TYPE_VIEW_MINICARD, GalViewMinicard)) -#define GAL_VIEW_MINICARD_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GAL_TYPE_VIEW_MINICARD, GalViewMinicardClass)) -#define GAL_IS_VIEW_MINICARD(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GAL_TYPE_VIEW_MINICARD)) -#define GAL_IS_VIEW_MINICARD_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GAL_TYPE_VIEW_MINICARD)) +/* Standard GObject macros */ +#define GAL_TYPE_VIEW_MINICARD \ + (gal_view_minicard_get_type ()) +#define GAL_VIEW_MINICARD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), GAL_TYPE_VIEW_MINICARD, GalViewMinicard)) +#define GAL_VIEW_MINICARD_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), GAL_TYPE_VIEW_MINICARD, GalViewMinicardClass)) +#define GAL_IS_VIEW_MINICARD(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), GAL_TYPE_VIEW_MINICARD)) +#define GAL_IS_VIEW_MINICARD_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), GAL_TYPE_VIEW_MINICARD)) +#define GAL_VIEW_MINICARD_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), GAL_TYPE_VIEW_MINICARD, GalViewMinicardClass)) -typedef struct { - GalView base; +G_BEGIN_DECLS + +typedef struct _GalViewMinicard GalViewMinicard; +typedef struct _GalViewMinicardClass GalViewMinicardClass; + +struct _GalViewMinicard { + GalView parent; char *title; double column_width; EMinicardViewWidget *emvw; guint emvw_column_width_changed_id; -} GalViewMinicard; +}; -typedef struct { +struct _GalViewMinicardClass { GalViewClass parent_class; -} GalViewMinicardClass; - -/* Standard functions */ -GType gal_view_minicard_get_type (void); -GalView *gal_view_minicard_new (const gchar *title); -GalView *gal_view_minicard_construct (GalViewMinicard *view, - const gchar *title); -void gal_view_minicard_attach (GalViewMinicard *view, - EABView *address_view); -void gal_view_minicard_detach (GalViewMinicard *view); - -#endif /* _GAL_VIEW_MINICARD_H_ */ +}; + +GType gal_view_minicard_get_type (void); +GalView * gal_view_minicard_new (const gchar *title); +GalView * gal_view_minicard_construct (GalViewMinicard *view, + const gchar *title); +void gal_view_minicard_attach (GalViewMinicard *view, + EAddressbookView *address_view); +void gal_view_minicard_detach (GalViewMinicard *view); + +G_END_DECLS + +#endif /* GAL_VIEW_MINICARD_H */ |