]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-ui-utils.c
Merge branch 'sasl'
[empathy.git] / libempathy-gtk / empathy-ui-utils.c
index 6339a891dac9aaacd37ad7caabaa4294df213aa8..4c128742405b72274640e1b50b70b986c9594de2 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2002-2007 Imendio AB
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2010 Collabora Ltd.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -23,6 +23,7 @@
  *          Martyn Russell <martyn@imendio.com>
  *          Xavier Claessens <xclaesse@gmail.com>
  *          Jonny Lamb <jonny.lamb@collabora.co.uk>
+ *          Travis Reitter <travis.reitter@collabora.co.uk>
  *
  *          Part of this file is copied from GtkSourceView (gtksourceiter.c):
  *          Paolo Maggi
@@ -38,6 +39,9 @@
 #include <gtk/gtk.h>
 #include <gio/gio.h>
 
+#include <telepathy-glib/util.h>
+#include <folks/folks.h>
+
 #include "empathy-ui-utils.h"
 #include "empathy-images.h"
 #include "empathy-smiley-manager.h"
@@ -125,9 +129,9 @@ empathy_builder_get_file (const gchar *filename,
 }
 
 void
-empathy_builder_connect (GtkBuilder *gui,
-                        gpointer    user_data,
-                        gchar      *first_object,
+empathy_builder_connect (GtkBuilder  *gui,
+                        gpointer     user_data,
+                        const gchar *first_object,
                         ...)
 {
        va_list      args;
@@ -202,6 +206,7 @@ empathy_icon_name_for_presence (TpConnectionPresenceType presence)
        case TP_CONNECTION_PRESENCE_TYPE_UNKNOWN:
                return EMPATHY_IMAGE_PENDING;
        case TP_CONNECTION_PRESENCE_TYPE_UNSET:
+       default:
                return NULL;
        }
 
@@ -220,6 +225,19 @@ empathy_icon_name_for_contact (EmpathyContact *contact)
        return empathy_icon_name_for_presence (presence);
 }
 
+const gchar *
+empathy_icon_name_for_individual (FolksIndividual *individual)
+{
+       FolksPresenceType folks_presence;
+       TpConnectionPresenceType presence;
+
+       folks_presence =
+           folks_presence_get_presence_type (FOLKS_PRESENCE (individual));
+       presence = empathy_folks_presence_type_to_tp (folks_presence);
+
+       return empathy_icon_name_for_presence (presence);
+}
+
 const gchar *
 empathy_protocol_name_for_contact (EmpathyContact   *contact)
 {
@@ -421,6 +439,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,
@@ -454,27 +501,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);
 
@@ -495,6 +522,164 @@ empathy_pixbuf_avatar_from_contact_scaled (EmpathyContact *contact,
        return empathy_pixbuf_from_avatar_scaled (avatar, width, height);
 }
 
+typedef struct {
+       FolksIndividual *individual;
+       GSimpleAsyncResult *result;
+       guint width;
+       guint height;
+} PixbufAvatarFromIndividualClosure;
+
+static PixbufAvatarFromIndividualClosure *
+pixbuf_avatar_from_individual_closure_new (FolksIndividual    *individual,
+                                          GSimpleAsyncResult *result,
+                                          gint                width,
+                                          gint                height)
+{
+       PixbufAvatarFromIndividualClosure *closure;
+
+       g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+       closure = g_new0 (PixbufAvatarFromIndividualClosure, 1);
+       closure->individual = g_object_ref (individual);
+       closure->result = g_object_ref (result);
+       closure->width = width;
+       closure->height = height;
+
+       return closure;
+}
+
+static void
+pixbuf_avatar_from_individual_closure_free (
+               PixbufAvatarFromIndividualClosure *closure)
+{
+       g_object_unref (closure->individual);
+       g_object_unref (closure->result);
+       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 = NULL;
+       gsize data_size;
+       struct SizeData size_data;
+       GError *error = NULL;
+       GdkPixbufLoader *loader = NULL;
+
+       if (!g_file_load_contents_finish (file, result, &data, &data_size,
+                               NULL, &error)) {
+               DEBUG ("failed to load avatar from file: %s",
+                               error->message);
+               g_simple_async_result_set_from_error (closure->result, error);
+               goto out;
+       }
+
+       size_data.width = closure->width;
+       size_data.height = closure->height;
+       size_data.preserve_aspect_ratio = TRUE;
+
+       loader = gdk_pixbuf_loader_new ();
+
+       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");
+               g_simple_async_result_set_from_error (closure->result, error);
+               goto out;
+       }
+       if (!gdk_pixbuf_loader_close (loader, &error)) {
+               DEBUG ("Failed to close pixbuf loader: %s",
+                       error ? error->message : "No error given");
+               g_simple_async_result_set_from_error (closure->result, error);
+               goto out;
+       }
+
+       g_simple_async_result_set_op_res_gpointer (closure->result,
+                       avatar_pixbuf_from_loader (loader), g_object_unref);
+
+out:
+       g_simple_async_result_complete (closure->result);
+
+       g_clear_error (&error);
+       g_free (data);
+       tp_clear_object (&loader);
+       pixbuf_avatar_from_individual_closure_free (closure);
+}
+
+void
+empathy_pixbuf_avatar_from_individual_scaled_async (
+               FolksIndividual     *individual,
+               gint                 width,
+               gint                 height,
+               GCancellable        *cancellable,
+               GAsyncReadyCallback  callback,
+               gpointer             user_data)
+{
+       GFile *avatar_file;
+       GSimpleAsyncResult *result;
+       PixbufAvatarFromIndividualClosure *closure;
+
+       result = g_simple_async_result_new (G_OBJECT (individual),
+                       callback, user_data,
+                       empathy_pixbuf_avatar_from_individual_scaled_async);
+
+       avatar_file = folks_avatar_get_avatar (FOLKS_AVATAR (individual));
+       if (avatar_file == NULL)
+               goto out;
+
+       closure = pixbuf_avatar_from_individual_closure_new (individual, result,
+                                                            width, height);
+       if (closure == NULL)
+               goto out;
+
+       g_file_load_contents_async (avatar_file, cancellable,
+                       avatar_file_load_contents_cb, closure);
+
+       g_object_unref (result);
+
+       return;
+
+out:
+       g_simple_async_result_set_op_res_gpointer (result, NULL, NULL);
+       g_simple_async_result_complete (result);
+       g_object_unref (result);
+}
+
+/* Return a ref on the GdkPixbuf */
+GdkPixbuf *
+empathy_pixbuf_avatar_from_individual_scaled_finish (
+               FolksIndividual *individual,
+               GAsyncResult *result,
+               GError **error)
+{
+       GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+       gboolean result_valid;
+       GdkPixbuf *pixbuf;
+
+       g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+       g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple), NULL);
+
+       if (g_simple_async_result_propagate_error (simple, error))
+               return NULL;
+
+       result_valid = g_simple_async_result_is_valid (result,
+                       G_OBJECT (individual),
+                       empathy_pixbuf_avatar_from_individual_scaled_async);
+       g_return_val_if_fail (result_valid, NULL);
+
+       pixbuf = g_simple_async_result_get_op_res_gpointer (simple);
+       return pixbuf != NULL ? g_object_ref (pixbuf) : NULL;
+}
+
 GdkPixbuf *
 empathy_pixbuf_contact_status_icon (EmpathyContact *contact,
                                   gboolean       show_protocol)
@@ -524,7 +709,8 @@ empathy_pixbuf_contact_status_icon_with_icon_name (EmpathyContact *contact,
        gint       height, width;
        gint       numerator, denominator;
 
-       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+       g_return_val_if_fail (EMPATHY_IS_CONTACT (contact) ||
+                       (show_protocol == FALSE), NULL);
        g_return_val_if_fail (icon_name != NULL, NULL);
 
        numerator = 3;
@@ -539,13 +725,14 @@ empathy_pixbuf_contact_status_icon_with_icon_name (EmpathyContact *contact,
 
        pix_status = gdk_pixbuf_new_from_file (icon_filename, NULL);
 
-       g_free (icon_filename);
-
        if (pix_status == NULL) {
                DEBUG ("Could not open icon %s\n", icon_filename);
+               g_free (icon_filename);
                return NULL;
        }
 
+       g_free (icon_filename);
+
        if (!show_protocol)
                return pix_status;
 
@@ -1377,7 +1564,7 @@ empathy_window_iconify (GtkWindow *window, GtkStatusIcon *status_icon)
 
        gtk_status_icon_get_geometry (status_icon, NULL, &icon_location, NULL);
        gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
-       dpy = gdk_x11_drawable_get_xdisplay (gdk_window);
+       dpy = GDK_WINDOW_XDISPLAY (gdk_window);
 
        data[0] = icon_location.x;
        data[1] = icon_location.y;
@@ -1387,7 +1574,7 @@ empathy_window_iconify (GtkWindow *window, GtkStatusIcon *status_icon)
        XChangeProperty (dpy,
                         GDK_WINDOW_XID (gdk_window),
                         gdk_x11_get_xatom_by_name_for_display (
-                               gdk_drawable_get_display (gdk_window),
+                               gdk_window_get_display (gdk_window),
                         "_NET_WM_ICON_GEOMETRY"),
                         XA_CARDINAL, 32, PropModeReplace,
                         (guchar *)&data, 4);
@@ -1423,7 +1610,11 @@ empathy_window_present_with_time (GtkWindow *window,
                        gtk_widget_hide (GTK_WIDGET (window));
        }
 
-       gtk_window_present_with_time (window, timestamp);
+       if (timestamp == GDK_CURRENT_TIME)
+               gtk_window_present (window);
+       else
+               gtk_window_present_with_time (window, timestamp);
+
        gtk_window_set_skip_taskbar_hint (window, FALSE);
        gtk_window_deiconify (window);
 }
@@ -1431,7 +1622,7 @@ empathy_window_present_with_time (GtkWindow *window,
 void
 empathy_window_present (GtkWindow *window)
 {
-  empathy_window_present_with_time (window, GDK_CURRENT_TIME);
+  empathy_window_present_with_time (window, gtk_get_current_event_time ());
 }
 
 GtkWindow *
@@ -1670,8 +1861,16 @@ empathy_receive_file_with_file_chooser (EmpathyFTHandler *handler)
 {
        GtkWidget *widget;
        const gchar *dir;
+       EmpathyContact *contact;
+       gchar *title;
+
+       contact = empathy_ft_handler_get_contact (handler);
+       g_assert (contact != NULL);
 
-       widget = gtk_file_chooser_dialog_new (_("Select a destination"),
+       title = g_strdup_printf (_("Incoming file from %s"),
+               empathy_contact_get_alias (contact));
+
+       widget = gtk_file_chooser_dialog_new (title,
                                              NULL,
                                              GTK_FILE_CHOOSER_ACTION_SAVE,
                                              GTK_STOCK_CANCEL,
@@ -1695,5 +1894,5 @@ empathy_receive_file_with_file_chooser (EmpathyFTHandler *handler)
                G_CALLBACK (file_manager_receive_file_response_cb), handler);
 
        gtk_widget_show (widget);
+       g_free (title);
 }
-