[accounts-dialog] Use a popup menu to select the user's icon



commit 98005457c8ec879dceaeae5858063e636f8507cf
Author: Bastien Nocera <hadess hadess net>
Date:   Fri Jan 15 11:32:28 2010 +0000

    Use a popup menu to select the user's icon
    
    In a popup menu, present the user with the various options to
    select their user icon:
    - Reset icon
    - Set to the cropped version of a picture
    - Capture via webcam using Cheese
    - Select from the list of stock icons

 data/user-accounts-dialog.ui |    2 +-
 src/main.c                   |   31 +-
 src/um-crop-area.c           |    3 +
 src/um-photo-dialog.c        |  670 ++++++++++++++++++++++--------------------
 src/um-photo-dialog.h        |    5 +-
 5 files changed, 380 insertions(+), 331 deletions(-)
---
diff --git a/data/user-accounts-dialog.ui b/data/user-accounts-dialog.ui
index 63e424b..f8b622b 100644
--- a/data/user-accounts-dialog.ui
+++ b/data/user-accounts-dialog.ui
@@ -570,7 +570,7 @@
                                   </packing>
                                 </child>
                                 <child>
-                                  <object class="GtkButton" id="user-icon-button">
+                                  <object class="GtkToggleButton" id="user-icon-button">
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">True</property>
diff --git a/src/main.c b/src/main.c
index 7cd177b..79983c1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -19,6 +19,8 @@
  * Written by: Matthias Clasen <mclasen redhat com>
  */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <locale.h>
@@ -32,6 +34,10 @@
 #include <unique/unique.h>
 #include <polkit/polkit.h>
 
+#ifdef HAVE_CHEESE
+#include <gst/gst.h>
+#endif /* HAVE_CHEESE */
+
 #include "um-user.h"
 #include "um-user-manager.h"
 
@@ -366,6 +372,8 @@ show_user (UmUser *user, UserAccountDialog *d)
         gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf);
         g_object_unref (pixbuf);
 
+        um_photo_dialog_set_user (d->photo_dialog, user);
+
         label = get_widget (d, "full-name-value-label");
         gtk_label_set_text (GTK_LABEL (label), um_user_get_real_name (user));
         gtk_widget_set_tooltip_text (label, um_user_get_user_name (user));
@@ -676,20 +684,6 @@ selected_user_changed (GtkTreeSelection *selection, UserAccountDialog *d)
 }
 
 static void
-change_icon (GtkButton *button, UserAccountDialog *d)
-{
-        UmUser *user;
-
-        user = get_selected_user (d);
-
-        um_photo_dialog_set_user (d->photo_dialog, user);
-        um_photo_dialog_show (d->photo_dialog,
-                              GTK_WINDOW (get_widget (d, "user-account-window")));
-
-        g_object_unref (user);
-}
-
-static void
 change_name (GtkButton *button, UserAccountDialog *d)
 {
         UmUser *user;
@@ -1004,6 +998,7 @@ main (int argc, char *argv[])
         GError *error;
         const gchar *filename;
         GtkWidget *dialog;
+        GtkWidget *button;
         GOptionContext *context;
         static gboolean do_debug;
         static gboolean do_version;
@@ -1017,12 +1012,17 @@ main (int argc, char *argv[])
         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 
         g_thread_init (NULL);
+        gdk_threads_init ();
 
         context = g_option_context_new ("");
         g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
         g_option_context_set_summary (context, _("Lets you edit user account information."));
         g_option_context_add_main_entries (context, entries, NULL);
         g_option_context_add_group (context, gtk_get_option_group (TRUE));
+#ifdef HAVE_CHEESE
+	g_option_context_add_group (context, gst_init_get_option_group ());
+#endif /* HAVE_CHEESE */
+
         error = NULL;
         if (!g_option_context_parse (context, &argc, &argv, &error)) {
                 g_warning ("%s", error->message);
@@ -1076,8 +1076,9 @@ main (int argc, char *argv[])
         d->email_dialog = um_email_dialog_new ();
         d->language_dialog = um_language_dialog_new ();
         d->password_dialog = um_password_dialog_new ();
-        d->photo_dialog = um_photo_dialog_new ();
         d->location_dialog = um_location_dialog_new ();
+        button = get_widget (d, "user-icon-button");
+        d->photo_dialog = um_photo_dialog_new (button, d->main_window);
 
         d->main_window = get_widget (d, "user-account-window");
         gtk_widget_show (d->main_window);
diff --git a/src/um-crop-area.c b/src/um-crop-area.c
index 47053c0..3b19615 100644
--- a/src/um-crop-area.c
+++ b/src/um-crop-area.c
@@ -415,6 +415,9 @@ um_crop_area_motion_notify_event (GtkWidget      *widget,
 	gint width, height, d;
 	UmCropArea *area = UM_CROP_AREA (widget);
 
+	if (area->priv->browse_pixbuf == NULL)
+		return FALSE;
+
 	width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
 	height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
 
diff --git a/src/um-photo-dialog.c b/src/um-photo-dialog.c
index 906a588..31edf1c 100644
--- a/src/um-photo-dialog.c
+++ b/src/um-photo-dialog.c
@@ -19,6 +19,8 @@
  * Written by: Matthias Clasen <mclasen redhat com>
  */
 
+#include "config.h"
+
 #include <stdlib.h>
 
 #include <glib.h>
@@ -27,88 +29,85 @@
 #define GNOME_DESKTOP_USE_UNSTABLE_API
 #include <libgnomeui/gnome-desktop-thumbnail.h>
 
+#ifdef HAVE_CHEESE
+#include <cheese-avatar-chooser.h>
+#endif /* HAVE_CHEESE */
+
 #include "um-photo-dialog.h"
 #include "um-user-manager.h"
 #include "um-crop-area.h"
 
+#define ROW_SPAN 6
+
 struct _UmPhotoDialog {
-        GtkWidget *dialog;
-        GtkWidget *user_icon;
-        GtkWidget *user_name;
-        GtkWidget *gallery_radio;
-        GtkWidget *browse_radio;
-        GtkWidget *photo_radio;
-        GtkWidget *notebook;
-        GtkWidget *gallery;
-        GtkWidget *browse_drawing_area;
-        GtkWidget *browse_scale;
-        GtkWidget *ok_button;
-        GtkListStore *gallery_store;
+        GtkWidget *parent_window;
+        GtkWidget *photo_popup;
+        GtkWidget *popup_button;
+        GtkWidget *crop_area;
 
         GnomeDesktopThumbnailFactory *thumb_factory;
-        GdkPixbuf *browse_pixbuf;
 
         UmUser *user;
 };
 
 static void
-cancel_photo_dialog (GtkButton     *button,
-                     UmPhotoDialog *um)
+crop_dialog_response (GtkWidget     *dialog,
+                      gint           response_id,
+                      UmPhotoDialog *um)
 {
-        gtk_widget_hide (um->dialog);
-        um_photo_dialog_set_user (um, NULL);
-}
-
-static void
-accept_photo_dialog (GtkButton     *button,
-                     UmPhotoDialog *um)
-{
-        GtkTreeModel *model;
-        GList *selected;
-        GtkTreeIter iter;
-        gchar *file;
         GdkPixbuf *pb, *pb2;
 
-        switch (gtk_notebook_get_current_page (GTK_NOTEBOOK (um->notebook))) {
-        case 0:
-                model = GTK_TREE_MODEL (um->gallery_store);
-                selected = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (um->gallery));
-                if (selected == NULL)
-                        goto out;
-
-                gtk_tree_model_get_iter (model, &iter, (GtkTreePath *)selected->data);
-                g_list_foreach (selected, (GFunc)gtk_tree_path_free, NULL);
-                g_list_free (selected);
-
-                gtk_tree_model_get (model, &iter, 1, &file, -1);
-
-                um_user_set_icon_file (um->user, file);
-
-                g_free (file);
-                break;
-
-        case 1:
-                pb = um_crop_area_get_picture (UM_CROP_AREA (um->browse_drawing_area));
-                pb2 = gdk_pixbuf_scale_simple (pb, 96, 96, GDK_INTERP_BILINEAR);
+        if (response_id != GTK_RESPONSE_ACCEPT) {
+                um->crop_area = NULL;
+                gtk_widget_destroy (dialog);
+                return;
+        }
 
-                um_user_set_icon_data (um->user, pb2);
+        pb = um_crop_area_get_picture (UM_CROP_AREA (um->crop_area));
+        pb2 = gdk_pixbuf_scale_simple (pb, 96, 96, GDK_INTERP_BILINEAR);
 
-                g_object_unref (pb2);
-                g_object_unref (pb);
+        um_user_set_icon_data (um->user, pb2);
 
-        }
+        g_object_unref (pb2);
+        g_object_unref (pb);
 
-out:
-        gtk_widget_hide (um->dialog);
-        um_photo_dialog_set_user (um, NULL);
+        um->crop_area = NULL;
+        gtk_widget_destroy (dialog);
 }
 
 static void
-show_gallery (GtkButton     *button,
-              UmPhotoDialog *um)
+um_photo_dialog_crop (UmPhotoDialog *um,
+                      GdkPixbuf     *pixbuf)
 {
-        gtk_notebook_set_current_page (GTK_NOTEBOOK (um->notebook), 0);
-        gtk_widget_set_sensitive (um->ok_button, TRUE);
+        GtkWidget *dialog;
+        GtkWidget *frame;
+
+        dialog = gtk_dialog_new_with_buttons ("",
+                                              GTK_WINDOW (um->parent_window),
+                                              GTK_DIALOG_NO_SEPARATOR,
+                                              GTK_STOCK_CANCEL,
+                                              GTK_RESPONSE_REJECT,
+                                              "Select",
+                                              GTK_RESPONSE_ACCEPT,
+                                              NULL);
+
+        g_signal_connect (G_OBJECT (dialog), "response",
+                          G_CALLBACK (crop_dialog_response), um);
+
+        /* Content */
+        um->crop_area           = um_crop_area_new ();
+        um_crop_area_set_picture (UM_CROP_AREA (um->crop_area), pixbuf);
+        frame                   = gtk_frame_new (NULL);
+        gtk_container_add (GTK_CONTAINER (frame), um->crop_area);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
+
+        gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+                            frame,
+                            TRUE, TRUE, 8);
+
+        gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 300);
+
+        gtk_widget_show_all (dialog);
 }
 
 static void
@@ -120,35 +119,30 @@ file_chooser_response (GtkDialog     *chooser,
         GError *error;
         GdkPixbuf *pixbuf;
 
-        if (response == GTK_RESPONSE_ACCEPT) {
-                filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
-
-                error = NULL;
-                pixbuf = gdk_pixbuf_new_from_file (filename, &error);
-                if (pixbuf == NULL) {
-                        g_warning ("Failed to load %s: %s", filename, error->message);
-                        g_error_free (error);
-                }
-                if (um->browse_pixbuf)
-                        g_object_unref (um->browse_pixbuf);
-                um->browse_pixbuf = pixbuf;
-
-                um_crop_area_set_picture (UM_CROP_AREA (um->browse_drawing_area), pixbuf);
+        if (response != GTK_RESPONSE_ACCEPT) {
+                gtk_widget_destroy (GTK_WIDGET (chooser));
+                return;
+        }
 
-                g_free (filename);
+        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
 
-                gtk_widget_set_sensitive (um->ok_button, TRUE);
-        }
-        else {
-                gtk_widget_set_sensitive (um->ok_button, FALSE);
+        error = NULL;
+        pixbuf = gdk_pixbuf_new_from_file (filename, &error);
+        if (pixbuf == NULL) {
+                g_warning ("Failed to load %s: %s", filename, error->message);
+                g_error_free (error);
         }
+        g_free (filename);
 
         gtk_widget_destroy (GTK_WIDGET (chooser));
+
+        um_photo_dialog_crop (um, pixbuf);
+        g_object_unref (pixbuf);
 }
 
 static void
-update_preview (GtkFileChooser *chooser,
-                UmPhotoDialog  *um)
+update_preview (GtkFileChooser               *chooser,
+                GnomeDesktopThumbnailFactory *thumb_factory)
 {
         gchar *uri;
 
@@ -176,7 +170,7 @@ update_preview (GtkFileChooser *chooser,
                 }
 
                 if (mime_type) {
-                        pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (um->thumb_factory,
+                        pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (thumb_factory,
                                                                                      uri,
                                                                                      mime_type);
                 }
@@ -198,27 +192,20 @@ update_preview (GtkFileChooser *chooser,
 }
 
 static void
-show_files (GtkButton     *button,
-            UmPhotoDialog *um)
+um_photo_dialog_select_file (UmPhotoDialog *um)
 {
         GtkWidget *chooser;
         const gchar *folder;
         GtkWidget *preview;
 
-        if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
-                return;
-
-        gtk_notebook_set_current_page (GTK_NOTEBOOK (um->notebook), 1);
-
         chooser = gtk_file_chooser_dialog_new (_("Browse for more pictures"),
-                                               GTK_WINDOW (um->dialog),
+                                               GTK_WINDOW (um->parent_window),
                                                GTK_FILE_CHOOSER_ACTION_OPEN,
                                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                                GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                                NULL);
 
-        gtk_window_set_modal (GTK_WINDOW (chooser),
-                              gtk_window_get_modal (GTK_WINDOW (um->dialog)));
+        gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
 
         preview = gtk_image_new ();
         gtk_widget_set_size_request (preview, 128, -1);
@@ -226,7 +213,7 @@ show_files (GtkButton     *button,
         gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (chooser), FALSE);
         gtk_widget_show (preview);
         g_signal_connect (chooser, "update-preview",
-                          G_CALLBACK (update_preview), um);
+                          G_CALLBACK (update_preview), um->thumb_factory);
 
         folder = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
         if (folder)
@@ -237,200 +224,266 @@ show_files (GtkButton     *button,
                           G_CALLBACK (file_chooser_response), um);
 
         gtk_window_present (GTK_WINDOW (chooser));
-        gtk_widget_set_sensitive (um->ok_button, FALSE);
 }
 
 static void
-show_photo (GtkButton     *button,
-            UmPhotoDialog *um)
+none_icon_selected (GtkMenuItem   *menuitem,
+                    UmPhotoDialog *um)
 {
-        gtk_notebook_set_current_page (GTK_NOTEBOOK (um->notebook), 2);
-        gtk_widget_set_sensitive (um->ok_button, FALSE);
+        um_user_set_icon_file (um->user, NULL);
 }
 
 static void
-load_faces (UmPhotoDialog *um)
+file_icon_selected (GtkMenuItem   *menuitem,
+                    UmPhotoDialog *um)
 {
-        GDir *dir;
-        const gchar *face;
-        gchar *filename;
+        um_photo_dialog_select_file (um);
+}
+
+#ifdef HAVE_CHEESE
+static gboolean
+destroy_chooser (GtkWidget *chooser)
+{
+        gtk_widget_destroy (chooser);
+        return FALSE;
+}
+
+static void
+webcam_response_cb (GtkDialog     *dialog,
+                    int            response,
+                    UmPhotoDialog  *um)
+{
+        if (response == GTK_RESPONSE_ACCEPT) {
+                GdkPixbuf *pb, *pb2;
+
+                g_object_get (G_OBJECT (dialog), "pixbuf", &pb, NULL);
+                pb2 = gdk_pixbuf_scale_simple (pb, 96, 96, GDK_INTERP_BILINEAR);
+
+                um_user_set_icon_data (um->user, pb2);
+
+                g_object_unref (pb2);
+                g_object_unref (pb);
+        }
+        if (response != GTK_RESPONSE_DELETE_EVENT &&
+            response != GTK_RESPONSE_NONE)
+                g_idle_add ((GSourceFunc) destroy_chooser, dialog);
+}
+
+static void
+webcam_icon_selected (GtkMenuItem   *menuitem,
+                      UmPhotoDialog *um)
+{
+        GtkWidget *window;
+
+        window = cheese_avatar_chooser_new ();
+        gtk_window_set_transient_for (GTK_WINDOW (window),
+                                      GTK_WINDOW (um->parent_window));
+        g_signal_connect (G_OBJECT (window), "response",
+                          G_CALLBACK (webcam_response_cb), um);
+        gtk_widget_show (window);
+}
+#endif /* HAVE_CHEESE */
+
+static void
+stock_icon_selected (GtkMenuItem   *menuitem,
+                     UmPhotoDialog *um)
+{
+        const char *filename;
+
+        filename = g_object_get_data (G_OBJECT (menuitem), "filename");
+        um_user_set_icon_file (um->user, filename);
+}
+
+static GtkWidget *
+menu_item_for_filename (UmPhotoDialog *um,
+                        const char    *filename)
+{
+        GtkWidget *image, *menuitem;
         GFile *file;
         GIcon *icon;
-        GtkListStore *store;
-        GtkTreeIter iter;
 
-        /* TODO load incrementally, add recent images, add user faces */
-        store = gtk_list_store_new (4, G_TYPE_ICON, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_STRING);
+        file = g_file_new_for_path (filename);
+        icon = g_file_icon_new (file);
+        g_object_unref (file);
+        image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_DIALOG);
+        g_object_unref (icon);
+
+        menuitem = gtk_menu_item_new ();
+        gtk_container_add (GTK_CONTAINER (menuitem), image);
+        gtk_widget_show_all (menuitem);
+
+        g_object_set_data_full (G_OBJECT (menuitem), "filename",
+                                g_strdup (filename), (GDestroyNotify) g_free);
+        g_signal_connect (G_OBJECT (menuitem), "activate",
+                          G_CALLBACK (stock_icon_selected), um);
+
+        return menuitem;
+}
+
+static void
+setup_photo_popup (UmPhotoDialog *um)
+{
+        GtkWidget *menu, *menuitem;
+        guint x, y;
+        GDir *dir;
+        const char *face;
+
+        menu = gtk_menu_new ();
+
+        menuitem = gtk_menu_item_new_with_label (_("None"));
+        gtk_menu_attach (GTK_MENU (menu), GTK_WIDGET (menuitem),
+                         0, ROW_SPAN - 1, 0, 1);
+        g_signal_connect (G_OBJECT (menuitem), "activate",
+                          G_CALLBACK (none_icon_selected), um);
+        gtk_widget_show (menuitem);
+
+        menuitem = gtk_menu_item_new_with_label (_("Browse for more pictures..."));
+        gtk_menu_attach (GTK_MENU (menu), GTK_WIDGET (menuitem),
+                         0, ROW_SPAN - 1, 1, 2);
+        g_signal_connect (G_OBJECT (menuitem), "activate",
+                          G_CALLBACK (file_icon_selected), um);
+        gtk_widget_show (menuitem);
+
+#ifdef HAVE_CHEESE
+        menuitem = gtk_menu_item_new_with_label (_("Take a photograph..."));
+        gtk_menu_attach (GTK_MENU (menu), GTK_WIDGET (menuitem),
+                         0, ROW_SPAN - 1, 2, 3);
+        g_signal_connect (G_OBJECT (menuitem), "activate",
+                          G_CALLBACK (webcam_icon_selected), um);
+        gtk_widget_show (menuitem);
+#endif /* HAVE_CHEESE */
+
+        /* Separator */
+        menuitem = gtk_separator_menu_item_new ();
+#ifdef HAVE_CHEESE
+        gtk_menu_attach (GTK_MENU (menu), GTK_WIDGET (menuitem),
+                         0, ROW_SPAN - 1, 3, 4);
+#else
+        gtk_menu_attach (GTK_MENU (menu), GTK_WIDGET (menuitem),
+                         0, ROW_SPAN - 1, 2, 3);
+#endif /* HAVE_CHEESE */
+        gtk_widget_show (menuitem);
+
+        x = 0;
+#ifdef HAVE_CHEESE
+        y = 5;
+#else
+        y = 4;
+#endif /* HAVE_CHEESE */
         dir = g_dir_open (DATADIR "/pixmaps/faces", 0, NULL);
         while ((face = g_dir_read_name (dir)) != NULL) {
+                char *filename;
+
                 filename = g_build_filename (DATADIR "/pixmaps/faces", face, NULL);
-                file = g_file_new_for_path (filename);
-                icon = g_file_icon_new (file);
-                gtk_list_store_append (store, &iter);
-                gtk_list_store_set (store, &iter, 0, icon, 1, filename, 2, TRUE, 3, NULL, -1);
-                g_object_unref (icon);
-                g_object_unref (file);
+                menuitem = menu_item_for_filename (um, filename);
                 g_free (filename);
+                if (menuitem == NULL)
+                        continue;
+
+                gtk_menu_attach (GTK_MENU (menu), GTK_WIDGET (menuitem),
+                                 x, x + 1, y, y + 1);
+                gtk_widget_show (menuitem);
+
+                x++;
+                if (x >= ROW_SPAN - 1) {
+                        y++;
+                        x = 0;
+                }
         }
         g_dir_close (dir);
 
-        gtk_icon_view_set_model (GTK_ICON_VIEW (um->gallery), GTK_TREE_MODEL (store));
-        um->gallery_store = store;
+        um->photo_popup = menu;
 }
 
 static void
-gallery_selection_changed (GtkIconView   *gallery,
-                           UmPhotoDialog *um)
+popup_icon_menu_position (GtkMenu *menu,
+                          gint *x,
+                          gint *y,
+                          gboolean *push_in,
+                          UmPhotoDialog *um)
 {
-        GList *list;
-        GtkTreeModel *model;
-        GtkTreePath *path;
-        GtkTreeIter iter;
-        gboolean can_select;
-
-        model = GTK_TREE_MODEL (um->gallery_store);
-        list = gtk_icon_view_get_selected_items (gallery);
-        if (list == NULL) {
-                can_select = FALSE;
-                goto out;
-        }
+        GtkRequisition menu_req;
+        GtkTextDirection direction;
+        GtkAllocation allocation;
 
-        path = list->data;
+        gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
 
-        gtk_tree_model_get_iter (model, &iter, path);
-        gtk_tree_model_get (model, &iter, 2, &can_select, -1);
+        direction = gtk_widget_get_direction (um->popup_button);
 
-        g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
-        g_list_free (list);
+        gdk_window_get_origin (gtk_widget_get_window (um->popup_button), x, y);
+        gtk_widget_get_allocation (um->popup_button, &allocation);
+        *x += allocation.x;
+        *y += allocation.y + allocation.height;
 
-out:
-        gtk_widget_set_sensitive (um->ok_button, can_select);
+        if (direction == GTK_TEXT_DIR_LTR)
+                *x += MAX (allocation.width - menu_req.width, 0);
+        else if (menu_req.width > allocation.width)
+                *x -= menu_req.width - allocation.width;
+
+        *push_in = TRUE;
 }
 
 static void
-gallery_item_activated (GtkIconView   *gallery,
-                        GtkTreePath   *path,
-                        UmPhotoDialog *um)
+popup_icon_menu (GtkToggleButton *button, UmPhotoDialog *um)
 {
-        GtkTreeModel *model;
-        GtkTreeIter iter;
-        gboolean can_select;
-        gchar *file;
-
-        model = GTK_TREE_MODEL (um->gallery_store);
-        gtk_tree_model_get_iter (model, &iter, path);
-        gtk_tree_model_get (model, &iter, 2, &can_select, -1);
-
-        if (!can_select)
-                return;
-
-        gtk_tree_model_get (model, &iter, 1, &file, -1);
+        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) && !GTK_WIDGET_VISIBLE (um->photo_popup)) {
+                gtk_menu_popup (GTK_MENU (um->photo_popup),
+                                NULL, NULL,
+                                (GtkMenuPositionFunc) popup_icon_menu_position, um,
+                                0, gtk_get_current_event_time ());
+        } else {
+                gtk_menu_popdown (GTK_MENU (um->photo_popup));
+        }
+}
 
-        um_user_set_icon_file (um->user, file);
+static gboolean
+on_popup_button_button_pressed (GtkToggleButton *button,
+                                GdkEventButton *event,
+                                UmPhotoDialog  *um)
+{
+        if (event->button == 1) {
+                if (!GTK_WIDGET_VISIBLE (um->photo_popup)) {
+                        popup_icon_menu (button, um);
+                        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+                } else {
+                        gtk_menu_popdown (GTK_MENU (um->photo_popup));
+                        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
+                }
 
-        g_free (file);
+                return TRUE;
+        }
 
-        gtk_widget_hide (um->dialog);
-        um_photo_dialog_set_user (um, NULL);
+        return FALSE;
 }
 
 static void
-scale_changed (GtkRange      *range,
-               UmPhotoDialog *um)
+on_photo_popup_unmap (GtkWidget     *popup_menu,
+                      UmPhotoDialog *um)
 {
-        gtk_widget_queue_draw (um->browse_drawing_area);
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (um->popup_button), FALSE);
 }
 
 UmPhotoDialog *
-um_photo_dialog_new (void)
+um_photo_dialog_new (GtkWidget *button, GtkWidget *parent)
 {
-        GtkBuilder *builder;
-        GtkWidget *widget;
         UmPhotoDialog *um;
-        const gchar *filename;
-        GError *error = NULL;
-        GtkCellRenderer *cell;
-
-        builder = gtk_builder_new ();
-
-        filename = DATADIR "/" PACKAGE_NAME "/photo-dialog.ui";
-        if (!g_file_test (filename, G_FILE_TEST_EXISTS))
-                filename = "../data/photo-dialog.ui";
-        if (!gtk_builder_add_from_file (builder, filename, &error)) {
-                g_error ("%s", error->message);
-                g_error_free (error);
-                exit (1);
-        }
 
         um = g_new0 (UmPhotoDialog, 1);
 
-        widget = (GtkWidget *) gtk_builder_get_object (builder, "dialog");
-        g_signal_connect (widget, "delete-event",
-                          G_CALLBACK (gtk_widget_hide_on_delete), NULL);
-        um->dialog = widget;
-
-        um->notebook = (GtkWidget *) gtk_builder_get_object (builder, "notebook");
-        um->user_icon = (GtkWidget *) gtk_builder_get_object (builder, "user-icon");
-        um->user_name = (GtkWidget *) gtk_builder_get_object (builder, "user-name");
-
-        widget = (GtkWidget *) gtk_builder_get_object (builder, "cancel-button");
-        g_signal_connect (widget, "clicked",
-                          G_CALLBACK (cancel_photo_dialog), um);
-
-        widget = (GtkWidget *) gtk_builder_get_object (builder, "ok-button");
-        g_signal_connect (widget, "clicked",
-                          G_CALLBACK (accept_photo_dialog), um);
-        um->ok_button = widget;
-        gtk_widget_grab_default (widget);
-
-        widget = (GtkWidget *) gtk_builder_get_object (builder, "gallery-radiobutton");
-        g_signal_connect (widget, "clicked",
-                          G_CALLBACK (show_gallery), um);
-        um->gallery_radio = widget;
-
-        widget = (GtkWidget *) gtk_builder_get_object (builder, "browse-radiobutton");
-        g_signal_connect (widget, "clicked",
-                          G_CALLBACK (show_files), um);
-        um->browse_radio = widget;
-
-        widget = (GtkWidget *) gtk_builder_get_object (builder, "photo-radiobutton");
-        g_signal_connect (widget, "clicked",
-                          G_CALLBACK (show_photo), um);
-        um->photo_radio = widget;
-
-        widget = (GtkWidget *) gtk_builder_get_object (builder, "gallery");
-        g_signal_connect (widget, "selection-changed",
-                          G_CALLBACK (gallery_selection_changed), um);
-        g_signal_connect (widget, "item-activated",
-                          G_CALLBACK (gallery_item_activated), um);
-        gtk_icon_view_set_item_padding (GTK_ICON_VIEW (widget), 4);
-        gtk_icon_view_set_row_spacing (GTK_ICON_VIEW (widget), 0);
-        gtk_icon_view_set_column_spacing (GTK_ICON_VIEW (widget), 0);
-        gtk_widget_set_size_request (widget, 248, -1);
-        cell = gtk_cell_renderer_pixbuf_new ();
-        g_object_set (cell, "stock-size", GTK_ICON_SIZE_DIALOG, NULL);
-        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), cell, FALSE);
-        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (widget), cell, "gicon", 0);
-        gtk_icon_view_set_tooltip_column (GTK_ICON_VIEW (widget), 3);
-
-        um->gallery = widget;
-
         um->thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
 
-        /* FIXME replace drawing area with UmCropArea */
-        widget = (GtkWidget *) gtk_builder_get_object (builder, "browse-drawing-area");
-        gtk_widget_destroy (widget);
-        um->browse_drawing_area = um_crop_area_new ();
-        widget = (GtkWidget *) gtk_builder_get_object (builder, "vbox1234");
-        gtk_box_pack_start (GTK_BOX (widget), um->browse_drawing_area, TRUE, TRUE, 0);
-        gtk_widget_show (um->browse_drawing_area);
+        /* Set up the popup */
+        um->popup_button = button;
+        setup_photo_popup (um);
+        g_signal_connect (button, "toggled",
+                          G_CALLBACK (popup_icon_menu), um);
+        g_signal_connect (G_OBJECT (um->popup_button), "button-press-event",
+                          G_CALLBACK (on_popup_button_button_pressed), um);
+        g_signal_connect (um->photo_popup, "unmap",
+                          G_CALLBACK (on_photo_popup_unmap), um);
 
-        widget = (GtkWidget *) gtk_builder_get_object (builder, "browse-scale");
-        g_signal_connect (widget, "value-changed",
-                          G_CALLBACK (scale_changed), um);
-        um->browse_scale = widget;
-
-        load_faces (um);
+        /* Parent window */
+        um->parent_window = parent;
 
         return um;
 }
@@ -438,7 +491,10 @@ um_photo_dialog_new (void)
 void
 um_photo_dialog_free (UmPhotoDialog *um)
 {
-        gtk_widget_destroy (um->dialog);
+        gtk_widget_destroy (um->photo_popup);
+
+        if (um->thumb_factory)
+                g_object_unref (um->thumb_factory);
 
         if (um->user)
                 g_object_unref (um->user);
@@ -446,47 +502,68 @@ um_photo_dialog_free (UmPhotoDialog *um)
         g_free (um);
 }
 
-static gboolean
-clear_tip (GtkTreeModel *model,
-           GtkTreePath  *path,
-           GtkTreeIter  *iter,
-           gpointer      data)
+static void
+clear_tip (GtkMenuItem  *item,
+           gpointer      user_data)
 {
+        GList *children;
+        GtkWidget *image;
         GIcon *icon, *icon2;
+        const char *filename;
+
+        /* Not a stock icon? */
+        filename = g_object_get_data (G_OBJECT (item), "filename");
+        if (filename == NULL)
+                return;
 
-        gtk_tree_model_get (model, iter, 0, &icon, -1);
+        children = gtk_container_get_children (GTK_CONTAINER (item));
+        image = children->data;
+        g_assert (image != NULL);
+        g_list_free (children);
+
+        gtk_image_get_gicon (GTK_IMAGE (image), &icon, NULL);
 
         if (G_IS_EMBLEMED_ICON (icon))
                 icon2 = g_emblemed_icon_get_icon (G_EMBLEMED_ICON (icon));
         else
-                icon2 = icon;
+                return;
 
-        gtk_list_store_set ((GtkListStore *)model, iter,
-                            0, icon2,
-                            2, TRUE,
-                            3, NULL,
-                            -1);
+        gtk_image_set_from_gicon (GTK_IMAGE (image), icon2, GTK_ICON_SIZE_DIALOG);
         g_object_unref (icon);
+}
 
-        return FALSE;
+static void
+set_tip (GtkWidget  *item,
+         const char *tip,
+         GEmblem    *emblem)
+{
+        GList *children;
+        GtkWidget *image;
+        GIcon *icon, *icon2;
+
+        children = gtk_container_get_children (GTK_CONTAINER (item));
+        image = children->data;
+        g_assert (image != NULL);
+        g_list_free (children);
+
+        gtk_image_get_gicon (GTK_IMAGE (image), &icon, NULL);
+        g_object_ref (emblem);
+        icon2 = g_emblemed_icon_new (icon, emblem);
+        gtk_image_set_from_gicon (GTK_IMAGE (image), icon2, GTK_ICON_SIZE_DIALOG);
+
+        gtk_widget_set_tooltip_text (GTK_WIDGET (item), tip);
 }
 
 void
 um_photo_dialog_set_user (UmPhotoDialog *um,
                           UmUser        *user)
 {
-        GdkPixbuf *pixbuf;
-        const gchar *name;
-        GtkTreeModel *model;
-        GtkTreeIter iter;
-        GtkTreePath *path;
         UmUserManager *manager;
         GSList *list, *l;
         UmUser *u;
-        const gchar *filename;
-        gchar *tip, *f;
-        GIcon *icon, *icon2;
+        GIcon *icon;
         GEmblem *emblem;
+        GList *children, *c;
 
         g_return_if_fail (um != NULL);
 
@@ -495,18 +572,12 @@ um_photo_dialog_set_user (UmPhotoDialog *um,
                 um->user = NULL;
         }
         um->user = user;
+
         if (um->user) {
                 g_object_ref (user);
 
-                pixbuf = um_user_render_icon (user, FALSE, 48);
-		gtk_image_set_from_pixbuf (GTK_IMAGE (um->user_icon), pixbuf);
-		g_object_unref (pixbuf);
-
-                name = um_user_get_real_name (user);
-                gtk_label_set_label (GTK_LABEL (um->user_name), name);
-
-                model = GTK_TREE_MODEL (um->gallery_store);
-                gtk_tree_model_foreach (model, clear_tip, NULL);
+                children = gtk_container_get_children (GTK_CONTAINER (um->photo_popup));
+                g_list_foreach (children, (GFunc) clear_tip, NULL);
 
                 manager = um_user_manager_ref_default ();
                 list = um_user_manager_list_users (manager);
@@ -517,59 +588,34 @@ um_photo_dialog_set_user (UmPhotoDialog *um,
                 g_object_unref (icon);
 
                 for (l = list; l; l = l->next) {
+                        const char *filename;
+
                         u = l->data;
+                        if (u == user)
+                                continue;
                         filename = um_user_get_icon_file (u);
                         if (filename  == NULL)
                                 continue;
-                        gtk_tree_model_get_iter_first (model, &iter);
-                        do {
-                                gtk_tree_model_get (model, &iter, 1, &f, -1);
-                                if (g_strcmp0 (f, filename) == 0) {
-                                        if (u == user) {
-                                                path = gtk_tree_model_get_path (model, &iter);
-                                                gtk_icon_view_select_path (GTK_ICON_VIEW (um->gallery), path);
-                                                gtk_tree_path_free (path);
-                                        }
-                                        else {
-                                                tip = g_strdup_printf (_("Used by %s"),
-                                                                       um_user_get_real_name (u));
-                                                gtk_tree_model_get (model, &iter, 0, &icon, -1);
-                                                icon2 = g_emblemed_icon_new (icon, emblem);
-                                                gtk_list_store_set ((GtkListStore*)model, &iter,
-                                                                    0, icon2,
-                                                                    2, FALSE,
-                                                                    3, tip,
-                                                                    -1);
-                                                g_object_unref (icon);
-                                                g_object_unref (icon2);
-                                                g_free (tip);
-                                        }
-
-                                        g_free (f);
+                        for (c = children; c; c = c->next) {
+                                const char *f;
+
+                                f = g_object_get_data (G_OBJECT (c->data), "filename");
+                                if (f == NULL)
+                                        continue;
+                                if (strcmp (f, filename) == 0) {
+                                        char *tip;
+
+                                        tip = g_strdup_printf (_("Used by %s"),
+                                                               um_user_get_real_name (u));
+                                        set_tip (GTK_WIDGET (c->data), tip, emblem);
+                                        g_free (tip);
                                         break;
                                 }
-                                g_free (f);
-                        } while (gtk_tree_model_iter_next (model, &iter));
+                        }
                 }
                 g_slist_free (list);
 
                 g_object_unref (emblem);
-
-                gallery_selection_changed (GTK_ICON_VIEW (um->gallery), um);
-
-                gtk_notebook_set_current_page (GTK_NOTEBOOK (um->notebook), 0);
-                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (um->gallery_radio), TRUE);
-                if (um->browse_pixbuf) {
-                        g_object_unref (um->browse_pixbuf);
-                        um->browse_pixbuf = NULL;
-                }
         }
 }
 
-void
-um_photo_dialog_show (UmPhotoDialog *um,
-                      GtkWindow     *parent)
-{
-        gtk_window_set_transient_for (GTK_WINDOW (um->dialog), parent);
-        gtk_window_present (GTK_WINDOW (um->dialog));
-}
diff --git a/src/um-photo-dialog.h b/src/um-photo-dialog.h
index 32a975c..f5a9b5f 100644
--- a/src/um-photo-dialog.h
+++ b/src/um-photo-dialog.h
@@ -29,12 +29,11 @@ G_BEGIN_DECLS
 
 typedef struct _UmPhotoDialog UmPhotoDialog;
 
-UmPhotoDialog *um_photo_dialog_new      (void);
+UmPhotoDialog *um_photo_dialog_new      (GtkWidget *button,
+                                         GtkWidget *parent);
 void           um_photo_dialog_free     (UmPhotoDialog *dialog);
 void           um_photo_dialog_set_user (UmPhotoDialog *dialog,
                                          UmUser        *user);
-void           um_photo_dialog_show     (UmPhotoDialog *dialog,
-                                         GtkWindow     *parent);
 
 G_END_DECLS
 



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