summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/ui/contacts-avatar-dialog.ui313
-rw-r--r--data/ui/style.css18
-rw-r--r--meson.build1
-rw-r--r--src/contacts-avatar-dialog.vala114
-rw-r--r--src/contacts-contact-editor.vala32
-rw-r--r--src/contacts-contact-frame.vala120
-rw-r--r--src/contacts-utils.vala22
-rw-r--r--src/meson.build2
8 files changed, 239 insertions, 383 deletions
diff --git a/data/ui/contacts-avatar-dialog.ui b/data/ui/contacts-avatar-dialog.ui
index b9c0819..851116b 100644
--- a/data/ui/contacts-avatar-dialog.ui
+++ b/data/ui/contacts-avatar-dialog.ui
@@ -1,293 +1,164 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.20"/>
- <template class="ContactsAvatarDialog" parent="GtkDialog">
+ <template class="ContactsAvatarPopover" parent="GtkPopover">
<property name="visible">True</property>
- <property name="title" translatable="yes">Select Picture</property>
- <property name="modal">True</property>
<style>
- <class name="contacts-avatar-dialog"/>
+ <class name="contacts-avatar-popover"/>
</style>
- <child internal-child="vbox">
+ <child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <property name="margin">12</property>
<child>
- <object class="GtkGrid" id="grid">
+ <object class="GtkStack" id="views_stack">
<property name="visible">True</property>
- <property name="border_width">8</property>
- <property name="column_spacing">16</property>
- <property name="row_spacing">11</property>
<child>
- </child>
- <!-- ContactFrame -->
- <placeholder/>
- <child>
- <object class="GtkLabel" id="contact_name_label">
+ <object class="GtkFlowBox" id="personas_thumbnail_grid">
<property name="visible">True</property>
- <property name="halign">start</property>
- <property name="valign">start</property>
- <property name="hexpand">True</property>
- <property name="margin_top">4</property>
- <property name="ellipsize">end</property>
- <property name="label" translatable="yes">New Contact</property>
- <style>
- <class name="contact-display-name"/>
- </style>
+ <property name="orientation">vertical</property>
</object>
<packing>
- <property name="top_attach">0</property>
- <property name="left_attach">1</property>
+ <property name="name">thumbnail-page</property>
</packing>
</child>
<child>
- <object class="GtkFrame">
+ <object class="GtkGrid" id="crop_page">
<property name="visible">True</property>
- <style>
- <class name="contacts-avatar-frame"/>
- </style>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkStack" id="views_stack">
+ <object class="GtkActionBar">
<property name="visible">True</property>
<child>
- <object class="GtkGrid" id="thumbnail_page">
+ <object class="GtkBox">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="orientation">horizontal</property>
+ <style>
+ <class name="linked"/>
+ </style>
<child>
- <object class="GtkScrolledWindow">
+ <object class="GtkButton">
<property name="visible">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="height_request">300</property>
+ <signal name="clicked" handler="on_crop_page_select_button_clicked" swapped="no"/>
<child>
- <object class="GtkBox">
+ <object class="GtkImage">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkFlowBox" id="personas_thumbnail_grid">
- <property name="visible">True</property>
- </object>
- </child>
- <child>
- <object class="GtkSeparator">
- <property name="visible">True</property>
- <property name="orientation">horizontal</property>
- </object>
- </child>
- <child>
- <object class="GtkFlowBox" id="stock_thumbnail_grid">
- <property name="visible">True</property>
- <property name="min_children_per_line">5</property>
- <property name="max_children_per_line">8</property>
- </object>
- </child>
+ <property name="can_focus">False</property>
+ <property name="pixel_size">16</property>
+ <property name="icon_name">object-select-symbolic</property>
</object>
</child>
</object>
</child>
<child>
- <object class="GtkActionBar">
+ <object class="GtkButton">
<property name="visible">True</property>
+ <signal name="clicked" handler="on_crop_page_cancel_button_clicked" swapped="no"/>
<child>
- <object class="GtkBox" id="webcam_button_box">
- <property name="orientation">horizontal</property>
- <style>
- <class name="linked"/>
- </style>
- <child>
- <object class="GtkButton">
- <property name="visible">True</property>
- <signal name="clicked" handler="select_avatar_file_cb" swapped="no"/>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="pixel_size">16</property>
- <property name="icon_name">list-add-symbolic</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkButton" id="webcam_button">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <signal name="clicked" handler="on_webcam_button_clicked" swapped="no"/>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="pixel_size">16</property>
- <property name="icon_name">camera-photo-symbolic</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkButton">
- <property name="visible" bind-source="webcam_button_box" bind-property="visible" bind-flags="invert-boolean|sync-create" />
- <signal name="clicked" handler="select_avatar_file_cb" swapped="no"/>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="pixel_size">16</property>
- <property name="icon_name">list-add-symbolic</property>
- </object>
- </child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="pixel_size">16</property>
+ <property name="icon_name">edit-undo-symbolic</property>
</object>
</child>
</object>
</child>
</object>
- <packing>
- <property name="name">thumbnail-page</property>
- </packing>
</child>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="name">crop-page</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="photobooth_page">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkActionBar">
+ <property name="visible">True</property>
<child>
- <object class="GtkGrid" id="crop_page">
+ <object class="GtkBox">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="orientation">horizontal</property>
+ <style>
+ <class name="linked"/>
+ </style>
<child>
- <object class="GtkActionBar">
+ <object class="GtkButton">
<property name="visible">True</property>
+ <signal name="clicked" handler="on_photobooth_page_select_button_clicked" swapped="no"/>
<child>
- <object class="GtkBox">
+ <object class="GtkImage">
<property name="visible">True</property>
- <property name="orientation">horizontal</property>
- <style>
- <class name="linked"/>
- </style>
- <child>
- <object class="GtkButton">
- <property name="visible">True</property>
- <signal name="clicked" handler="on_crop_page_select_button_clicked" swapped="no"/>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="pixel_size">16</property>
- <property name="icon_name">object-select-symbolic</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkButton">
- <property name="visible">True</property>
- <signal name="clicked" handler="on_crop_page_cancel_button_clicked" swapped="no"/>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="pixel_size">16</property>
- <property name="icon_name">edit-undo-symbolic</property>
- </object>
- </child>
- </object>
- </child>
+ <property name="can_focus">False</property>
+ <property name="pixel_size">16</property>
+ <property name="icon_name">object-select-symbolic</property>
</object>
</child>
</object>
- <packing>
- <property name="top_attach">1</property>
- <property name="left_attach">0</property>
- </packing>
</child>
- </object>
- <packing>
- <property name="name">crop-page</property>
- </packing>
- </child>
- <child>
- <object class="GtkGrid" id="photobooth_page">
- <property name="orientation">vertical</property>
<child>
- <object class="GtkActionBar">
+ <object class="GtkButton">
<property name="visible">True</property>
+ <signal name="clicked" handler="on_photobooth_page_cancel_button_clicked" swapped="no"/>
<child>
- <object class="GtkBox">
+ <object class="GtkImage">
<property name="visible">True</property>
- <property name="orientation">horizontal</property>
- <style>
- <class name="linked"/>
- </style>
- <child>
- <object class="GtkButton">
- <property name="visible">True</property>
- <signal name="clicked" handler="on_photobooth_page_select_button_clicked" swapped="no"/>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="pixel_size">16</property>
- <property name="icon_name">object-select-symbolic</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkButton">
- <property name="visible">True</property>
- <signal name="clicked" handler="on_photobooth_page_cancel_button_clicked" swapped="no"/>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="pixel_size">16</property>
- <property name="icon_name">edit-undo-symbolic</property>
- </object>
- </child>
- </object>
- </child>
+ <property name="can_focus">False</property>
+ <property name="pixel_size">16</property>
+ <property name="icon_name">edit-undo-symbolic</property>
</object>
</child>
</object>
- <packing>
- <property name="top_attach">1</property>
- <property name="left_attach">0</property>
- </packing>
</child>
</object>
- <packing>
- <property name="name">photobooth-page</property>
- </packing>
</child>
</object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">0</property>
+ </packing>
</child>
</object>
<packing>
- <property name="top_attach">1</property>
- <property name="left_attach">0</property>
- <property name="width">2</property>
+ <property name="name">photobooth-page</property>
</packing>
</child>
</object>
</child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">horizontal</property>
+ <property name="halign">center</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkButton" id="webcam_button">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="label" translatable="yes">Take a picture…</property>
+ <signal name="clicked" handler="on_webcam_button_clicked" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Select a file…</property>
+ <signal name="clicked" handler="select_avatar_file_cb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
</object>
</child>
-
- <child type="action">
- <object class="GtkButton" id="select_button">
- <property name="visible">True</property>
- <property name="can-default">True</property>
- <property name="sensitive">False</property>
- <property name="label" translatable="yes">Select</property>
- </object>
- </child>
- <child type="action">
- <object class="GtkButton" id="cancel_button">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Cancel</property>
- </object>
- </child>
- <action-widgets>
- <action-widget response="cancel">cancel_button</action-widget>
- <action-widget response="ok" default="true">select_button</action-widget>
- </action-widgets>
</template>
</interface>
diff --git a/data/ui/style.css b/data/ui/style.css
index 6a75863..01c94bb 100644
--- a/data/ui/style.css
+++ b/data/ui/style.css
@@ -56,23 +56,11 @@ row.contact-data-row {
}
.contacts-avatar-frame.frame {
- border-width: 1px 1px 1px 1px;
- border-style: solid;
- border-color: @borders;
- border-image: none;
- border-radius: 0;
- padding: 0;
-}
-
-.main-avatar-frame.frame {
- border-width: 1px;
- border-style: solid;
- border-color: @borders;
- border-radius: 6px;
+ padding: 0;
}
.main-avatar-frame border {
- border-radius: 5px;
+ border-width: 0;
}
/* Give the avatar in the ContactSheet some margin,
@@ -136,6 +124,6 @@ ContactsWindow .primary-toolbar.toolbar {
text-shadow: 1px 1px alpha(@theme_base_color, 0.6);
}
-.contacts-avatar-dialog .contact-display-name {
+.contacts-avatar-popover .contact-display-name {
font-size: 20px;
}
diff --git a/meson.build b/meson.build
index 9238512..4f58e34 100644
--- a/meson.build
+++ b/meson.build
@@ -36,7 +36,6 @@ gee = dependency('gee-0.8')
gio_unix = dependency('gio-unix-2.0', version: '>=' + min_glib_version)
glib = dependency('glib-2.0', version: '>=' + min_glib_version)
gmodule_export = dependency('gmodule-export-2.0', version: '>=' + min_glib_version)
-gnome_desktop = dependency('gnome-desktop-3.0')
goa = dependency('goa-1.0')
gtk = dependency('gtk+-3.0', version: '>= 3.22.0')
libebook = dependency('libebook-1.2', version: '>=' + min_eds_version)
diff --git a/src/contacts-avatar-dialog.vala b/src/contacts-avatar-dialog.vala
index 58f3010..21a0031 100644
--- a/src/contacts-avatar-dialog.vala
+++ b/src/contacts-avatar-dialog.vala
@@ -21,40 +21,32 @@ using Folks;
/**
* The AvatarDialog can be used to choose the avatar for a contact.
- * This can be done by either choosing a stock thumbnail, an image file
- * provided by the user, or -if cheese is enabled- by using a webcam.
+ * This can be done by choosing from:
+ * - one of the contact's avatar,
+ * - an image file on the user's machine
+ * - (if cheese is enabled) a webcam.
+ * - a fallback avatar
*
* After a user has initially chosen an avatar, we provide a cropping tool.
*/
[GtkTemplate (ui = "/org/gnome/Contacts/ui/contacts-avatar-dialog.ui")]
-public class Contacts.AvatarDialog : Dialog {
+public class Contacts.AvatarPopover : Popover {
const int MAIN_SIZE = 128;
const int ICONS_SIZE = 64;
private Contact contact;
- // This will provide the default thumbnails
- private Gnome.DesktopThumbnailFactory thumbnail_factory;
-
- [GtkChild]
- private Grid grid;
- [GtkChild]
- private Label contact_name_label;
[GtkChild]
private Stack views_stack;
[GtkChild]
private FlowBox personas_thumbnail_grid;
[GtkChild]
- private FlowBox stock_thumbnail_grid;
- [GtkChild]
private Grid crop_page;
private Cc.CropArea crop_area;
[GtkChild]
private Grid photobooth_page;
[GtkChild]
private Button webcam_button;
- [GtkChild]
- private Box webcam_button_box;
private ContactFrame current_avatar;
@@ -72,13 +64,12 @@ public class Contacts.AvatarDialog : Dialog {
*/
public signal void set_avatar (GLib.Icon avatar_icon);
- public AvatarDialog (Window main_window, Contact? contact) {
+ public AvatarPopover (Widget? relative_to, Contact? contact) {
Object (
- transient_for: main_window,
- use_header_bar: 1
+ relative_to: relative_to,
+ modal: true
);
- this.thumbnail_factory = new Gnome.DesktopThumbnailFactory (Gnome.ThumbnailSize.NORMAL);
this.contact = contact;
// Load the current avatar
@@ -92,14 +83,10 @@ public class Contacts.AvatarDialog : Dialog {
}
this.current_avatar.set_hexpand (false);
this.current_avatar.show ();
- this.grid.attach (this.current_avatar, 0, 0);
+ /* this.grid.attach (this.current_avatar, 0, 0); */
- if (contact != null)
- this.contact_name_label.label = contact.display_name;
#if HAVE_CHEESE
- this.webcam_button_box.show ();
-
// Look for camera devices.
this.camera_monitor = new Cheese.CameraDeviceMonitor ();
this.camera_monitor.added.connect ( () => {
@@ -125,9 +112,6 @@ public class Contacts.AvatarDialog : Dialog {
this.photobooth_page.show ();
this.flash = new Cheese.Flash (this);
-#else
- // Don't show the camera button
- this.webcam_button_box.hide ();
#endif
this.views_stack.set_visible_child_name ("thumbnail-page");
@@ -141,7 +125,7 @@ public class Contacts.AvatarDialog : Dialog {
});
*/
- update_thumbnail_grids ();
+ update_thumbnail_grid ();
}
private Gdk.Pixbuf scale_pixbuf_for_avatar_use (Gdk.Pixbuf pixbuf) {
@@ -189,25 +173,14 @@ public class Contacts.AvatarDialog : Dialog {
return null;
}
- private ContactFrame? frame_for_filename (string filename) {
- ContactFrame? image_frame = null;
- try {
- var pixbuf = new Gdk.Pixbuf.from_file (filename);
- return create_frame (pixbuf);
- } catch {
- }
- return image_frame;
- }
-
private void selected_pixbuf (Gdk.Pixbuf pixbuf) {
var p = pixbuf.scale_simple (MAIN_SIZE, MAIN_SIZE, Gdk.InterpType.HYPER);
this.current_avatar.set_pixbuf (p);
this.new_pixbuf = pixbuf;
- set_response_sensitive (ResponseType.OK, true);
}
- private void update_thumbnail_grids () {
+ private void update_thumbnail_grid () {
if (this.contact != null) {
foreach (var p in contact.individual.personas) {
ContactFrame? frame = frame_for_persona (p);
@@ -216,14 +189,6 @@ public class Contacts.AvatarDialog : Dialog {
}
}
this.personas_thumbnail_grid.show_all ();
-
- var stock_files = Utils.get_stock_avatars ();
- foreach (var file_name in stock_files) {
- ContactFrame? frame = frame_for_filename (file_name);
- if (frame != null)
- this.stock_thumbnail_grid.add (frame);
- }
- this.stock_thumbnail_grid.show_all ();
}
public void update_preview (FileChooser chooser) {
@@ -240,8 +205,9 @@ public class Contacts.AvatarDialog : Dialog {
if (file_info != null) {
var mime_type = file_info.get_content_type ();
- if (mime_type != null)
- pixbuf = thumbnail_factory.generate_thumbnail (uri, mime_type);
+ //XXX FIXME do this without gnome-desktop pls
+ /* if (mime_type != null) */
+ /* pixbuf = thumbnail_factory.generate_thumbnail (uri, mime_type); */
}
} catch (GLib.Error e) {
}
@@ -271,30 +237,30 @@ public class Contacts.AvatarDialog : Dialog {
this.views_stack.set_visible_child_name ("crop-page");
}
- public override void response (int response_id) {
- if (response_id == ResponseType.OK && this.new_pixbuf != null) {
- try {
- uint8[] buffer;
- if (this.new_pixbuf.save_to_buffer (out buffer, "png", null)) {
- var icon = new BytesIcon (new Bytes (buffer));
- set_avatar (icon);
- } else {
- /* Failure. Fall through. */
- }
- } catch {
- }
- }
-
-#if HAVE_CHEESE
- /* Ensure the Vala garbage collector disposes of the Cheese widget.
- * This prevents the 'Device or resource busy' warnings, see:
- * https://bugzilla.gnome.org/show_bug.cgi?id=700959
- */
- this.cheese = null;
-#endif
-
- this.destroy ();
- }
+ /* public override void response (int response_id) {*/
+ /* if (response_id == ResponseType.OK && this.new_pixbuf != null) {*/
+ /* try {*/
+ /* uint8[] buffer;*/
+ /* if (this.new_pixbuf.save_to_buffer (out buffer, "png", null)) {*/
+ /* var icon = new BytesIcon (new Bytes (buffer));*/
+ /* set_avatar (icon);*/
+ /* } else {*/
+ /* Failure. Fall through. */
+ /* }*/
+ /* } catch {*/
+ /* }*/
+ /* }*/
+
+/* #if HAVE_CHEESE*/
+ /* Ensure the Vala garbage collector disposes of the Cheese widget.
+ * This prevents the 'Device or resource busy' warnings, see:
+ * https://bugzilla.gnome.org/show_bug.cgi?id=700959
+ */
+ /* this.cheese = null;*/
+/* #endif*/
+
+ /* this.destroy ();*/
+ /* }*/
[GtkCallback]
private void select_avatar_file_cb (Button button) {
@@ -332,7 +298,7 @@ public class Contacts.AvatarDialog : Dialog {
else
selected_pixbuf (scale_pixbuf_for_avatar_use (pixbuf));
- update_thumbnail_grids ();
+ update_thumbnail_grid ();
} catch {
}
diff --git a/src/contacts-contact-editor.vala b/src/contacts-contact-editor.vala
index b94dba5..72626c7 100644
--- a/src/contacts-contact-editor.vala
+++ b/src/contacts-contact-editor.vala
@@ -978,23 +978,23 @@ public class Contacts.ContactEditor : Grid {
this.container_grid.attach (this.avatar_frame, 0, 0, 1, 3);
}
- // Show the avatar dialog when the avatar is clicked
+ // Show the avatar popover when the avatar is clicked
private void on_avatar_frame_clicked () {
- var dialog = new AvatarDialog ((Window) get_toplevel (), this.contact);
- dialog.set_avatar.connect ( (icon) => {
- this.avatar_frame.set_data ("value", icon);
- this.avatar_frame.set_data ("changed", true);
-
- Gdk.Pixbuf? a_pixbuf = null;
- try {
- var stream = (icon as LoadableIcon).load (PROFILE_SIZE, null);
- a_pixbuf = new Gdk.Pixbuf.from_stream_at_scale (stream, PROFILE_SIZE, PROFILE_SIZE, true);
- } catch {
- }
-
- this.avatar_frame.set_pixbuf (a_pixbuf);
- });
- dialog.run ();
+ var popover = new AvatarPopover (this.avatar_frame, this.contact);
+ /* dialog.set_avatar.connect ( (icon) => { */
+ /* this.avatar_frame.set_data ("value", icon); */
+ /* this.avatar_frame.set_data ("changed", true); */
+
+ /* Gdk.Pixbuf? a_pixbuf = null; */
+ /* try { */
+ /* var stream = (icon as LoadableIcon).load (PROFILE_SIZE, null); */
+ /* a_pixbuf = new Gdk.Pixbuf.from_stream_at_scale (stream, PROFILE_SIZE, PROFILE_SIZE, true); */
+ /* } catch { */
+ /* } */
+
+ /* this.avatar_frame.set_pixbuf (a_pixbuf); */
+ /* }); */
+ popover.show ();
}
public bool avatar_changed () {
diff --git a/src/contacts-contact-frame.vala b/src/contacts-contact-frame.vala
index b1ec072..c216d63 100644
--- a/src/contacts-contact-frame.vala
+++ b/src/contacts-contact-frame.vala
@@ -23,15 +23,17 @@ using Gee;
public class Contacts.ContactFrame : Frame {
private int size;
private Gdk.Pixbuf? pixbuf;
- private Pango.Layout? layout;
+ private Contact? contact;
public signal void clicked ();
public ContactFrame (int size, bool with_button = false) {
this.size = size;
+ this.contact = null;
- var image = new Image ();
+ var image = new DrawingArea ();
image.set_size_request (size, size);
+ //TODO Border (or not? what if we have a color)
if (with_button) {
var button = new Button ();
@@ -51,61 +53,115 @@ public class Contacts.ContactFrame : Frame {
}
image.show ();
- image.draw.connect (draw_image);
+ image.draw.connect (on_draw_avatar);
set_shadow_type (ShadowType.NONE);
}
- public void set_pixbuf (Gdk.Pixbuf a_pixbuf) {
- pixbuf = Contact.frame_icon (a_pixbuf);
+ public void set_pixbuf (Gdk.Pixbuf? a_pixbuf) {
+ this.pixbuf = (a_pixbuf != null)? Contact.frame_icon (a_pixbuf) : null;
queue_draw ();
}
public void set_image (AvatarDetails? details, Contact? contact = null) {
+ this.contact = contact;
+
Gdk.Pixbuf? a_pixbuf = null;
- if (details != null &&
- details.avatar != null) {
+ if (details != null && details.avatar != null) {
try {
- var stream = details.avatar.load (size, null);
- a_pixbuf = new Gdk.Pixbuf.from_stream_at_scale (stream, size, size, true);
+ var stream = details.avatar.load (size, null);
+ a_pixbuf = new Gdk.Pixbuf.from_stream_at_scale (stream, size, size, true);
}
catch {
}
}
if (a_pixbuf == null) {
- a_pixbuf = Contact.draw_fallback_avatar (size, contact);
+ a_pixbuf = null;
}
set_pixbuf (a_pixbuf);
}
- public bool draw_image (Cairo.Context cr) {
+ public bool on_draw_avatar (Cairo.Context cr) {
cr.save ();
- if (pixbuf != null) {
- Gdk.cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
- cr.paint();
- }
+ if (this.pixbuf != null)
+ draw_pixbuf (cr);
+ else // Draw the standard person fallback
+ draw_initial (cr);
- if (layout != null) {
- Utils.cairo_rounded_box (cr, 0, 0, size, size, 4);
- cr.clip ();
-
- cr.set_source_rgba (0, 0, 0, 0.5);
- cr.rectangle (0, size, size, 0);
- cr.fill ();
-
- cr.set_source_rgb (1.0, 1.0, 1.0);
- Pango.Rectangle rect;
- layout.get_extents (null, out rect);
- double label_width = rect.width/(double)Pango.SCALE;
- double label_height = rect.height / (double)Pango.SCALE;
- cr.move_to (Math.round ((size - label_width) / 2.0),
- size + Math.floor ((-label_height) / 2.0));
- Pango.cairo_show_layout (cr, layout);
- }
cr.restore ();
return true;
}
+
+ private void draw_pixbuf (Cairo.Context cr) {
+ Gdk.cairo_set_source_pixbuf (cr, this.pixbuf, 0, 0);
+ // Clip with a circle
+ cr.arc (this.size / 2, this.size / 2, (this.size - 1) / 2, 0, 2*Math.PI);
+ cr.clip_preserve ();
+ cr.paint ();
+
+ // Draw a border
+ cr.arc (this.size / 2, this.size / 2, (this.size - 1) / 2, 0, 2*Math.PI);
+ cr.set_line_width (0.5);
+ cr.set_source_rgb (0, 0, 0);
+ cr.stroke ();
+ }
+
+ private void draw_initial (Cairo.Context cr) {
+ // The background colors
+ double bg_r, bg_g, bg_b;
+ get_background_color (out bg_r, out bg_g, out bg_b);
+ // The foreground colors
+ var fg_r = bg_r * 0.5;
+ var fg_g = bg_g * 0.5;
+ var fg_b = bg_b * 0.5;
+
+ // Draw the background circle
+ cr.set_source_rgb (bg_r, bg_g, bg_b);
+ cr.arc (this.size / 2, this.size / 2, (this.size - 1) / 2, 0, 2*Math.PI);
+ cr.fill_preserve ();
+ // Draw the border
+ cr.set_line_width (0.5);
+ cr.set_source_rgb (fg_r, fg_g, fg_b);
+ cr.stroke ();
+
+ // Draw the initial
+ if (this.contact != null && this.contact.display_name != "") {
+ var initial = this.contact.display_name.get_char_validated ();
+ if (initial == -1)
+ return;
+ var initial_upper = initial.totitle ().to_string ();
+
+ // Get the styling right
+ cr.set_source_rgb (fg_r, fg_g, fg_b);
+ //XXX no better way to do this (ie without hardcoding Cantarell)
+ cr.select_font_face ("Cantarell", Cairo.FontSlant.NORMAL, Cairo.FontWeight.NORMAL);
+ cr.set_font_size (this.size * 0.66);
+ // Center it
+ Cairo.TextExtents extents;
+ cr.text_extents (initial_upper, out extents);
+ cr.move_to ((this.size - extents.width) / 2 - extents.x_bearing,
+ (this.size - extents.height) / 2 - extents.y_bearing);
+
+ cr.show_text (initial_upper);
+ }
+ }
+
+ private void get_background_color (out double r, out double g, out double b) {
+ //XXX find something if this.contact == nulll or id == ""
+
+ // We use the hash of the id so we get the same color for a contact
+ var hash = str_hash (this.contact.individual.id);
+
+ r = ((hash & 0xFF0000) >> 16) / 255.0;
+ g = ((hash & 0x00FF00) >> 8) / 255.0;
+ b = (hash & 0x0000FF) / 255.0;
+
+ // Make it a bit lighter by default (and since the foreground will be darker)
+ r = (r + 2) / 3.0;
+ g = (g + 2) / 3.0;
+ b = (b + 2) / 3.0;
+ }
}
diff --git a/src/contacts-utils.vala b/src/contacts-utils.vala
index 954e1f2..b828467 100644
--- a/src/contacts-utils.vala
+++ b/src/contacts-utils.vala
@@ -273,28 +273,6 @@ namespace Contacts.Utils {
entry.select_region (start, end);
}
- public string[] get_stock_avatars () {
- string[] files = {};
- var system_data_dirs = Environment.get_system_data_dirs ();
- foreach (var data_dir in system_data_dirs) {
- var path = Path.build_filename (data_dir, "pixmaps", "faces");
- Dir? dir = null;
- try {
- dir = Dir.open (path);
- } catch (Error e) {
- debug ("Couldn't open stock avatars folder \"%s\": %s", path, e.message);
- }
- if (dir != null) {
- string? face;
- while ((face = dir.read_name ()) != null) {
- var filename = Path.build_filename (path, face);
- files += filename;
- }
- }
- };
- return files;
- }
-
public PersonaStore[] get_eds_address_books (Store contacts_store) {
PersonaStore[] stores = {};
foreach (var backend in contacts_store.backend_store.enabled_backends.values) {
diff --git a/src/meson.build b/src/meson.build
index 2a387c3..f8067be 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -42,7 +42,6 @@ contacts_c_sources = [
contacts_c_args = [
'-include', 'config.h',
- '-DGNOME_DESKTOP_USE_UNSTABLE_API',
'-DLOCALEDIR="@0@"'.format(locale_dir),
]
@@ -52,7 +51,6 @@ contacts_deps = [
gee,
gio_unix,
glib,
- gnome_desktop,
goa,
gtk,
libebook,