[gnome-initial-setup/wip/feborges/generate-user-pics: 54/56] account: Generate a default user profile picture
- From: Felipe Borges <felipeborges src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-initial-setup/wip/feborges/generate-user-pics: 54/56] account: Generate a default user profile picture
- Date: Tue, 23 Oct 2018 10:41:53 +0000 (UTC)
commit 4fa37c74b05b28ca4b834189c2d2d030a09d0aee
Author: Felipe Borges <felipeborges gnome org>
Date: Tue Oct 23 11:41:28 2018 +0200
account: Generate a default user profile picture
Generate a default user account picture composed of a background
color and the user's initials.
The background color is defined by mapping the hash of the user
name with an existing colour in our palette[0].
A new avatar is generated whenever the user full name entry focuses
out.
These changes are based on the mockups for the Settings Users panel[1].
[0] https://gitlab.gnome.org/Community/Design/HIG-app-icons/blob/master/GNOME%20HIG.gpl
[1] https://wiki.gnome.org/Design/OS/AvatarChooser#Tentative_Design
Fixes #6
.../pages/account/gis-account-avatar-chooser.ui | 9 ++
.../pages/account/gis-account-page-local.c | 6 ++
.../pages/account/um-photo-dialog.c | 35 +++++++
.../pages/account/um-photo-dialog.h | 3 +
gnome-initial-setup/pages/account/um-utils.c | 109 +++++++++++++++++++++
gnome-initial-setup/pages/account/um-utils.h | 3 +
6 files changed, 165 insertions(+)
---
diff --git a/gnome-initial-setup/pages/account/gis-account-avatar-chooser.ui
b/gnome-initial-setup/pages/account/gis-account-avatar-chooser.ui
index 7ab6a18..871470b 100644
--- a/gnome-initial-setup/pages/account/gis-account-avatar-chooser.ui
+++ b/gnome-initial-setup/pages/account/gis-account-avatar-chooser.ui
@@ -8,6 +8,15 @@
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">GTK_ORIENTATION_VERTICAL</property>
+ <child>
+ <object class="GtkFlowBox" id="recent_pictures">
+ <property name="visible">True</property>
+ <property name="halign">start</property>
+ <property name="margin">20</property>
+ <property name="margin-bottom">0</property>
+ <property name="selection-mode">none</property>
+ </object>
+ </child>
<child>
<object class="GtkFlowBox" id="flowbox">
<property name="visible">True</property>
diff --git a/gnome-initial-setup/pages/account/gis-account-page-local.c
b/gnome-initial-setup/pages/account/gis-account-page-local.c
index e7a2cad..69fd317 100644
--- a/gnome-initial-setup/pages/account/gis-account-page-local.c
+++ b/gnome-initial-setup/pages/account/gis-account-page-local.c
@@ -277,8 +277,14 @@ validate (GisAccountPageLocal *page)
static gboolean
on_focusout (GisAccountPageLocal *page)
{
+ GisAccountPageLocalPrivate *priv = gis_account_page_local_get_instance_private (page);
+ const gchar *name;
+
validate (page);
+ name = gtk_entry_get_text (GTK_ENTRY (priv->fullname_entry));
+ um_photo_dialog_generate_avatar (priv->photo_dialog, name);
+
return FALSE;
}
diff --git a/gnome-initial-setup/pages/account/um-photo-dialog.c
b/gnome-initial-setup/pages/account/um-photo-dialog.c
index 4b6c38d..7d758d6 100644
--- a/gnome-initial-setup/pages/account/um-photo-dialog.c
+++ b/gnome-initial-setup/pages/account/um-photo-dialog.c
@@ -46,13 +46,16 @@ struct _UmPhotoDialog {
GtkWidget *popup_button;
GtkWidget *take_picture_button;
GtkWidget *flowbox;
+ GtkWidget *recent_pictures;
#ifdef HAVE_CHEESE
CheeseCameraDeviceMonitor *monitor;
guint num_cameras;
#endif /* HAVE_CHEESE */
+ GListStore *recent_faces;
GListStore *faces;
+ GFile *generated_avatar;
SelectAvatarCallback *callback;
gpointer data;
@@ -187,6 +190,15 @@ setup_photo_popup (UmPhotoDialog *um)
g_signal_connect (um->flowbox, "child-activated",
G_CALLBACK (face_widget_activated), um);
+ um->recent_faces = g_list_store_new (G_TYPE_FILE);
+ gtk_flow_box_bind_model (GTK_FLOW_BOX (um->recent_pictures),
+ G_LIST_MODEL (um->recent_faces),
+ create_face_widget,
+ um,
+ NULL);
+ g_signal_connect (um->recent_pictures, "child-activated",
+ G_CALLBACK (face_widget_activated), um);
+
dirs = g_get_system_data_dirs ();
for (i = 0; dirs[i] != NULL; i++) {
g_autoptr(GFileEnumerator) enumerator = NULL;
@@ -267,6 +279,28 @@ on_popup_button_button_pressed (GtkToggleButton *button,
return FALSE;
}
+void
+um_photo_dialog_generate_avatar (UmPhotoDialog *um,
+ const gchar *name)
+{
+ cairo_surface_t *surface;
+ GFileIOStream *io_stream = NULL;
+
+ surface = generate_user_picture (name);
+
+ /* Save into a tmp file that later gets copied by AccountssService */
+ um->generated_avatar = g_file_new_tmp ("usericonXXXXXX", &io_stream, NULL);
+ cairo_surface_write_to_png (surface, g_file_get_path (um->generated_avatar));
+
+ /* Overwrite the first item */
+ if (g_list_model_get_item (G_LIST_MODEL (um->recent_faces), 0) != NULL)
+ g_list_store_remove (um->recent_faces, 0);
+
+ g_list_store_insert (um->recent_faces, 0,
+ um->generated_avatar);
+ gtk_widget_show_all (um->recent_pictures);
+}
+
UmPhotoDialog *
um_photo_dialog_new (GtkWidget *button,
SelectAvatarCallback callback,
@@ -319,6 +353,7 @@ um_photo_dialog_class_init (UmPhotoDialogClass *klass)
gtk_widget_class_set_template_from_resource (wclass,
"/org/gnome/initial-setup/gis-account-avatar-chooser.ui");
gtk_widget_class_bind_template_child (wclass, UmPhotoDialog, flowbox);
+ gtk_widget_class_bind_template_child (wclass, UmPhotoDialog, recent_pictures);
gtk_widget_class_bind_template_child (wclass, UmPhotoDialog, take_picture_button);
#ifdef HAVE_CHEESE
gtk_widget_class_bind_template_callback (wclass, webcam_icon_selected);
diff --git a/gnome-initial-setup/pages/account/um-photo-dialog.h
b/gnome-initial-setup/pages/account/um-photo-dialog.h
index 964b415..20a1e7d 100644
--- a/gnome-initial-setup/pages/account/um-photo-dialog.h
+++ b/gnome-initial-setup/pages/account/um-photo-dialog.h
@@ -41,6 +41,9 @@ UmPhotoDialog *um_photo_dialog_new (GtkWidget *button,
gpointer data);
void um_photo_dialog_free (UmPhotoDialog *dialog);
+void um_photo_dialog_generate_avatar (UmPhotoDialog *dialog,
+ const gchar *name);
+
G_END_DECLS
#endif
diff --git a/gnome-initial-setup/pages/account/um-utils.c b/gnome-initial-setup/pages/account/um-utils.c
index 00133a7..924bd11 100644
--- a/gnome-initial-setup/pages/account/um-utils.c
+++ b/gnome-initial-setup/pages/account/um-utils.c
@@ -476,3 +476,112 @@ generate_username_choices (const gchar *name,
g_string_free (item3, TRUE);
g_string_free (item4, TRUE);
}
+
+#define IMAGE_SIZE 512
+
+static gchar *
+extract_initials_from_name (const gchar *name)
+{
+ g_autofree gchar *upper_cased_name = g_ascii_strup (name, -1);
+ gchar *initials = NULL;
+ gint i;
+
+ for (i = 1; upper_cased_name[i] != '\0'; i++) {
+ if (upper_cased_name[i] == ' ') {
+ initials = g_strdup_printf ("%c%c", name[0], name[i + 1]);
+ break;
+ }
+ }
+
+ if (initials == NULL)
+ initials = g_strdup_printf ("%c", name[0]);
+
+ return initials;
+}
+
+GdkRGBA
+get_color_for_name (const gchar *name)
+{
+ // https://gitlab.gnome.org/Community/Design/HIG-app-icons/blob/master/GNOME%20HIG.gpl
+ static gdouble gnome_color_palette[][3] = {
+ { 152, 193, 241 },
+ { 98, 160, 234 },
+ { 53, 132, 228 },
+ { 28, 113, 216 },
+ { 26, 95, 180 },
+ { 143, 240, 164 },
+ { 87, 227, 137 },
+ { 51, 209, 122 },
+ { 46, 194, 126 },
+ { 38, 162, 105 },
+ { 249, 240, 107 },
+ { 248, 228, 92 },
+ { 246, 211, 45 },
+ { 245, 194, 17 },
+ { 229, 165, 10 },
+ { 255, 190, 111 },
+ { 255, 163, 72 },
+ { 255, 120, 0 },
+ { 230, 97, 0 },
+ { 198, 70, 0 },
+ { 246, 97, 81 },
+ { 237, 51, 59 },
+ { 224, 27, 36 },
+ { 192, 28, 40 },
+ { 165, 29, 45 },
+ { 220, 138, 221 },
+ { 192, 97, 203 },
+ { 163, 71, 186 },
+ { 129, 61, 156 },
+ { 97, 53, 131 },
+ { 205, 171, 143 },
+ { 181, 131, 90 },
+ { 152, 106, 68 },
+ { 134, 94, 60 },
+ { 99, 69, 44 }
+ };
+
+ GdkRGBA color = { 255, 255, 255, 1.0 };
+ guint hash = g_str_hash (name);
+ gint number_of_colors = sizeof (gnome_color_palette)/sizeof (gnome_color_palette[0]);
+ gint idx = hash % number_of_colors;
+
+ color.red = gnome_color_palette[idx][0];
+ color.green = gnome_color_palette[idx][1];
+ color.blue = gnome_color_palette[idx][2];
+
+ return color;
+}
+
+cairo_surface_t *
+generate_user_picture (const gchar *name) {
+ g_autofree gchar *initials = extract_initials_from_name (name);
+ GdkRGBA color = get_color_for_name (name);
+ cairo_text_extents_t extents;
+ cairo_surface_t *surface;
+ gdouble x, y;
+ cairo_t *cr;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, IMAGE_SIZE, IMAGE_SIZE);
+ cr = cairo_create (surface);
+
+ cairo_set_source_rgb (cr, color.red/255.0, color.green/255.0, color.blue/255.0);
+ cairo_arc (cr, IMAGE_SIZE/2, IMAGE_SIZE/2, IMAGE_SIZE/2, 0, 2 * G_PI);
+ cairo_fill (cr);
+
+ /* Draw the initials on top */
+ cairo_set_source_rgb (cr, 36/255.0, 31/255.0, 49/255.0);
+ cairo_select_font_face (cr, "Cantarell",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size (cr, IMAGE_SIZE/2);
+ cairo_text_extents (cr, initials, &extents);
+ x = IMAGE_SIZE/2 - (extents.width/2 + extents.x_bearing);
+ y = IMAGE_SIZE/2 - (extents.height/2 + extents.y_bearing);
+
+ cairo_move_to (cr, x, y);
+ cairo_show_text (cr, initials);
+ cairo_destroy (cr);
+
+ return surface;
+}
diff --git a/gnome-initial-setup/pages/account/um-utils.h b/gnome-initial-setup/pages/account/um-utils.h
index d298721..7a3c010 100644
--- a/gnome-initial-setup/pages/account/um-utils.h
+++ b/gnome-initial-setup/pages/account/um-utils.h
@@ -52,6 +52,9 @@ gboolean is_valid_username (const gchar *name,
void generate_username_choices (const gchar *name,
GtkListStore *store);
+cairo_surface_t *generate_user_picture (const gchar *name);
+
+
G_END_DECLS
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]