[gnome-initial-setup/wip/feborges/generate-user-pics: 1/4] 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: 1/4] account: Generate a default user profile picture
- Date: Mon, 4 Feb 2019 12:18:59 +0000 (UTC)
commit b59079bdb5621cd2da9664eabacfbf00f947f963
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 | 2 +
.../pages/account/um-photo-dialog.c | 37 +++++++
.../pages/account/um-photo-dialog.h | 3 +
gnome-initial-setup/pages/account/um-utils.c | 118 +++++++++++++++++++++
gnome-initial-setup/pages/account/um-utils.h | 3 +
6 files changed, 172 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..2c7bd9c 100644
--- a/gnome-initial-setup/pages/account/gis-account-page-local.c
+++ b/gnome-initial-setup/pages/account/gis-account-page-local.c
@@ -269,6 +269,8 @@ validate (GisAccountPageLocal *page)
gtk_label_set_text (GTK_LABEL (priv->username_explanation), tip);
g_free (tip);
+ um_photo_dialog_generate_avatar (priv->photo_dialog, name);
+
validation_changed (page);
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..e4ac51b 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,30 @@ on_popup_button_button_pressed (GtkToggleButton *button,
return FALSE;
}
+void
+um_photo_dialog_generate_avatar (UmPhotoDialog *um,
+ const gchar *name)
+{
+ cairo_surface_t *surface;
+ gchar *filename;
+
+ surface = generate_user_picture (name);
+
+ /* Save into a tmp file that later gets copied by AccountsService */
+ filename = g_build_filename (g_get_user_runtime_dir (), "avatar.png", NULL);
+ um->generated_avatar = g_file_new_for_path (filename);
+ cairo_surface_write_to_png (surface, g_file_get_path (um->generated_avatar));
+ g_free (filename);
+
+ /* 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 +355,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..678f1eb 100644
--- a/gnome-initial-setup/pages/account/um-utils.c
+++ b/gnome-initial-setup/pages/account/um-utils.c
@@ -476,3 +476,121 @@ 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)
+{
+ GString *initials = g_string_new ("");
+ const gchar *p;
+ gchar *normalized;
+ gunichar unichar;
+
+ p = g_strstrip (g_utf8_strup (name, -1));
+ normalized = g_utf8_normalize (p, -1, G_NORMALIZE_DEFAULT_COMPOSE);
+ if (normalized == NULL) {
+ g_free (normalized);
+
+ return NULL;
+ }
+
+ unichar = g_utf8_get_char (normalized);
+ g_string_append_unichar (initials, unichar);
+
+ p = g_utf8_strrchr (normalized, -1, ' ');
+ if (p != NULL && g_utf8_next_char (p) != NULL) {
+ p = g_utf8_next_char (p);
+
+ unichar = g_utf8_get_char (p);
+ g_string_append_unichar (initials, unichar);
+ }
+
+ g_free (normalized);
+
+ return g_string_free (initials, FALSE);
+}
+
+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] = {
+ { 98, 160, 234 },
+ { 53, 132, 228 },
+ { 28, 113, 216 },
+ { 26, 95, 180 },
+ { 87, 227, 137 },
+ { 51, 209, 122 },
+ { 46, 194, 126 },
+ { 38, 162, 105 },
+ { 248, 228, 92 },
+ { 246, 211, 45 },
+ { 245, 194, 17 },
+ { 229, 165, 10 },
+ { 255, 163, 72 },
+ { 255, 120, 0 },
+ { 230, 97, 0 },
+ { 198, 70, 0 },
+ { 237, 51, 59 },
+ { 224, 27, 36 },
+ { 192, 28, 40 },
+ { 165, 29, 45 },
+ { 192, 97, 203 },
+ { 163, 71, 186 },
+ { 129, 61, 156 },
+ { 97, 53, 131 },
+ { 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 = G_N_ELEMENTS (gnome_color_palette);
+ 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) {
+ PangoFontDescription *font_desc;
+ g_autofree gchar *initials = extract_initials_from_name (name);
+ g_autofree gchar *font = g_strdup_printf ("Sans %d", (int)ceil (IMAGE_SIZE / 2.5));
+ PangoLayout *layout;
+ GdkRGBA color = get_color_for_name (name);
+ cairo_surface_t *surface;
+ gint width, height;
+ cairo_t *cr;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ IMAGE_SIZE,
+ IMAGE_SIZE);
+ cr = cairo_create (surface);
+
+ cairo_arc (cr, IMAGE_SIZE/2, IMAGE_SIZE/2, IMAGE_SIZE/2, 0, 2 * G_PI);
+ cairo_set_source_rgb (cr, color.red/255.0, color.green/255.0, color.blue/255.0);
+ cairo_fill (cr);
+
+ /* Draw the initials on top */
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ layout = pango_cairo_create_layout (cr);
+ pango_layout_set_text (layout, initials, -1);
+ font_desc = pango_font_description_from_string (font);
+ pango_layout_set_font_description (layout, font_desc);
+ pango_font_description_free (font_desc);
+
+ pango_layout_get_size (layout, &width, &height);
+ cairo_translate (cr, IMAGE_SIZE/2, IMAGE_SIZE/2);
+ cairo_move_to (cr, - ((double)width / PANGO_SCALE)/2, - ((double)height/PANGO_SCALE)/2);
+ pango_cairo_show_layout (cr, layout);
+ 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]