aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy-gtk
diff options
context:
space:
mode:
authorTravis Reitter <treitter@gmail.com>2010-06-12 04:22:38 +0800
committerTravis Reitter <treitter@gmail.com>2010-07-21 07:12:35 +0800
commit48a9944fd9f3b4461a239d2da490fba24874df80 (patch)
tree50c6dced199adadfe3bd45f14df6a7ab139f1d54 /libempathy-gtk
parentd6aa2f99e3e626f81b455c0fa1ff4817a4e4f2f6 (diff)
downloadgsoc2013-empathy-48a9944fd9f3b4461a239d2da490fba24874df80.tar
gsoc2013-empathy-48a9944fd9f3b4461a239d2da490fba24874df80.tar.gz
gsoc2013-empathy-48a9944fd9f3b4461a239d2da490fba24874df80.tar.bz2
gsoc2013-empathy-48a9944fd9f3b4461a239d2da490fba24874df80.tar.lz
gsoc2013-empathy-48a9944fd9f3b4461a239d2da490fba24874df80.tar.xz
gsoc2013-empathy-48a9944fd9f3b4461a239d2da490fba24874df80.tar.zst
gsoc2013-empathy-48a9944fd9f3b4461a239d2da490fba24874df80.zip
Implement avatar support.
Diffstat (limited to 'libempathy-gtk')
-rw-r--r--libempathy-gtk/empathy-individual-store.c33
-rw-r--r--libempathy-gtk/empathy-ui-utils.c159
-rw-r--r--libempathy-gtk/empathy-ui-utils.h9
3 files changed, 170 insertions, 31 deletions
diff --git a/libempathy-gtk/empathy-individual-store.c b/libempathy-gtk/empathy-individual-store.c
index 4fed77aaf..0e3dd259e 100644
--- a/libempathy-gtk/empathy-individual-store.c
+++ b/libempathy-gtk/empathy-individual-store.c
@@ -528,6 +528,24 @@ individual_store_contact_active_cb (ShowActiveData *data)
}
static void
+individual_avatar_pixbuf_received_cb (FolksIndividual *individual,
+ GdkPixbuf *pixbuf,
+ gpointer user_data)
+{
+ EmpathyIndividualStore *self = user_data;
+ GList *iters, *l;
+
+ iters = individual_store_find_contact (self, individual);
+
+ for (l = iters; l; l = l->next)
+ {
+ gtk_tree_store_set (GTK_TREE_STORE (self), l->data,
+ EMPATHY_INDIVIDUAL_STORE_COL_PIXBUF_AVATAR, pixbuf,
+ -1);
+ }
+}
+
+static void
individual_store_contact_update (EmpathyIndividualStore *self,
FolksIndividual *individual)
{
@@ -544,7 +562,6 @@ individual_store_contact_update (EmpathyIndividualStore *self,
gboolean do_set_active = FALSE;
gboolean do_set_refresh = FALSE;
gboolean show_avatar = FALSE;
- GdkPixbuf *pixbuf_avatar;
GdkPixbuf *pixbuf_status;
priv = GET_PRIV (self);
@@ -657,17 +674,16 @@ individual_store_contact_update (EmpathyIndividualStore *self,
{
show_avatar = TRUE;
}
- /* TODO: implement */
- DEBUG ("avatars unimplemented");
+
+ empathy_pixbuf_avatar_from_individual_scaled_async (individual, 32, 32,
+ individual_avatar_pixbuf_received_cb, self);
pixbuf_status =
empathy_individual_store_get_individual_status_icon (self, individual);
- pixbuf_avatar = NULL;
for (l = iters; l && set_model; l = l->next)
{
gtk_tree_store_set (GTK_TREE_STORE (self), l->data,
EMPATHY_INDIVIDUAL_STORE_COL_ICON_STATUS, pixbuf_status,
- EMPATHY_INDIVIDUAL_STORE_COL_PIXBUF_AVATAR, pixbuf_avatar,
EMPATHY_INDIVIDUAL_STORE_COL_PIXBUF_AVATAR_VISIBLE, show_avatar,
EMPATHY_INDIVIDUAL_STORE_COL_NAME,
folks_individual_get_alias (individual),
@@ -687,11 +703,6 @@ individual_store_contact_update (EmpathyIndividualStore *self,
EMPATHY_INDIVIDUAL_STORE_COL_IS_SEPARATOR, FALSE, -1);
}
- if (pixbuf_avatar)
- {
- g_object_unref (pixbuf_avatar);
- }
-
if (priv->show_active && do_set_active)
{
individual_store_contact_set_active (self, individual, do_set_active,
@@ -731,6 +742,8 @@ static void
individual_store_add_individual_and_connect (EmpathyIndividualStore *self,
FolksIndividual *individual)
{
+ g_signal_connect (individual, "notify::avatar",
+ G_CALLBACK (individual_store_contact_updated_cb), self);
g_signal_connect (individual, "notify::presence-type",
G_CALLBACK (individual_store_contact_updated_cb), self);
g_signal_connect (individual, "notify::presence-message",
diff --git a/libempathy-gtk/empathy-ui-utils.c b/libempathy-gtk/empathy-ui-utils.c
index 93c08d1c5..83fbc636e 100644
--- a/libempathy-gtk/empathy-ui-utils.c
+++ b/libempathy-gtk/empathy-ui-utils.c
@@ -436,6 +436,35 @@ empathy_gdk_pixbuf_is_opaque (GdkPixbuf *pixbuf)
return TRUE;
}
+static GdkPixbuf *
+avatar_pixbuf_from_loader (GdkPixbufLoader *loader)
+{
+ GdkPixbuf *pixbuf;
+
+ pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ if (!gdk_pixbuf_get_has_alpha (pixbuf)) {
+ GdkPixbuf *rounded_pixbuf;
+
+ rounded_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+ gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf));
+ gdk_pixbuf_copy_area (pixbuf, 0, 0,
+ gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf),
+ rounded_pixbuf,
+ 0, 0);
+ pixbuf = rounded_pixbuf;
+ } else {
+ g_object_ref (pixbuf);
+ }
+
+ if (empathy_gdk_pixbuf_is_opaque (pixbuf)) {
+ empathy_avatar_pixbuf_roundify (pixbuf);
+ }
+
+ return pixbuf;
+}
+
GdkPixbuf *
empathy_pixbuf_from_avatar_scaled (EmpathyAvatar *avatar,
gint width,
@@ -469,27 +498,7 @@ empathy_pixbuf_from_avatar_scaled (EmpathyAvatar *avatar,
}
gdk_pixbuf_loader_close (loader, NULL);
-
- pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
- if (!gdk_pixbuf_get_has_alpha (pixbuf)) {
- GdkPixbuf *rounded_pixbuf;
-
- rounded_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
- gdk_pixbuf_get_width (pixbuf),
- gdk_pixbuf_get_height (pixbuf));
- gdk_pixbuf_copy_area (pixbuf, 0, 0,
- gdk_pixbuf_get_width (pixbuf),
- gdk_pixbuf_get_height (pixbuf),
- rounded_pixbuf,
- 0, 0);
- pixbuf = rounded_pixbuf;
- } else {
- g_object_ref (pixbuf);
- }
-
- if (empathy_gdk_pixbuf_is_opaque (pixbuf)) {
- empathy_avatar_pixbuf_roundify (pixbuf);
- }
+ pixbuf = avatar_pixbuf_from_loader (loader);
g_object_unref (loader);
@@ -510,6 +519,114 @@ empathy_pixbuf_avatar_from_contact_scaled (EmpathyContact *contact,
return empathy_pixbuf_from_avatar_scaled (avatar, width, height);
}
+typedef struct {
+ FolksIndividual *individual;
+ EmpathyPixbufAvatarFromIndividualCb callback;
+ gpointer user_data;
+ guint width;
+ guint height;
+} PixbufAvatarFromIndividualClosure;
+
+static void
+pixbuf_avatar_from_individual_closure_free (
+ PixbufAvatarFromIndividualClosure *closure)
+{
+ g_object_unref (closure->individual);
+ g_free (closure);
+}
+
+static void
+avatar_file_load_contents_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GFile *file = G_FILE (object);
+ PixbufAvatarFromIndividualClosure *closure = user_data;
+ char *data;
+ gsize data_size;
+ struct SizeData size_data;
+ GError *error = NULL;
+ GdkPixbufLoader *loader = NULL;
+ GdkPixbuf *pixbuf = NULL;
+
+ if (!g_file_load_contents_finish (file, result, &data, &data_size,
+ NULL, &error)) {
+ DEBUG ("failed to load avatar from file: %s",
+ error->message);
+ goto out;
+ }
+
+ size_data.width = closure->width;
+ size_data.height = closure->height;
+ size_data.preserve_aspect_ratio = TRUE;
+
+ loader = gdk_pixbuf_loader_new ();
+
+ /* XXX: this seems a bit racy, but apparently works well enough */
+ g_signal_connect (loader, "size-prepared",
+ G_CALLBACK (pixbuf_from_avatar_size_prepared_cb),
+ &size_data);
+
+ if (!gdk_pixbuf_loader_write (loader, (guchar *) data, data_size,
+ &error)) {
+ DEBUG ("Failed to write to pixbuf loader: %s",
+ error ? error->message : "No error given");
+ goto out;
+ }
+ if (!gdk_pixbuf_loader_close (loader, &error)) {
+ DEBUG ("Failed to close pixbuf loader: %s",
+ error ? error->message : "No error given");
+ goto out;
+ }
+
+ pixbuf = avatar_pixbuf_from_loader (loader);
+
+ closure->callback (closure->individual, pixbuf, closure->user_data);
+
+out:
+ g_clear_error (&error);
+ g_free (data);
+ if (loader != NULL)
+ g_object_unref (loader);
+ pixbuf_avatar_from_individual_closure_free (closure);
+}
+
+void
+empathy_pixbuf_avatar_from_individual_scaled_async (FolksIndividual *individual,
+ gint width,
+ gint height,
+ EmpathyPixbufAvatarFromIndividualCb callback,
+ gpointer user_data)
+{
+ GFile *avatar_file;
+ PixbufAvatarFromIndividualClosure *closure;
+
+ if (!FOLKS_IS_INDIVIDUAL (individual)) {
+ DEBUG ("failed assertion: FOLKS_IS_INDIVIDUAL (individual)");
+ goto out;
+ }
+
+ avatar_file = folks_avatar_get_avatar (FOLKS_AVATAR (individual));
+ if (avatar_file == NULL) {
+ goto out;
+ }
+
+ closure = g_new0 (PixbufAvatarFromIndividualClosure, 1);
+ closure->individual = g_object_ref (individual);
+ closure->callback = callback;
+ closure->user_data = user_data;
+ closure->width = width;
+ closure->height = height;
+
+ g_file_load_contents_async (avatar_file, NULL,
+ avatar_file_load_contents_cb, closure);
+
+ return;
+
+out:
+ callback (individual, NULL, user_data);
+}
+
GdkPixbuf *
empathy_pixbuf_contact_status_icon (EmpathyContact *contact,
gboolean show_protocol)
diff --git a/libempathy-gtk/empathy-ui-utils.h b/libempathy-gtk/empathy-ui-utils.h
index 3032aea84..3e9a8434e 100644
--- a/libempathy-gtk/empathy-ui-utils.h
+++ b/libempathy-gtk/empathy-ui-utils.h
@@ -49,6 +49,10 @@ G_BEGIN_DECLS
(x) < gdk_screen_width () && \
(y) < gdk_screen_height ())
+typedef void (*EmpathyPixbufAvatarFromIndividualCb) (FolksIndividual *individual,
+ GdkPixbuf *pixbuf,
+ gpointer user_data);
+
void empathy_gtk_init (void);
/* Glade */
@@ -72,6 +76,11 @@ GdkPixbuf * empathy_pixbuf_from_data (gchar *data,
GdkPixbuf * empathy_pixbuf_from_data_and_mime (gchar *data,
gsize data_size,
gchar **mime_type);
+void empathy_pixbuf_avatar_from_individual_scaled_async (FolksIndividual *individual,
+ gint width,
+ gint height,
+ EmpathyPixbufAvatarFromIndividualCb callback,
+ gpointer user_data);
GdkPixbuf * empathy_pixbuf_from_avatar_scaled (EmpathyAvatar *avatar,
gint width,
gint height);