aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy-gtk
diff options
context:
space:
mode:
authorXavier Claessens <xclaesse@gmail.com>2007-10-09 00:44:44 +0800
committerXavier Claessens <xclaesse@src.gnome.org>2007-10-09 00:44:44 +0800
commit0d4e81432f5ace47ac86991aa239e4a55686de00 (patch)
tree22cc64055c78370d4a973af8e85a36740f60f930 /libempathy-gtk
parent311dbc21826654538e098a8d838153d5b075f6c7 (diff)
downloadgsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.tar
gsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.tar.gz
gsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.tar.bz2
gsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.tar.lz
gsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.tar.xz
gsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.tar.zst
gsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.zip
Implement EmpathyAvatarChooser and EmpathyAvatarImage and make use of them
2007-10-08 Xavier Claessens <xclaesse@gmail.com> * libempathy-gtk/empathy-ui-utils.c: * libempathy-gtk/empathy-ui-utils.h: * libempathy-gtk/empathy-contact-widget.c: * libempathy-gtk/empathy-contact-widget.h: * libempathy-gtk/empathy-avatar-chooser.c: * libempathy-gtk/empathy-avatar-chooser.h: * libempathy-gtk/empathy-avatar-image.c: * libempathy-gtk/empathy-avatar-image.h: * libempathy-gtk/Makefile.am: * src/empathy.c: Implement EmpathyAvatarChooser and EmpathyAvatarImage and make use of them in contact information windows. That means we can now enlarge avatars when clicking on it and we can set our own avatar if we edit our own contact. svn path=/trunk/; revision=363
Diffstat (limited to 'libempathy-gtk')
-rw-r--r--libempathy-gtk/Makefile.am6
-rw-r--r--libempathy-gtk/empathy-avatar-chooser.c572
-rw-r--r--libempathy-gtk/empathy-avatar-chooser.h59
-rw-r--r--libempathy-gtk/empathy-avatar-image.c306
-rw-r--r--libempathy-gtk/empathy-avatar-image.h58
-rw-r--r--libempathy-gtk/empathy-contact-widget.c64
-rw-r--r--libempathy-gtk/empathy-contact-widget.h9
-rw-r--r--libempathy-gtk/empathy-ui-utils.c119
-rw-r--r--libempathy-gtk/empathy-ui-utils.h111
9 files changed, 1198 insertions, 106 deletions
diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am
index fa13e27cc..71ec03bcd 100644
--- a/libempathy-gtk/Makefile.am
+++ b/libempathy-gtk/Makefile.am
@@ -12,7 +12,7 @@ BUILT_SOURCES = \
lib_LTLIBRARIES = libempathy-gtk.la
libempathy_gtk_la_SOURCES = \
- ephy-spinner.c ephy-spinner.h \
+ ephy-spinner.c ephy-spinner.h \
empathy-main-window.c \
empathy-status-icon.c \
empathy-contact-widget.c \
@@ -48,6 +48,8 @@ libempathy_gtk_la_SOURCES = \
empathy-chatrooms-window.c \
empathy-log-window.c \
empathy-call-window.c \
+ empathy-avatar-chooser.c \
+ empathy-avatar-image.c \
empathy-ui-utils.c
# do not distribute generated files
@@ -98,6 +100,8 @@ libempathy_gtk_headers = \
empathy-chatrooms-window.h \
empathy-log-window.h \
empathy-call-window.h \
+ empathy-avatar-chooser.h \
+ empathy-avatar-image.h \
empathy-ui-utils.h
libempathy_gtk_includedir = $(includedir)/libempathy-gtk/
diff --git a/libempathy-gtk/empathy-avatar-chooser.c b/libempathy-gtk/empathy-avatar-chooser.c
new file mode 100644
index 000000000..2ef3de429
--- /dev/null
+++ b/libempathy-gtk/empathy-avatar-chooser.c
@@ -0,0 +1,572 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2007 Imendio AB.
+ * Copyright (C) 2007 Collabora Ltd.
+ *
+ * This library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Based on Novell's e-image-chooser.
+ * Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <libgnomevfs/gnome-vfs-ops.h>
+
+#include <libempathy/empathy-debug.h>
+#include <libempathy/empathy-conf.h>
+
+#include "empathy-avatar-chooser.h"
+#include "empathy-preferences.h"
+#include "empathy-ui-utils.h"
+
+#define DEBUG_DOMAIN "AvatarChooser"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_AVATAR_CHOOSER_TYPE, EmpathyAvatarChooserPriv))
+
+#define AVATAR_MAX 96
+#define DEFAULT_DIR DATADIR"/pixmaps/faces"
+
+typedef struct {
+ GdkPixbuf *pixbuf;
+ gchar *image_data;
+ gsize image_data_size;
+} EmpathyAvatarChooserPriv;
+
+static void avatar_chooser_finalize (GObject *object);
+static void avatar_chooser_set_image_from_data (EmpathyAvatarChooser *chooser,
+ gchar *data,
+ gsize size);
+static gboolean avatar_chooser_drag_motion_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ EmpathyAvatarChooser *chooser);
+static void avatar_chooser_drag_leave_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time,
+ EmpathyAvatarChooser *chooser);
+static gboolean avatar_chooser_drag_drop_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ EmpathyAvatarChooser *chooser);
+static void avatar_chooser_drag_data_received_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ EmpathyAvatarChooser *chooser);
+static void avatar_chooser_clicked_cb (GtkWidget *button,
+ EmpathyAvatarChooser *chooser);
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL];
+
+G_DEFINE_TYPE (EmpathyAvatarChooser, empathy_avatar_chooser, GTK_TYPE_BUTTON);
+
+/*
+ * Drag and drop stuff
+ */
+#define URI_LIST_TYPE "text/uri-list"
+
+enum DndTargetType {
+ DND_TARGET_TYPE_URI_LIST
+};
+
+static const GtkTargetEntry drop_types[] = {
+ { URI_LIST_TYPE, 0, DND_TARGET_TYPE_URI_LIST },
+};
+
+static void
+empathy_avatar_chooser_class_init (EmpathyAvatarChooserClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = avatar_chooser_finalize;
+
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_type_class_add_private (object_class, sizeof (EmpathyAvatarChooserPriv));
+}
+
+static void
+empathy_avatar_chooser_init (EmpathyAvatarChooser *chooser)
+{
+ EmpathyAvatarChooserPriv *priv;
+
+ priv = GET_PRIV (chooser);
+
+ gtk_drag_dest_set (GTK_WIDGET (chooser),
+ GTK_DEST_DEFAULT_ALL,
+ drop_types,
+ G_N_ELEMENTS (drop_types),
+ GDK_ACTION_COPY);
+
+ g_signal_connect (chooser, "drag-motion",
+ G_CALLBACK (avatar_chooser_drag_motion_cb),
+ chooser);
+ g_signal_connect (chooser, "drag-leave",
+ G_CALLBACK (avatar_chooser_drag_leave_cb),
+ chooser);
+ g_signal_connect (chooser, "drag-drop",
+ G_CALLBACK (avatar_chooser_drag_drop_cb),
+ chooser);
+ g_signal_connect (chooser, "drag-data-received",
+ G_CALLBACK (avatar_chooser_drag_data_received_cb),
+ chooser);
+ g_signal_connect (chooser, "clicked",
+ G_CALLBACK (avatar_chooser_clicked_cb),
+ chooser);
+
+ empathy_avatar_chooser_set (chooser, NULL);
+}
+
+static void
+avatar_chooser_finalize (GObject *object)
+{
+ EmpathyAvatarChooserPriv *priv;
+
+ priv = GET_PRIV (object);
+
+ if (priv->pixbuf) {
+ g_object_unref (priv->pixbuf);
+ }
+ g_free (priv->image_data);
+
+ G_OBJECT_CLASS (empathy_avatar_chooser_parent_class)->finalize (object);
+}
+
+static void
+avatar_chooser_set_pixbuf (EmpathyAvatarChooser *chooser,
+ GdkPixbuf *pixbuf)
+{
+ EmpathyAvatarChooserPriv *priv = GET_PRIV (chooser);
+ GtkWidget *image;
+ GError *error = NULL;
+
+ if (priv->pixbuf) {
+ g_object_unref (priv->pixbuf);
+ priv->pixbuf = NULL;
+ }
+ g_free (priv->image_data);
+ priv->image_data = NULL;
+ priv->image_data_size = 0;
+
+ if (pixbuf) {
+ priv->pixbuf = empathy_pixbuf_scale_down_if_necessary (pixbuf, AVATAR_MAX);
+ }
+
+ if (priv->pixbuf) {
+ if (!gdk_pixbuf_save_to_buffer (priv->pixbuf,
+ &priv->image_data,
+ &priv->image_data_size,
+ "png",
+ &error, NULL)) {
+ empathy_debug (DEBUG_DOMAIN, "Failed to save pixbuf: %s",
+ error ? error->message : "No error given");
+ g_clear_error (&error);
+ g_object_unref (priv->pixbuf);
+ priv->pixbuf = NULL;
+ }
+ }
+
+ if (!priv->pixbuf) {
+ image = gtk_image_new_from_icon_name ("stock_person",
+ GTK_ICON_SIZE_DIALOG);
+ } else {
+ image = gtk_image_new_from_pixbuf (priv->pixbuf);
+ }
+
+ gtk_button_set_image (GTK_BUTTON (chooser), image);
+ g_signal_emit (chooser, signals[CHANGED], 0);
+}
+
+static void
+avatar_chooser_set_image_from_file (EmpathyAvatarChooser *chooser,
+ const gchar *filename)
+{
+ GdkPixbuf *pixbuf;
+ GError *error = NULL;
+
+ if (!(pixbuf = gdk_pixbuf_new_from_file (filename, &error))) {
+ empathy_debug (DEBUG_DOMAIN, "Failed to load pixbuf from file: %s",
+ error ? error->message : "No error given");
+ g_clear_error (&error);
+ }
+
+ avatar_chooser_set_pixbuf (chooser, pixbuf);
+ if (pixbuf) {
+ g_object_unref (pixbuf);
+ }
+}
+
+static void
+avatar_chooser_set_image_from_data (EmpathyAvatarChooser *chooser,
+ gchar *data,
+ gsize size)
+{
+ GdkPixbuf *pixbuf;
+
+ pixbuf = empathy_pixbuf_from_data (data, size);
+ avatar_chooser_set_pixbuf (chooser, pixbuf);
+ if (pixbuf) {
+ g_object_unref (pixbuf);
+ }
+}
+
+static gboolean
+avatar_chooser_drag_motion_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ EmpathyAvatarChooser *chooser)
+{
+ EmpathyAvatarChooserPriv *priv;
+ GList *p;
+
+ priv = GET_PRIV (chooser);
+
+ for (p = context->targets; p != NULL; p = p->next) {
+ gchar *possible_type;
+
+ possible_type = gdk_atom_name (GDK_POINTER_TO_ATOM (p->data));
+
+ if (!strcmp (possible_type, URI_LIST_TYPE)) {
+ g_free (possible_type);
+ gdk_drag_status (context, GDK_ACTION_COPY, time);
+
+ return TRUE;
+ }
+
+ g_free (possible_type);
+ }
+
+ return FALSE;
+}
+
+static void
+avatar_chooser_drag_leave_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time,
+ EmpathyAvatarChooser *chooser)
+{
+}
+
+static gboolean
+avatar_chooser_drag_drop_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ EmpathyAvatarChooser *chooser)
+{
+ EmpathyAvatarChooserPriv *priv;
+ GList *p;
+
+ priv = GET_PRIV (chooser);
+
+ if (context->targets == NULL) {
+ return FALSE;
+ }
+
+ for (p = context->targets; p != NULL; p = p->next) {
+ char *possible_type;
+
+ possible_type = gdk_atom_name (GDK_POINTER_TO_ATOM (p->data));
+ if (!strcmp (possible_type, URI_LIST_TYPE)) {
+ g_free (possible_type);
+ gtk_drag_get_data (widget, context,
+ GDK_POINTER_TO_ATOM (p->data),
+ time);
+
+ return TRUE;
+ }
+
+ g_free (possible_type);
+ }
+
+ return FALSE;
+}
+
+static void
+avatar_chooser_drag_data_received_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ EmpathyAvatarChooser *chooser)
+{
+ gchar *target_type;
+ gboolean handled = FALSE;
+
+ target_type = gdk_atom_name (selection_data->target);
+ if (!strcmp (target_type, URI_LIST_TYPE)) {
+ GnomeVFSHandle *handle = NULL;
+ GnomeVFSResult result;
+ GnomeVFSFileInfo info;
+ gchar *uri;
+ gchar *nl;
+ gchar *data = NULL;
+
+ nl = strstr (selection_data->data, "\r\n");
+ if (nl) {
+ uri = g_strndup (selection_data->data,
+ nl - (gchar*) selection_data->data);
+ } else {
+ uri = g_strdup (selection_data->data);
+ }
+
+ result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
+ if (result == GNOME_VFS_OK) {
+ result = gnome_vfs_get_file_info_from_handle (handle,
+ &info,
+ GNOME_VFS_FILE_INFO_DEFAULT);
+ if (result == GNOME_VFS_OK) {
+ GnomeVFSFileSize data_size;
+
+ data = g_malloc (info.size);
+
+ result = gnome_vfs_read (handle, data, info.size, &data_size);
+ if (result == GNOME_VFS_OK) {
+ avatar_chooser_set_image_from_data (chooser,
+ data,
+ data_size);
+ handled = TRUE;
+ } else {
+ g_free (data);
+ }
+ }
+
+ gnome_vfs_close (handle);
+ }
+
+ g_free (uri);
+ }
+
+ gtk_drag_finish (context, handled, FALSE, time);
+}
+
+static void
+avatar_chooser_update_preview_cb (GtkFileChooser *file_chooser,
+ EmpathyAvatarChooser *chooser)
+{
+ gchar *filename;
+
+ filename = gtk_file_chooser_get_preview_filename (file_chooser);
+
+ if (filename) {
+ GtkWidget *image;
+ GdkPixbuf *pixbuf = NULL;
+ GdkPixbuf *scaled_pixbuf;
+
+ pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
+
+ image = gtk_file_chooser_get_preview_widget (file_chooser);
+
+ if (pixbuf) {
+ scaled_pixbuf = empathy_pixbuf_scale_down_if_necessary (pixbuf, AVATAR_MAX);
+ gtk_image_set_from_pixbuf (GTK_IMAGE (image), scaled_pixbuf);
+ g_object_unref (scaled_pixbuf);
+ g_object_unref (pixbuf);
+ } else {
+ gtk_image_set_from_stock (GTK_IMAGE (image),
+ "gtk-dialog-question",
+ GTK_ICON_SIZE_DIALOG);
+ }
+ }
+
+ gtk_file_chooser_set_preview_widget_active (file_chooser, TRUE);
+}
+
+static void
+avatar_chooser_response_cb (GtkWidget *widget,
+ gint response,
+ EmpathyAvatarChooser *chooser)
+{
+ if (response == GTK_RESPONSE_OK) {
+ gchar *filename;
+ gchar *path;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ avatar_chooser_set_image_from_file (chooser, filename);
+ g_free (filename);
+
+ path = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (widget));
+ if (path) {
+ empathy_conf_set_string (empathy_conf_get (),
+ EMPATHY_PREFS_UI_AVATAR_DIRECTORY,
+ path);
+ g_free (path);
+ }
+ }
+ else if (response == GTK_RESPONSE_NO) {
+ avatar_chooser_set_image_from_data (chooser, NULL, 0);
+ }
+
+ gtk_widget_destroy (widget);
+}
+
+static void
+avatar_chooser_clicked_cb (GtkWidget *button,
+ EmpathyAvatarChooser *chooser)
+{
+ GtkFileChooser *chooser_dialog;
+ GtkWidget *image;
+ gchar *saved_dir = NULL;
+ const gchar *default_dir = DEFAULT_DIR;
+ const gchar *pics_dir;
+ GtkFileFilter *filter;
+
+ chooser_dialog = GTK_FILE_CHOOSER (
+ gtk_file_chooser_dialog_new (_("Select Your Avatar Image"),
+ empathy_get_toplevel_window (GTK_WIDGET (chooser)),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ _("No Image"),
+ GTK_RESPONSE_NO,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN,
+ GTK_RESPONSE_OK,
+ NULL));
+
+ /* Get special dirs */
+ empathy_conf_get_string (empathy_conf_get (),
+ EMPATHY_PREFS_UI_AVATAR_DIRECTORY,
+ &saved_dir);
+ if (saved_dir && !g_file_test (saved_dir, G_FILE_TEST_IS_DIR)) {
+ g_free (saved_dir);
+ saved_dir = NULL;
+ }
+ if (!g_file_test (default_dir, G_FILE_TEST_IS_DIR)) {
+ default_dir = NULL;
+ }
+ pics_dir = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
+ if (pics_dir && !g_file_test (pics_dir, G_FILE_TEST_IS_DIR)) {
+ pics_dir = NULL;
+ }
+
+ /* Set current dir to the last one or to DEFAULT_DIR or to home */
+ if (saved_dir) {
+ gtk_file_chooser_set_current_folder (chooser_dialog, saved_dir);
+ }
+ else if (pics_dir) {
+ gtk_file_chooser_set_current_folder (chooser_dialog, pics_dir);
+ }
+ else if (default_dir) {
+ gtk_file_chooser_set_current_folder (chooser_dialog, default_dir);
+ } else {
+ gtk_file_chooser_set_current_folder (chooser_dialog, g_get_home_dir ());
+ }
+
+ /* Add shortcuts to special dirs */
+ if (saved_dir) {
+ gtk_file_chooser_add_shortcut_folder (chooser_dialog, saved_dir, NULL);
+ }
+ else if (pics_dir) {
+ gtk_file_chooser_add_shortcut_folder (chooser_dialog, pics_dir, NULL);
+ }
+ if (default_dir) {
+ gtk_file_chooser_add_shortcut_folder (chooser_dialog, default_dir, NULL);
+ }
+
+ /* Setup preview image */
+ image = gtk_image_new ();
+ gtk_file_chooser_set_preview_widget (chooser_dialog, image);
+ gtk_widget_set_size_request (image, AVATAR_MAX, AVATAR_MAX);
+ gtk_widget_show (image);
+ gtk_file_chooser_set_use_preview_label (chooser_dialog, FALSE);
+ g_signal_connect (chooser_dialog, "update-preview",
+ G_CALLBACK (avatar_chooser_update_preview_cb),
+ chooser);
+
+ /* Setup filers */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_set_name (filter, _("Images"));
+ gtk_file_filter_add_pixbuf_formats (filter);
+ gtk_file_chooser_add_filter (chooser_dialog, filter);
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_set_name (filter, _("All Files"));
+ gtk_file_filter_add_pattern(filter, "*");
+ gtk_file_chooser_add_filter (chooser_dialog, filter);
+
+ /* Setup response */
+ gtk_dialog_set_default_response (GTK_DIALOG (chooser_dialog), GTK_RESPONSE_OK);
+ g_signal_connect (chooser_dialog, "response",
+ G_CALLBACK (avatar_chooser_response_cb),
+ chooser);
+
+ gtk_widget_show (GTK_WIDGET (chooser_dialog));
+ g_free (saved_dir);
+}
+
+GtkWidget *
+empathy_avatar_chooser_new (void)
+{
+ return g_object_new (EMPATHY_AVATAR_CHOOSER_TYPE, NULL);
+}
+
+void
+empathy_avatar_chooser_set (EmpathyAvatarChooser *chooser,
+ EmpathyAvatar *avatar)
+{
+ g_return_if_fail (EMPATHY_IS_AVATAR_CHOOSER (chooser));
+
+ avatar_chooser_set_image_from_data (chooser,
+ avatar ? avatar->data : NULL,
+ avatar ? avatar->len : 0);
+}
+
+void
+empathy_avatar_chooser_get_image_data (EmpathyAvatarChooser *chooser,
+ gchar **data,
+ gsize *data_size)
+{
+ EmpathyAvatarChooserPriv *priv;
+
+ g_return_if_fail (EMPATHY_IS_AVATAR_CHOOSER (chooser));
+
+ priv = GET_PRIV (chooser);
+
+ if (data) {
+ *data = priv->image_data;
+ }
+ if (*data_size) {
+ *data_size = priv->image_data_size;
+ }
+}
+
diff --git a/libempathy-gtk/empathy-avatar-chooser.h b/libempathy-gtk/empathy-avatar-chooser.h
new file mode 100644
index 000000000..b0c08df11
--- /dev/null
+++ b/libempathy-gtk/empathy-avatar-chooser.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2007 Imendio AB.
+ * Copyright (C) 2007 Collabora Ltd.
+ *
+ * This library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Based on Novell's e-image-chooser.
+ * Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#ifndef __EMPATHY_AVATAR_CHOOSER_H__
+#define __EMPATHY_AVATAR_CHOOSER_H__
+
+#include <gtk/gtkbutton.h>
+
+#include <libempathy/empathy-avatar.h>
+
+G_BEGIN_DECLS
+
+#define EMPATHY_AVATAR_CHOOSER_TYPE (empathy_avatar_chooser_get_type ())
+#define EMPATHY_AVATAR_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_AVATAR_CHOOSER_TYPE, EmpathyAvatarChooser))
+#define EMPATHY_AVATAR_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EMPATHY_AVATAR_CHOOSER_TYPE, EmpathyAvatarChooserClass))
+#define EMPATHY_IS_AVATAR_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_AVATAR_CHOOSER_TYPE))
+#define EMPATHY_IS_AVATAR_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EMPATHY_AVATAR_CHOOSER_TYPE))
+
+typedef struct _EmpathyAvatarChooser EmpathyAvatarChooser;
+typedef struct _EmpathyAvatarChooserClass EmpathyAvatarChooserClass;
+typedef struct _EmpathyAvatarChooserPrivate EmpathyAvatarChooserPrivate;
+
+struct _EmpathyAvatarChooser {
+ GtkButton parent;
+};
+
+struct _EmpathyAvatarChooserClass {
+ GtkButtonClass parent_class;
+};
+
+GType empathy_avatar_chooser_get_type (void);
+GtkWidget *empathy_avatar_chooser_new (void);
+void empathy_avatar_chooser_set (EmpathyAvatarChooser *chooser,
+ EmpathyAvatar *avatar);
+void empathy_avatar_chooser_get_image_data (EmpathyAvatarChooser *chooser,
+ gchar **data,
+ gsize *data_size);
+
+#endif /* __EMPATHY_AVATAR_CHOOSER_H__ */
diff --git a/libempathy-gtk/empathy-avatar-image.c b/libempathy-gtk/empathy-avatar-image.c
new file mode 100644
index 000000000..cc4ecbf45
--- /dev/null
+++ b/libempathy-gtk/empathy-avatar-image.c
@@ -0,0 +1,306 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2007 Imendio AB
+ * Copyright (C) 2007 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
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#include <libempathy/empathy-debug.h>
+
+#include "empathy-avatar-image.h"
+#include "empathy-ui-utils.h"
+
+#define DEBUG_DOMAIN "AvatarImage"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_AVATAR_IMAGE, EmpathyAvatarImagePriv))
+
+#define MAX_SMALL 48
+#define MAX_LARGE 400
+
+typedef struct {
+ GtkWidget *image;
+ GtkWidget *popup;
+ GdkPixbuf *pixbuf;
+} EmpathyAvatarImagePriv;
+
+static void avatar_image_finalize (GObject *object);
+static void avatar_image_add_filter (EmpathyAvatarImage *avatar_image);
+static void avatar_image_remove_filter (EmpathyAvatarImage *avatar_image);
+static gboolean avatar_image_button_press_event (GtkWidget *widget,
+ GdkEventButton *event);
+static gboolean avatar_image_button_release_event (GtkWidget *widget,
+ GdkEventButton *event);
+
+G_DEFINE_TYPE (EmpathyAvatarImage, empathy_avatar_image, GTK_TYPE_EVENT_BOX);
+
+static void
+empathy_avatar_image_class_init (EmpathyAvatarImageClass *klass)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = avatar_image_finalize;
+
+ widget_class->button_press_event = avatar_image_button_press_event;
+ widget_class->button_release_event = avatar_image_button_release_event;
+
+ g_type_class_add_private (object_class, sizeof (EmpathyAvatarImagePriv));
+}
+
+static void
+empathy_avatar_image_init (EmpathyAvatarImage *avatar_image)
+{
+ EmpathyAvatarImagePriv *priv;
+
+ priv = GET_PRIV (avatar_image);
+
+ priv->image = gtk_image_new ();
+ gtk_container_add (GTK_CONTAINER (avatar_image), priv->image);
+ empathy_avatar_image_set (avatar_image, NULL);
+ gtk_widget_show (priv->image);
+
+ avatar_image_add_filter (avatar_image);
+}
+
+static void
+avatar_image_finalize (GObject *object)
+{
+ EmpathyAvatarImagePriv *priv;
+
+ priv = GET_PRIV (object);
+
+ avatar_image_remove_filter (EMPATHY_AVATAR_IMAGE (object));
+
+ if (priv->popup) {
+ gtk_widget_destroy (priv->popup);
+ }
+
+ if (priv->pixbuf) {
+ g_object_unref (priv->pixbuf);
+ }
+
+ G_OBJECT_CLASS (empathy_avatar_image_parent_class)->finalize (object);
+}
+
+static GdkFilterReturn
+avatar_image_filter_func (GdkXEvent *gdkxevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ XEvent *xevent = gdkxevent;
+ Atom atom;
+ EmpathyAvatarImagePriv *priv;
+
+ priv = GET_PRIV (data);
+
+ switch (xevent->type) {
+ case PropertyNotify:
+ atom = gdk_x11_get_xatom_by_name ("_NET_CURRENT_DESKTOP");
+ if (xevent->xproperty.atom == atom) {
+ if (priv->popup) {
+ gtk_widget_destroy (priv->popup);
+ priv->popup = NULL;
+ }
+ }
+ break;
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+avatar_image_add_filter (EmpathyAvatarImage *avatar_image)
+{
+ Window window;
+ GdkWindow *gdkwindow;
+ gint mask;
+
+ mask = PropertyChangeMask;
+
+ window = GDK_ROOT_WINDOW ();
+ gdkwindow = gdk_xid_table_lookup (window);
+
+ gdk_error_trap_push ();
+ if (gdkwindow) {
+ XWindowAttributes attrs;
+ XGetWindowAttributes (gdk_display, window, &attrs);
+ mask |= attrs.your_event_mask;
+ }
+
+ XSelectInput (gdk_display, window, mask);
+
+ gdk_error_trap_pop ();
+
+ gdk_window_add_filter (NULL, avatar_image_filter_func, avatar_image);
+}
+
+static void
+avatar_image_remove_filter (EmpathyAvatarImage *avatar_image)
+{
+ gdk_window_remove_filter (NULL, avatar_image_filter_func, avatar_image);
+}
+
+static gboolean
+avatar_image_button_press_event (GtkWidget *widget, GdkEventButton *event)
+{
+ EmpathyAvatarImagePriv *priv;
+ GtkWidget *popup;
+ GtkWidget *frame;
+ GtkWidget *image;
+ gint x, y;
+ gint popup_width, popup_height;
+ gint width, height;
+ GdkPixbuf *pixbuf;
+
+ priv = GET_PRIV (widget);
+
+ if (priv->popup) {
+ gtk_widget_destroy (priv->popup);
+ priv->popup = NULL;
+ }
+
+ if (event->button != 1 || event->type != GDK_BUTTON_PRESS || !priv->pixbuf) {
+ return FALSE;
+ }
+
+ popup_width = gdk_pixbuf_get_width (priv->pixbuf);
+ popup_height = gdk_pixbuf_get_height (priv->pixbuf);
+
+ width = priv->image->allocation.width;
+ height = priv->image->allocation.height;
+
+ /* Don't show a popup if the popup is smaller then the currently avatar
+ * image.
+ */
+ if (popup_height <= height && popup_width <= width) {
+ return TRUE;
+ }
+
+ pixbuf = empathy_pixbuf_scale_down_if_necessary (priv->pixbuf, MAX_LARGE);
+ popup_width = gdk_pixbuf_get_width (pixbuf);
+ popup_height = gdk_pixbuf_get_height (pixbuf);
+
+ popup = gtk_window_new (GTK_WINDOW_POPUP);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
+
+ gtk_container_add (GTK_CONTAINER (popup), frame);
+
+ image = gtk_image_new ();
+ gtk_container_add (GTK_CONTAINER (frame), image);
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf);
+ g_object_unref (pixbuf);
+
+ gdk_window_get_origin (priv->image->window, &x, &y);
+
+ x = x - (popup_width - width) / 2;
+ y = y - (popup_height - height) / 2;
+
+ gtk_window_move (GTK_WINDOW (popup), x, y);
+
+ priv->popup = popup;
+
+ gtk_widget_show_all (popup);
+
+ return TRUE;
+}
+
+static gboolean
+avatar_image_button_release_event (GtkWidget *widget, GdkEventButton *event)
+{
+ EmpathyAvatarImagePriv *priv;
+
+ priv = GET_PRIV (widget);
+
+ if (event->button != 1 || event->type != GDK_BUTTON_RELEASE) {
+ return FALSE;
+ }
+
+ if (!priv->popup) {
+ return TRUE;
+ }
+
+ gtk_widget_destroy (priv->popup);
+ priv->popup = NULL;
+
+ return TRUE;
+}
+
+GtkWidget *
+empathy_avatar_image_new (void)
+{
+ EmpathyAvatarImage *avatar_image;
+
+ avatar_image = g_object_new (EMPATHY_TYPE_AVATAR_IMAGE, NULL);
+
+ return GTK_WIDGET (avatar_image);
+}
+
+void
+empathy_avatar_image_set (EmpathyAvatarImage *avatar_image,
+ EmpathyAvatar *avatar)
+{
+ EmpathyAvatarImagePriv *priv = GET_PRIV (avatar_image);
+ GdkPixbuf *scaled_pixbuf;
+
+ g_return_if_fail (EMPATHY_IS_AVATAR_IMAGE (avatar_image));
+
+ if (priv->pixbuf) {
+ g_object_unref (priv->pixbuf);
+ priv->pixbuf = NULL;
+ }
+
+ if (avatar) {
+ priv->pixbuf = empathy_pixbuf_from_data (avatar->data, avatar->len);
+ }
+
+ if (!priv->pixbuf) {
+ gtk_image_set_from_icon_name (GTK_IMAGE (priv->image),
+ "stock_person",
+ GTK_ICON_SIZE_DIALOG);
+ return;
+ }
+
+ scaled_pixbuf = empathy_pixbuf_scale_down_if_necessary (priv->pixbuf, MAX_SMALL);
+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), scaled_pixbuf);
+
+ if (scaled_pixbuf != priv->pixbuf) {
+ gtk_widget_set_tooltip_text (GTK_WIDGET (avatar_image),
+ _("Click to enlarge"));
+ } else {
+ gtk_widget_set_tooltip_text (GTK_WIDGET (avatar_image),
+ NULL);
+ }
+
+ g_object_unref (scaled_pixbuf);
+}
+
diff --git a/libempathy-gtk/empathy-avatar-image.h b/libempathy-gtk/empathy-avatar-image.h
new file mode 100644
index 000000000..8a28ccb9a
--- /dev/null
+++ b/libempathy-gtk/empathy-avatar-image.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2007 Imendio AB
+ * Copyright (C) 2007 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
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#ifndef __EMPATHY_AVATAR_IMAGE_H__
+#define __EMPATHY_AVATAR_IMAGE_H__
+
+#include <gtk/gtkeventbox.h>
+
+#include <libempathy/empathy-avatar.h>
+
+G_BEGIN_DECLS
+
+#define EMPATHY_TYPE_AVATAR_IMAGE (empathy_avatar_image_get_type ())
+#define EMPATHY_AVATAR_IMAGE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_AVATAR_IMAGE, EmpathyAvatarImage))
+#define EMPATHY_AVATAR_IMAGE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EMPATHY_TYPE_AVATAR_IMAGE, EmpathyAvatarImageClass))
+#define EMPATHY_IS_AVATAR_IMAGE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_AVATAR_IMAGE))
+#define EMPATHY_IS_AVATAR_IMAGE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_AVATAR_IMAGE))
+#define EMPATHY_AVATAR_IMAGE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_AVATAR_IMAGE, EmpathyAvatarImageClass))
+
+typedef struct _EmpathyAvatarImage EmpathyAvatarImage;
+typedef struct _EmpathyAvatarImageClass EmpathyAvatarImageClass;
+
+struct _EmpathyAvatarImage {
+ GtkEventBox parent;
+};
+
+struct _EmpathyAvatarImageClass {
+ GtkEventBoxClass parent_class;
+};
+
+GType empathy_avatar_image_get_type (void) G_GNUC_CONST;
+GtkWidget * empathy_avatar_image_new (void);
+void empathy_avatar_image_set (EmpathyAvatarImage *avatar_image,
+ EmpathyAvatar *avatar);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_AVATAR_IMAGE_H__ */
diff --git a/libempathy-gtk/empathy-contact-widget.c b/libempathy-gtk/empathy-contact-widget.c
index b3081b130..b6fd4937d 100644
--- a/libempathy-gtk/empathy-contact-widget.c
+++ b/libempathy-gtk/empathy-contact-widget.c
@@ -38,6 +38,8 @@
#include "empathy-contact-widget.h"
#include "empathy-account-chooser.h"
+#include "empathy-avatar-chooser.h"
+#include "empathy-avatar-image.h"
#include "empathy-ui-utils.h"
/* Delay before updating the widget when the id entry changed (ms) */
@@ -47,7 +49,6 @@ typedef struct {
EmpathyContactFactory *factory;
EmpathyContactManager *manager;
EmpathyContact *contact;
- gboolean is_user;
EmpathyContactWidgetType type;
GtkCellRenderer *renderer;
guint widget_id_timeout;
@@ -100,6 +101,8 @@ static void contact_widget_set_contact (EmpathyContactWidget
static void contact_widget_contact_setup (EmpathyContactWidget *information);
static void contact_widget_contact_update (EmpathyContactWidget *information);
static gboolean contact_widget_update_contact (EmpathyContactWidget *information);
+static void contact_widget_avatar_changed_cb (EmpathyAvatarChooser *chooser,
+ EmpathyContactWidget *information);
static void contact_widget_account_changed_cb (GtkComboBox *widget,
EmpathyContactWidget *information);
static gboolean contact_widget_id_focus_out_cb (GtkWidget *widget,
@@ -153,13 +156,11 @@ empathy_contact_widget_new (EmpathyContact *contact,
GladeXML *glade;
information = g_slice_new0 (EmpathyContactWidget);
+ if (type == CONTACT_WIDGET_TYPE_EDIT && empathy_contact_is_user (contact)) {
+ type = CONTACT_WIDGET_TYPE_EDIT_USER;
+ }
information->type = type;
information->factory = empathy_contact_factory_new ();
- if (contact) {
- information->is_user = empathy_contact_is_user (contact);
- } else {
- information->is_user = FALSE;
- }
glade = empathy_glade_get_file ("empathy-contact-widget.glade",
"vbox_contact_widget",
@@ -339,12 +340,19 @@ contact_widget_id_changed_cb (GtkEntry *entry,
static void
contact_widget_contact_setup (EmpathyContactWidget *information)
{
- /* FIXME: Use EmpathyAvatarImage if (editable && is_user) */
- information->widget_avatar = gtk_image_new ();
+ if (information->type == CONTACT_WIDGET_TYPE_EDIT_USER) {
+ information->widget_avatar = empathy_avatar_chooser_new ();
+ g_signal_connect (information->widget_avatar, "changed",
+ G_CALLBACK (contact_widget_avatar_changed_cb),
+ information);
+ } else {
+ information->widget_avatar = empathy_avatar_image_new ();
+ }
gtk_box_pack_end (GTK_BOX (information->hbox_contact),
information->widget_avatar,
FALSE, FALSE,
6);
+ gtk_widget_show (information->widget_avatar);
/* Setup account label/chooser */
if (information->type == CONTACT_WIDGET_TYPE_ADD) {
@@ -459,6 +467,7 @@ contact_widget_contact_update (EmpathyContactWidget *information)
gtk_widget_show (information->label_alias);
gtk_widget_show (information->widget_alias);
gtk_widget_show (information->hbox_presence);
+ gtk_widget_show (information->widget_avatar);
} else {
gtk_widget_hide (information->label_alias);
gtk_widget_hide (information->widget_alias);
@@ -492,6 +501,20 @@ contact_widget_update_contact (EmpathyContactWidget *information)
}
static void
+contact_widget_avatar_changed_cb (EmpathyAvatarChooser *chooser,
+ EmpathyContactWidget *information)
+{
+ McAccount *account;
+ gchar *data;
+ gsize size;
+
+ account = empathy_contact_get_account (information->contact);
+ empathy_avatar_chooser_get_image_data (EMPATHY_AVATAR_CHOOSER (information->widget_avatar),
+ &data, &size);
+ mc_account_set_avatar_from_data (account, data, size, "png");
+}
+
+static void
contact_widget_account_changed_cb (GtkComboBox *widget,
EmpathyContactWidget *information)
{
@@ -550,18 +573,23 @@ contact_widget_presence_notify_cb (EmpathyContactWidget *information)
static void
contact_widget_avatar_notify_cb (EmpathyContactWidget *information)
{
- GdkPixbuf *avatar_pixbuf;
-
- avatar_pixbuf = empathy_pixbuf_avatar_from_contact_scaled (information->contact,
- 48, 48);
+ EmpathyAvatar *avatar = NULL;
- if (avatar_pixbuf) {
- gtk_image_set_from_pixbuf (GTK_IMAGE (information->widget_avatar),
- avatar_pixbuf);
- gtk_widget_show (information->widget_avatar);
- g_object_unref (avatar_pixbuf);
+ if (information->contact) {
+ avatar = empathy_contact_get_avatar (information->contact);
+ }
+ if (information->type == CONTACT_WIDGET_TYPE_EDIT_USER) {
+ g_signal_handlers_block_by_func (information->widget_avatar,
+ contact_widget_avatar_changed_cb,
+ information);
+ empathy_avatar_chooser_set (EMPATHY_AVATAR_CHOOSER (information->widget_avatar),
+ avatar);
+ g_signal_handlers_unblock_by_func (information->widget_avatar,
+ contact_widget_avatar_changed_cb,
+ information);
} else {
- gtk_widget_hide (information->widget_avatar);
+ empathy_avatar_image_set (EMPATHY_AVATAR_IMAGE (information->widget_avatar),
+ avatar);
}
}
diff --git a/libempathy-gtk/empathy-contact-widget.h b/libempathy-gtk/empathy-contact-widget.h
index 119d8a596..71fc06acb 100644
--- a/libempathy-gtk/empathy-contact-widget.h
+++ b/libempathy-gtk/empathy-contact-widget.h
@@ -30,10 +30,11 @@
G_BEGIN_DECLS
typedef enum {
- CONTACT_WIDGET_TYPE_SHOW, /* used to show contact information */
- CONTACT_WIDGET_TYPE_EDIT, /* used to edit contact information */
- CONTACT_WIDGET_TYPE_ADD, /* used to add a new contact */
- CONTACT_WIDGET_TYPE_SUBSCRIPTION /* used to accepte/reject a new contact */
+ CONTACT_WIDGET_TYPE_SHOW, /* used to show contact information */
+ CONTACT_WIDGET_TYPE_EDIT, /* used to edit contact information */
+ CONTACT_WIDGET_TYPE_ADD, /* used to add a new contact */
+ CONTACT_WIDGET_TYPE_SUBSCRIPTION, /* used to accepte/reject a new contact */
+ CONTACT_WIDGET_TYPE_EDIT_USER /* used to edit our own information */
} EmpathyContactWidgetType;
GtkWidget * empathy_contact_widget_new (EmpathyContact *contact,
diff --git a/libempathy-gtk/empathy-ui-utils.c b/libempathy-gtk/empathy-ui-utils.c
index 1c2d79c7b..fe032c9ee 100644
--- a/libempathy-gtk/empathy-ui-utils.c
+++ b/libempathy-gtk/empathy-ui-utils.c
@@ -201,35 +201,6 @@ empathy_glade_setup_size_group (GladeXML *gui,
va_end (args);
}
-GdkPixbuf *
-empathy_pixbuf_from_icon_name (const gchar *icon_name,
- GtkIconSize icon_size)
-{
- GtkIconTheme *theme;
- GdkPixbuf *pixbuf = NULL;
- GError *error = NULL;
- gint w, h;
- gint size = 48;
-
- theme = gtk_icon_theme_get_default ();
-
- if (gtk_icon_size_lookup (icon_size, &w, &h)) {
- size = (w + h) / 2;
- }
-
- pixbuf = gtk_icon_theme_load_icon (theme,
- icon_name,
- size,
- 0,
- &error);
- if (error) {
- empathy_debug (DEBUG_DOMAIN, "Error loading icon: %s", error->message);
- g_clear_error (&error);
- }
-
- return pixbuf;
-}
-
const gchar *
empathy_icon_name_from_account (McAccount *account)
{
@@ -293,6 +264,44 @@ empathy_icon_name_for_contact (EmpathyContact *contact)
return EMPATHY_IMAGE_UNKNOWN;
}
+GdkPixbuf *
+empathy_pixbuf_from_data (gchar *data,
+ gsize data_size)
+{
+ GdkPixbufLoader *loader;
+ GdkPixbuf *pixbuf = NULL;
+ GError *error = NULL;
+
+ if (!data) {
+ return NULL;
+ }
+
+ loader = gdk_pixbuf_loader_new ();
+ if (!gdk_pixbuf_loader_write (loader, data, data_size, &error)) {
+ empathy_debug (DEBUG_DOMAIN, "Failed to write to pixbuf loader: %s",
+ error ? error->message : "No error given");
+ g_clear_error (&error);
+ g_object_unref (loader);
+ return NULL;
+ }
+ if (!gdk_pixbuf_loader_close (loader, &error)) {
+ empathy_debug (DEBUG_DOMAIN, "Failed to close pixbuf loader: %s",
+ error ? error->message : "No error given");
+ g_clear_error (&error);
+ g_object_unref (loader);
+ return NULL;
+ }
+
+ pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ if (pixbuf) {
+ g_object_ref (pixbuf);
+ }
+
+ g_object_unref (loader);
+
+ return pixbuf;
+}
+
static void
pixbuf_from_avatar_size_prepared_cb (GdkPixbufLoader *loader,
int width,
@@ -488,6 +497,58 @@ empathy_pixbuf_avatar_from_contact_scaled (EmpathyContact *contact,
return empathy_pixbuf_from_avatar_scaled (avatar, width, height);
}
+GdkPixbuf *
+empathy_pixbuf_scale_down_if_necessary (GdkPixbuf *pixbuf, gint max_size)
+{
+ gint width, height;
+ gdouble factor;
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+
+ if (width > max_size || height > max_size) {
+ factor = (gdouble) max_size / MAX (width, height);
+
+ width = width * factor;
+ height = height * factor;
+
+ return gdk_pixbuf_scale_simple (pixbuf,
+ width, height,
+ GDK_INTERP_HYPER);
+ }
+
+ return g_object_ref (pixbuf);
+}
+
+GdkPixbuf *
+empathy_pixbuf_from_icon_name (const gchar *icon_name,
+ GtkIconSize icon_size)
+{
+ GtkIconTheme *theme;
+ GdkPixbuf *pixbuf = NULL;
+ GError *error = NULL;
+ gint w, h;
+ gint size = 48;
+
+ theme = gtk_icon_theme_get_default ();
+
+ if (gtk_icon_size_lookup (icon_size, &w, &h)) {
+ size = (w + h) / 2;
+ }
+
+ pixbuf = gtk_icon_theme_load_icon (theme,
+ icon_name,
+ size,
+ 0,
+ &error);
+ if (error) {
+ empathy_debug (DEBUG_DOMAIN, "Error loading icon: %s", error->message);
+ g_clear_error (&error);
+ }
+
+ return pixbuf;
+}
+
/* Stolen from GtkSourceView, hence the weird intendation. Please keep it like
* that to make it easier to apply changes from the original code.
*/
diff --git a/libempathy-gtk/empathy-ui-utils.h b/libempathy-gtk/empathy-ui-utils.h
index 3a8b896cb..eb189545a 100644
--- a/libempathy-gtk/empathy-ui-utils.h
+++ b/libempathy-gtk/empathy-ui-utils.h
@@ -48,63 +48,66 @@ G_BEGIN_DECLS
#define G_STR_EMPTY(x) ((x) == NULL || (x)[0] == '\0')
/* Glade */
-void empathy_glade_get_file_simple (const gchar *filename,
- const gchar *root,
- const gchar *domain,
- const gchar *first_required_widget,
- ...);
-GladeXML * empathy_glade_get_file (const gchar *filename,
- const gchar *root,
- const gchar *domain,
- const gchar *first_required_widget,
- ...);
-void empathy_glade_connect (GladeXML *gui,
- gpointer user_data,
- gchar *first_widget,
- ...);
-void empathy_glade_setup_size_group (GladeXML *gui,
- GtkSizeGroupMode mode,
- gchar *first_widget,
- ...);
+void empathy_glade_get_file_simple (const gchar *filename,
+ const gchar *root,
+ const gchar *domain,
+ const gchar *first_required_widget,
+ ...);
+GladeXML * empathy_glade_get_file (const gchar *filename,
+ const gchar *root,
+ const gchar *domain,
+ const gchar *first_required_widget,
+ ...);
+void empathy_glade_connect (GladeXML *gui,
+ gpointer user_data,
+ gchar *first_widget,
+ ...);
+void empathy_glade_setup_size_group (GladeXML *gui,
+ GtkSizeGroupMode mode,
+ gchar *first_widget,
+ ...);
/* Pixbufs */
-GdkPixbuf * empathy_pixbuf_from_icon_name (const gchar *icon_name,
- GtkIconSize icon_size);
-const gchar * empathy_icon_name_from_account (McAccount *account);
-const gchar * empathy_icon_name_for_presence_state (McPresence state);
-const gchar * empathy_icon_name_for_presence (EmpathyPresence *presence);
-const gchar * empathy_icon_name_for_contact (EmpathyContact *contact);
-GdkPixbuf * empathy_pixbuf_from_avatar_scaled (EmpathyAvatar *avatar,
- gint width,
- gint height);
-GdkPixbuf * empathy_pixbuf_avatar_from_contact_scaled (EmpathyContact *contact,
- gint width,
- gint height);
+const gchar * empathy_icon_name_from_account (McAccount *account);
+const gchar * empathy_icon_name_for_presence_state (McPresence state);
+const gchar * empathy_icon_name_for_presence (EmpathyPresence *presence);
+const gchar * empathy_icon_name_for_contact (EmpathyContact *contact);
+GdkPixbuf * empathy_pixbuf_from_data (gchar *data,
+ gsize data_size);
+GdkPixbuf * empathy_pixbuf_from_avatar_scaled (EmpathyAvatar *avatar,
+ gint width,
+ gint height);
+GdkPixbuf * empathy_pixbuf_avatar_from_contact_scaled (EmpathyContact *contact,
+ gint width,
+ gint height);
+GdkPixbuf * empathy_pixbuf_scale_down_if_necessary (GdkPixbuf *pixbuf,
+ gint max_size);
+GdkPixbuf * empathy_pixbuf_from_icon_name (const gchar *icon_name,
+ GtkIconSize icon_size);
/* Text view */
-gboolean empathy_text_iter_forward_search (const GtkTextIter *iter,
- const gchar *str,
- GtkTextIter *match_start,
- GtkTextIter *match_end,
- const GtkTextIter *limit);
-gboolean empathy_text_iter_backward_search (const GtkTextIter *iter,
- const gchar *str,
- GtkTextIter *match_start,
- GtkTextIter *match_end,
- const GtkTextIter *limit);
-
+gboolean empathy_text_iter_forward_search (const GtkTextIter*iter,
+ const gchar *str,
+ GtkTextIter *match_start,
+ GtkTextIter *match_end,
+ const GtkTextIter*limit);
+gboolean empathy_text_iter_backward_search (const GtkTextIter*iter,
+ const gchar *str,
+ GtkTextIter *match_start,
+ GtkTextIter *match_end,
+ const GtkTextIter*limit);
/* Windows */
-gboolean empathy_window_get_is_visible (GtkWindow *window);
-void empathy_window_present (GtkWindow *window,
- gboolean steal_focus);
-void empathy_window_iconify (GtkWindow *window,
- GtkStatusIcon *status_icon);
-GtkWindow *empathy_get_toplevel_window (GtkWidget *widget);
-void empathy_url_show (const char *url);
-void empathy_toggle_button_set_state_quietly (GtkWidget *widget,
- GCallback callback,
- gpointer user_data,
- gboolean active);
-GtkWidget *empathy_link_button_new (const gchar *url,
- const gchar *title);
+gboolean empathy_window_get_is_visible (GtkWindow *window);
+void empathy_window_present (GtkWindow *window,
+ gboolean steal_focus);
+void empathy_window_iconify (GtkWindow *window,
+ GtkStatusIcon *status_icon);
+GtkWindow * empathy_get_toplevel_window (GtkWidget *widget);
+void empathy_url_show (const char *url);
+void empathy_toggle_button_set_state_quietly (GtkWidget *widget,
+ GCallback callback,
+ gpointer user_data,
+ gboolean active);
+GtkWidget *empathy_link_button_new (const gchar *url,
+ const gchar *title);
G_END_DECLS