[anjal] Messave view shows contact's photo



commit 65950f99e541993daf3fe0b452d6abafd4e09872
Author: Srinivasa Ragavan <sragavan novell com>
Date:   Fri Jul 17 13:37:29 2009 +0530

    Messave view shows contact's photo

 src/mail-conv-view.c    |    6 +-
 src/mail-message-view.c |    1 +
 src/mail-utils.c        |  232 +++++++++++++++++++++++++++++++++++++++++++++++
 src/mail-utils.h        |    3 +
 4 files changed, 239 insertions(+), 3 deletions(-)
---
diff --git a/src/mail-conv-view.c b/src/mail-conv-view.c
index 4cb2db2..847e4c7 100644
--- a/src/mail-conv-view.c
+++ b/src/mail-conv-view.c
@@ -63,9 +63,9 @@ mail_conv_view_init (MailConvView  *shell)
 static void
 mail_conv_view_finalize (GObject *object)
 {
-MailConvView *shell = (MailConvView *)object;
-MailConvViewPrivate *priv = shell->priv;
-	
+	MailConvView *shell = (MailConvView *)object;
+	MailConvViewPrivate *priv = shell->priv;
+
 	g_free (priv);
 	
 	G_OBJECT_CLASS (mail_conv_view_parent_class)->finalize (object);
diff --git a/src/mail-message-view.c b/src/mail-message-view.c
index a3c0ba2..168639f 100644
--- a/src/mail-message-view.c
+++ b/src/mail-message-view.c
@@ -1195,6 +1195,7 @@ mail_message_view_set_message (MailMessageView *mmview, CamelFolder *folder, con
 	mmview->main_header = gtk_hbox_new (FALSE, 12);
 	tmp = gtk_image_new_from_icon_name ("stock_person", GTK_ICON_SIZE_DIALOG);
 	gtk_widget_show(tmp);
+	mail_util_fill_photo (tmp, camel_message_info_from(info));
 	gtk_box_pack_start ((GtkBox *)GTK_BOX (mmview->main_header), tmp, FALSE, FALSE, 3);
 
 	mmview->priv->table_headers = (GtkWidget *)table;
diff --git a/src/mail-utils.c b/src/mail-utils.c
index ebcdb1b..cd2a7e7 100644
--- a/src/mail-utils.c
+++ b/src/mail-utils.c
@@ -20,7 +20,13 @@
  *
  */
 
+#include <glib/gi18n.h>
 #include <mail-utils.h>
+#include <libebook/e-book.h>
+#include <libedataserver/e-flag.h>
+#include <camel/camel-operation.h>
+#include <camel/camel-internet-address.h>
+#include <mail/mail-mt.h>
 
 static GtkIconTheme *theme = NULL;
 
@@ -56,3 +62,229 @@ mail_utils_get_icon_path (const char *icon, int icon_size)
 	return file;
 }
 
+static EBook *default_book = NULL;
+GStaticMutex booklock = G_STATIC_MUTEX_INIT;
+static GHashTable *contact_pixbuf_cache = NULL;
+
+struct TryOpenEBookStruct {
+	GError **error;
+	EFlag *flag;
+	gboolean result;
+};
+
+static void
+try_open_e_book_cb (EBook *book, EBookStatus status, gpointer closure)
+{
+	struct TryOpenEBookStruct *data = (struct TryOpenEBookStruct *)closure;
+
+	if (!data)
+		return;
+
+	data->result = status == E_BOOK_ERROR_OK;
+
+	if (!data->result) {
+		g_clear_error (data->error);
+		g_set_error (data->error, E_BOOK_ERROR, status, "EBookStatus returned %d", status);
+	}
+
+	e_flag_set (data->flag);
+}
+
+/**
+ * try_open_e_book:
+ * Tries to open address book asynchronously, but acts as synchronous.
+ * The advantage is it checks periodically whether the camel_operation
+ * has been canceled or not, and if so, then stops immediately, with
+ * result FALSE. Otherwise returns same as e_book_open
+ **/
+static gboolean
+try_open_e_book (EBook *book, gboolean only_if_exists, GError **error)
+{
+	struct TryOpenEBookStruct data;
+	gboolean canceled = FALSE;
+	EFlag *flag = e_flag_new ();
+
+	data.error = error;
+	data.flag = flag;
+	data.result = FALSE;
+	
+	if (e_book_async_open (book, only_if_exists, try_open_e_book_cb, &data) != FALSE) {
+		e_flag_free (flag);
+		g_clear_error (error);
+		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_OTHER_ERROR, "Failed to call e_book_async_open.");
+		return FALSE;
+	}
+
+	while (canceled = camel_operation_cancel_check (NULL), !canceled && !e_flag_is_set (flag)) {
+		GTimeVal wait;
+
+		g_get_current_time (&wait);
+		g_time_val_add (&wait, 250000); /* waits 250ms */
+
+		e_flag_timed_wait (flag, &wait);
+	}
+
+	if (canceled) {
+		g_clear_error (error);
+		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_CANCELLED, "Operation has been canceled.");
+		e_book_cancel_async_op (book, NULL);
+		/* it had been canceled, the above callback may not be called, thus setting flag here */
+		e_flag_set (flag);
+	}
+
+	e_flag_wait (flag);
+	e_flag_free (flag);
+
+	return data.result && (!error || !*error);
+}
+
+static EContact *
+mu_get_contact (const char *addr)
+{
+	GError *error = NULL;
+	GList *contacts = NULL;
+	EContact *contact;
+	EBookQuery *query;
+
+	if (!default_book) {
+		default_book = e_book_new_default_addressbook (&error);
+		contact_pixbuf_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+
+		if (!try_open_e_book (default_book, TRUE, &error)) {
+			default_book = NULL;
+			g_message ("Unable to open addressbook: %s\n", error->message);
+			return NULL;
+		}
+	}
+
+	query = e_book_query_field_test(E_CONTACT_EMAIL, E_BOOK_QUERY_IS, addr);
+	
+	if (!e_book_get_contacts(default_book, query, &contacts, &error)) {
+		g_message ("Unable to get contacts: %s\n", error->message);
+		return NULL;
+	}
+
+	if (contacts) {
+		contact = contacts->data;
+		g_object_ref(contact);
+		g_list_foreach (contacts, (GFunc)g_object_unref, NULL);
+		g_list_free (contacts);
+	} else {
+		printf("Unable to get contact for %s\n", addr);
+	}
+
+	return contact;
+}
+
+struct _mail_contact_msg {
+	MailMsg base;
+
+	GtkWidget *widget;
+	char *address;
+	EContact *contact;
+	GdkPixbuf *pixbuf;
+};
+
+static gchar *
+mu_contact_desc (struct _mail_contact_msg *m)
+{
+	return g_strdup(_("Rendering image"));
+}
+
+static void
+mu_contact_exec (struct _mail_contact_msg *m)
+{
+	g_static_mutex_lock (&booklock);
+	if (!contact_pixbuf_cache || !g_hash_table_lookup_extended (contact_pixbuf_cache, m->address, NULL, (gpointer)&m->pixbuf)) {
+		m->contact = mu_get_contact (m->address);
+
+		if (m->contact) {
+			EContactPhoto *photo;
+
+			photo = e_contact_get (m->contact, E_CONTACT_PHOTO);
+			if (!photo)
+				photo = e_contact_get (m->contact, E_CONTACT_LOGO);
+			if (photo && photo->type == E_CONTACT_PHOTO_TYPE_INLINED) {
+				GdkPixbufLoader *loader = gdk_pixbuf_loader_new_with_mime_type ("image/png", NULL);
+				GdkPixbuf *pbuf;
+	
+				gdk_pixbuf_loader_set_size (loader, 72, 72);
+				gdk_pixbuf_loader_write (loader, photo->data.inlined.data, photo->data.inlined.length, NULL);
+				gdk_pixbuf_loader_close (loader, NULL);
+				e_contact_photo_free (photo);
+	
+				pbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+				m->pixbuf = pbuf;
+
+				g_object_ref (pbuf);
+				g_hash_table_insert (contact_pixbuf_cache, g_strdup(m->address), pbuf);
+
+				m->address = NULL; /* Saved one free/alloc cycle */
+	
+				g_object_unref (loader);
+			} else if (photo && photo->type == E_CONTACT_PHOTO_TYPE_URI) {
+				/* Handle URI */
+			}
+		} else
+			g_hash_table_insert (contact_pixbuf_cache, g_strdup(m->address), NULL);
+	} 
+	g_static_mutex_unlock (&booklock);
+
+}
+
+static void
+mu_contact_done (struct _mail_contact_msg *m)
+{
+	if (m->pixbuf) {
+		gtk_image_set_from_pixbuf((GtkImage *)m->widget, m->pixbuf);
+	}
+}
+
+static void
+mu_contact_free (struct _mail_contact_msg *m)
+{
+	if (m->contact)
+		g_object_unref (m->contact);
+	g_free (m->address);
+}
+
+static MailMsgInfo mail_contact_info = {
+	sizeof (struct _mail_contact_msg),
+	(MailMsgDescFunc) mu_contact_desc,
+	(MailMsgExecFunc) mu_contact_exec,
+	(MailMsgDoneFunc) mu_contact_done,
+	(MailMsgFreeFunc) mu_contact_free
+};
+
+
+int
+mail_util_fill_photo (GtkWidget *widget, const char *address)
+{
+	struct _mail_contact_msg *m;
+	gint id;
+	CamelInternetAddress *cia;
+	const char *email;
+
+	cia = camel_internet_address_new();
+	camel_address_decode((CamelAddress *) cia, (const gchar *) address);
+
+	m = mail_msg_new (&mail_contact_info);
+
+	m->widget = widget;
+	camel_internet_address_get(cia, 0, NULL, &email);
+	m->address = g_strdup(email);
+	camel_object_unref(cia);
+	id = m->base.seq;
+	mail_msg_unordered_push (m);
+
+	return id;
+}
+
+void
+mail_util_clear_photo_cache ()
+{
+	g_static_mutex_lock (&booklock);
+	g_hash_table_remove_all (contact_pixbuf_cache);
+	g_static_mutex_unlock (&booklock);
+
+}
diff --git a/src/mail-utils.h b/src/mail-utils.h
index 1e703e2..b572651 100644
--- a/src/mail-utils.h
+++ b/src/mail-utils.h
@@ -27,4 +27,7 @@
 
 GdkPixbuf * mail_utils_get_icon (const char *icon, int icon_size);
 char * mail_utils_get_icon_path (const char *icon, int icon_size);
+void mail_util_clear_photo_cache (void);
+int mail_util_fill_photo (GtkWidget *widget, const char *address);
+
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]