1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright 2009-2010 Red Hat, Inc,
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
* Written by: Matthias Clasen <mclasen@redhat.com>
27
#include <glib/gi18n.h>
29
#define GNOME_DESKTOP_USE_UNSTABLE_API
30
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
33
#include <cheese-avatar-chooser.h>
34
#include <cheese-camera-device.h>
35
#include <cheese-camera-device-monitor.h>
36
#endif /* HAVE_CHEESE */
38
#include "um-photo-dialog.h"
39
#include "um-user-manager.h"
40
#include "um-crop-area.h"
45
struct _UmPhotoDialog {
46
GtkWidget *photo_popup;
47
GtkWidget *popup_button;
51
CheeseCameraDeviceMonitor *monitor;
52
GtkWidget *take_photo_menuitem;
54
#endif /* HAVE_CHEESE */
56
GnomeDesktopThumbnailFactory *thumb_factory;
62
crop_dialog_response (GtkWidget *dialog,
68
if (response_id != GTK_RESPONSE_ACCEPT) {
70
gtk_widget_destroy (dialog);
74
pb = um_crop_area_get_picture (UM_CROP_AREA (um->crop_area));
75
pb2 = gdk_pixbuf_scale_simple (pb, 96, 96, GDK_INTERP_BILINEAR);
77
um_user_set_icon_data (um->user, pb2);
83
gtk_widget_destroy (dialog);
87
um_photo_dialog_crop (UmPhotoDialog *um,
93
dialog = gtk_dialog_new_with_buttons ("",
94
GTK_WINDOW (gtk_widget_get_toplevel (um->popup_button)),
101
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
103
gtk_window_set_icon_name (GTK_WINDOW (dialog), "system-users");
105
g_signal_connect (G_OBJECT (dialog), "response",
106
G_CALLBACK (crop_dialog_response), um);
109
um->crop_area = um_crop_area_new ();
110
um_crop_area_set_min_size (UM_CROP_AREA (um->crop_area), 48, 48);
111
um_crop_area_set_constrain_aspect (UM_CROP_AREA (um->crop_area), TRUE);
112
um_crop_area_set_picture (UM_CROP_AREA (um->crop_area), pixbuf);
113
frame = gtk_frame_new (NULL);
114
gtk_container_add (GTK_CONTAINER (frame), um->crop_area);
115
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
117
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
121
gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 300);
123
gtk_widget_show_all (dialog);
127
file_chooser_response (GtkDialog *chooser,
135
if (response != GTK_RESPONSE_ACCEPT) {
136
gtk_widget_destroy (GTK_WIDGET (chooser));
140
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
143
pixbuf = gdk_pixbuf_new_from_file (filename, &error);
144
if (pixbuf == NULL) {
145
g_warning ("Failed to load %s: %s", filename, error->message);
146
g_error_free (error);
150
gtk_widget_destroy (GTK_WIDGET (chooser));
152
um_photo_dialog_crop (um, pixbuf);
153
g_object_unref (pixbuf);
157
update_preview (GtkFileChooser *chooser,
158
GnomeDesktopThumbnailFactory *thumb_factory)
162
uri = gtk_file_chooser_get_preview_uri (chooser);
165
GdkPixbuf *pixbuf = NULL;
166
const gchar *mime_type = NULL;
168
GFileInfo *file_info;
171
preview = gtk_file_chooser_get_preview_widget (chooser);
173
file = g_file_new_for_uri (uri);
174
file_info = g_file_query_info (file,
175
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
176
G_FILE_QUERY_INFO_NONE,
178
g_object_unref (file);
180
if (file_info != NULL) {
181
mime_type = g_file_info_get_content_type (file_info);
182
g_object_unref (file_info);
186
pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (thumb_factory,
191
gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser),
195
if (pixbuf != NULL) {
196
gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf);
197
g_object_unref (pixbuf);
200
gtk_image_set_from_stock (GTK_IMAGE (preview),
201
GTK_STOCK_DIALOG_QUESTION,
202
GTK_ICON_SIZE_DIALOG);
208
gtk_file_chooser_set_preview_widget_active (chooser, TRUE);
212
um_photo_dialog_select_file (UmPhotoDialog *um)
218
chooser = gtk_file_chooser_dialog_new (_("Browse for more pictures"),
219
GTK_WINDOW (gtk_widget_get_toplevel (um->popup_button)),
220
GTK_FILE_CHOOSER_ACTION_OPEN,
221
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
222
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
225
gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
227
preview = gtk_image_new ();
228
gtk_widget_set_size_request (preview, 128, -1);
229
gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (chooser), preview);
230
gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (chooser), FALSE);
231
gtk_widget_show (preview);
232
g_signal_connect (chooser, "update-preview",
233
G_CALLBACK (update_preview), um->thumb_factory);
235
folder = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
237
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser),
240
g_signal_connect (chooser, "response",
241
G_CALLBACK (file_chooser_response), um);
243
gtk_window_present (GTK_WINDOW (chooser));
247
none_icon_selected (GtkMenuItem *menuitem,
250
um_user_set_icon_file (um->user, NULL);
254
file_icon_selected (GtkMenuItem *menuitem,
257
um_photo_dialog_select_file (um);
262
destroy_chooser (GtkWidget *chooser)
264
gtk_widget_destroy (chooser);
269
webcam_response_cb (GtkDialog *dialog,
273
if (response == GTK_RESPONSE_ACCEPT) {
276
g_object_get (G_OBJECT (dialog), "pixbuf", &pb, NULL);
277
pb2 = gdk_pixbuf_scale_simple (pb, 96, 96, GDK_INTERP_BILINEAR);
279
um_user_set_icon_data (um->user, pb2);
281
g_object_unref (pb2);
284
if (response != GTK_RESPONSE_DELETE_EVENT &&
285
response != GTK_RESPONSE_NONE)
286
g_idle_add ((GSourceFunc) destroy_chooser, dialog);
290
webcam_icon_selected (GtkMenuItem *menuitem,
295
window = cheese_avatar_chooser_new ();
296
gtk_window_set_transient_for (GTK_WINDOW (window),
297
GTK_WINDOW (gtk_widget_get_toplevel (um->popup_button)));
298
gtk_window_set_modal (GTK_WINDOW (window), TRUE);
299
g_signal_connect (G_OBJECT (window), "response",
300
G_CALLBACK (webcam_response_cb), um);
301
gtk_widget_show (window);
305
update_photo_menu_status (UmPhotoDialog *um)
307
if (um->num_cameras == 0)
308
gtk_widget_set_sensitive (um->take_photo_menuitem, FALSE);
310
gtk_widget_set_sensitive (um->take_photo_menuitem, TRUE);
314
device_added (CheeseCameraDeviceMonitor *monitor,
315
CheeseCameraDevice *device,
319
update_photo_menu_status (um);
323
device_removed (CheeseCameraDeviceMonitor *monitor,
328
update_photo_menu_status (um);
331
#endif /* HAVE_CHEESE */
334
stock_icon_selected (GtkMenuItem *menuitem,
337
const char *filename;
339
filename = g_object_get_data (G_OBJECT (menuitem), "filename");
340
um_user_set_icon_file (um->user, filename);
344
menu_item_for_filename (UmPhotoDialog *um,
345
const char *filename)
347
GtkWidget *image, *menuitem;
351
file = g_file_new_for_path (filename);
352
icon = g_file_icon_new (file);
353
g_object_unref (file);
354
image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_DIALOG);
355
g_object_unref (icon);
357
menuitem = gtk_menu_item_new ();
358
gtk_container_add (GTK_CONTAINER (menuitem), image);
359
gtk_widget_show_all (menuitem);
361
g_object_set_data_full (G_OBJECT (menuitem), "filename",
362
g_strdup (filename), (GDestroyNotify) g_free);
363
g_signal_connect (G_OBJECT (menuitem), "activate",
364
G_CALLBACK (stock_icon_selected), um);
370
setup_photo_popup (UmPhotoDialog *um)
372
GtkWidget *menu, *menuitem, *image;
374
const gchar * const * dirs;
378
gboolean none_item_shown;
379
gboolean added_faces;
381
menu = gtk_menu_new ();
385
none_item_shown = added_faces = FALSE;
387
dirs = g_get_system_data_dirs ();
388
for (i = 0; dirs[i] != NULL; i++) {
391
path = g_build_filename (dirs[i], "pixmaps", "faces", NULL);
392
dir = g_dir_open (path, 0, NULL);
398
while ((face = g_dir_read_name (dir)) != NULL) {
403
filename = g_build_filename (path, face, NULL);
404
menuitem = menu_item_for_filename (um, filename);
406
if (menuitem == NULL)
409
gtk_menu_attach (GTK_MENU (menu), GTK_WIDGET (menuitem),
411
gtk_widget_show (menuitem);
414
if (x >= ROW_SPAN - 1) {
429
image = gtk_image_new_from_icon_name ("avatar-default", GTK_ICON_SIZE_DIALOG);
430
menuitem = gtk_menu_item_new ();
431
gtk_container_add (GTK_CONTAINER (menuitem), image);
432
gtk_widget_show_all (menuitem);
433
gtk_menu_attach (GTK_MENU (menu), GTK_WIDGET (menuitem),
435
g_signal_connect (G_OBJECT (menuitem), "activate",
436
G_CALLBACK (none_icon_selected), um);
437
gtk_widget_show (menuitem);
438
none_item_shown = TRUE;
442
if (!none_item_shown) {
443
menuitem = gtk_menu_item_new_with_label (_("Disable image"));
444
gtk_menu_attach (GTK_MENU (menu), GTK_WIDGET (menuitem),
445
0, ROW_SPAN - 1, y, y + 1);
446
g_signal_connect (G_OBJECT (menuitem), "activate",
447
G_CALLBACK (none_icon_selected), um);
448
gtk_widget_show (menuitem);
453
menuitem = gtk_separator_menu_item_new ();
454
gtk_menu_attach (GTK_MENU (menu), GTK_WIDGET (menuitem),
455
0, ROW_SPAN - 1, y, y + 1);
456
gtk_widget_show (menuitem);
461
um->take_photo_menuitem = gtk_menu_item_new_with_label (_("Take a photo..."));
462
gtk_menu_attach (GTK_MENU (menu), GTK_WIDGET (um->take_photo_menuitem),
463
0, ROW_SPAN - 1, y, y + 1);
464
g_signal_connect (G_OBJECT (um->take_photo_menuitem), "activate",
465
G_CALLBACK (webcam_icon_selected), um);
466
gtk_widget_set_sensitive (um->take_photo_menuitem, FALSE);
467
gtk_widget_show (um->take_photo_menuitem);
469
um->monitor = cheese_camera_device_monitor_new ();
470
g_signal_connect (G_OBJECT (um->monitor), "added",
471
G_CALLBACK (device_added), um);
472
g_signal_connect (G_OBJECT (um->monitor), "removed",
473
G_CALLBACK (device_removed), um);
474
cheese_camera_device_monitor_coldplug (um->monitor);
477
#endif /* HAVE_CHEESE */
479
menuitem = gtk_menu_item_new_with_label (_("Browse for more pictures..."));
480
gtk_menu_attach (GTK_MENU (menu), GTK_WIDGET (menuitem),
481
0, ROW_SPAN - 1, y, y + 1);
482
g_signal_connect (G_OBJECT (menuitem), "activate",
483
G_CALLBACK (file_icon_selected), um);
484
gtk_widget_show (menuitem);
486
um->photo_popup = menu;
490
popup_icon_menu (GtkToggleButton *button, UmPhotoDialog *um)
492
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) && !gtk_widget_get_visible (um->photo_popup)) {
493
gtk_menu_popup (GTK_MENU (um->photo_popup),
495
(GtkMenuPositionFunc) popup_menu_below_button, um->popup_button,
496
0, gtk_get_current_event_time ());
498
gtk_menu_popdown (GTK_MENU (um->photo_popup));
503
on_popup_button_button_pressed (GtkToggleButton *button,
504
GdkEventButton *event,
507
if (event->button == 1) {
508
if (!gtk_widget_get_visible (um->photo_popup)) {
509
popup_icon_menu (button, um);
510
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
512
gtk_menu_popdown (GTK_MENU (um->photo_popup));
513
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
523
on_photo_popup_unmap (GtkWidget *popup_menu,
526
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (um->popup_button), FALSE);
530
popup_button_draw (GtkWidget *widget,
534
if (gtk_widget_get_state (gtk_bin_get_child (GTK_BIN (widget))) != GTK_STATE_PRELIGHT &&
535
!gtk_widget_is_focus (widget)) {
539
down_arrow (gtk_widget_get_style_context (widget),
541
gtk_widget_get_allocated_width (widget) - 12,
542
gtk_widget_get_allocated_height (widget) - 12,
547
popup_button_focus_changed (GObject *button,
551
gtk_widget_queue_draw (gtk_bin_get_child (GTK_BIN (button)));
555
um_photo_dialog_new (GtkWidget *button)
559
um = g_new0 (UmPhotoDialog, 1);
561
um->thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
563
/* Set up the popup */
564
um->popup_button = button;
565
setup_photo_popup (um);
566
g_signal_connect (button, "toggled",
567
G_CALLBACK (popup_icon_menu), um);
568
g_signal_connect (button, "button-press-event",
569
G_CALLBACK (on_popup_button_button_pressed), um);
570
g_signal_connect (button, "notify::is-focus",
571
G_CALLBACK (popup_button_focus_changed), um);
572
g_signal_connect_after (button, "draw",
573
G_CALLBACK (popup_button_draw), um);
575
g_signal_connect (um->photo_popup, "unmap",
576
G_CALLBACK (on_photo_popup_unmap), um);
582
um_photo_dialog_free (UmPhotoDialog *um)
584
gtk_widget_destroy (um->photo_popup);
586
if (um->thumb_factory)
587
g_object_unref (um->thumb_factory);
590
g_object_unref (um->monitor);
593
g_object_unref (um->user);
599
clear_tip (GtkMenuItem *item,
605
const char *filename;
607
/* Not a stock icon? */
608
filename = g_object_get_data (G_OBJECT (item), "filename");
609
if (filename == NULL)
612
children = gtk_container_get_children (GTK_CONTAINER (item));
613
image = children->data;
614
g_assert (image != NULL);
615
g_list_free (children);
617
gtk_image_get_gicon (GTK_IMAGE (image), &icon, NULL);
619
if (G_IS_EMBLEMED_ICON (icon))
620
icon2 = g_emblemed_icon_get_icon (G_EMBLEMED_ICON (icon));
624
gtk_image_set_from_gicon (GTK_IMAGE (image), icon2, GTK_ICON_SIZE_DIALOG);
625
g_object_unref (icon);
629
set_tip (GtkWidget *item,
637
children = gtk_container_get_children (GTK_CONTAINER (item));
638
image = children->data;
639
g_assert (image != NULL);
640
g_list_free (children);
642
gtk_image_get_gicon (GTK_IMAGE (image), &icon, NULL);
643
if (G_IS_EMBLEMED_ICON (icon)) {
647
icon2 = g_emblemed_icon_new (icon, emblem);
648
gtk_image_set_from_gicon (GTK_IMAGE (image), icon2, GTK_ICON_SIZE_DIALOG);
650
gtk_widget_set_tooltip_text (GTK_WIDGET (item), tip);
654
um_photo_dialog_set_user (UmPhotoDialog *um,
657
UmUserManager *manager;
664
g_return_if_fail (um != NULL);
667
g_object_unref (um->user);
673
g_object_ref (um->user);
675
children = gtk_container_get_children (GTK_CONTAINER (um->photo_popup));
676
g_list_foreach (children, (GFunc) clear_tip, NULL);
678
manager = um_user_manager_ref_default ();
679
list = um_user_manager_list_users (manager);
680
g_object_unref (manager);
682
icon = g_themed_icon_new ("avatar-default");
683
emblem = g_emblem_new (icon);
684
g_object_unref (icon);
686
for (l = list; l; l = l->next) {
687
const char *filename;
692
filename = um_user_get_icon_file (u);
693
if (filename == NULL)
695
for (c = children; c; c = c->next) {
698
f = g_object_get_data (G_OBJECT (c->data), "filename");
701
if (strcmp (f, filename) == 0) {
704
tip = g_strdup_printf (_("Used by %s"),
705
um_user_get_real_name (u));
706
set_tip (GTK_WIDGET (c->data), tip, emblem);
714
g_object_unref (emblem);