Commit 7479e32c authored by Julian Sparber's avatar Julian Sparber
Browse files

debian: add patches for avatar-selector

parent 4613aa3a
Pipeline #62393 passed with stages
in 10 minutes and 48 seconds
From 879dfc435e763049252eb3c2eb0311bba5622e15 Mon Sep 17 00:00:00 2001
From: Julian Sparber <julian@sparber.net>
Date: Thu, 17 Dec 2020 13:37:00 +0100
Subject: [PATCH] avatar-selector: move selector to a dialog
The previously used popover was to big and causes issues on
small screens and on X11.
This also merges the two FlowBoxes into one.
---
data/ui/contacts-avatar-selector.ui | 120 ++++++++++------
data/ui/style.css | 5 +
src/contacts-avatar-selector.vala | 209 +++++++++++++++-------------
src/contacts-contact-editor.vala | 2 +-
4 files changed, 200 insertions(+), 136 deletions(-)
diff --git a/data/ui/contacts-avatar-selector.ui b/data/ui/contacts-avatar-selector.ui
index 895805a9..336b6baf 100644
--- a/data/ui/contacts-avatar-selector.ui
+++ b/data/ui/contacts-avatar-selector.ui
@@ -1,54 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.22"/>
- <template class="ContactsAvatarSelector" parent="GtkPopover">
+ <template class="ContactsAvatarSelector" parent="GtkWindow">
<property name="can_focus">False</property>
- <child>
- <object class="GtkBox">
+ <property name="modal">True</property>
+ <property name="default_width">400</property>
+ <property name="default_height">400</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="skip_taskbar_hint">True</property>
+ <signal name="delete-event" handler="on_delete_event" swapped="no"/>
+ <child type="titlebar">
+ <object class="GtkHeaderBar">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin_left">10</property>
- <property name="margin_right">10</property>
- <property name="margin_top">10</property>
- <property name="margin_bottom">10</property>
- <property name="orientation">vertical</property>
- <property name="spacing">10</property>
+ <property name="can_focus">False</property>
<child>
- <object class="GtkFlowBox" id="personas_thumbnail_grid">
+ <object class="GtkButton">
+ <property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="column_spacing">5</property>
- <property name="row_spacing">5</property>
- <property name="selection_mode">none</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="on_cancel_clicked" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="label" translatable="yes">Done</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="on_done_clicked" swapped="no"/>
+ <style>
+ <class name="suggested-action"/>
+ </style>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
+ <property name="pack_type">end</property>
</packing>
</child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkFlowBox" id="stock_thumbnail_grid">
+ <object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="column_spacing">5</property>
- <property name="row_spacing">5</property>
- <property name="min_children_per_line">5</property>
- <property name="max_children_per_line">8</property>
- <property name="selection_mode">none</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">10</property>
+ <property name="margin_right">10</property>
+ <property name="margin_top">10</property>
+ <property name="margin_bottom">10</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkFlowBox" id="thumbnail_grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="column_spacing">5</property>
+ <property name="row_spacing">5</property>
+ <property name="max_children_per_line">8</property>
+ <property name="selection_mode">single</property>
+ <property name="homogeneous">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
</object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible">True</property>
+ </object>>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="halign">center</property>
+ <property name="margin_left">10</property>
+ <property name="margin_right">10</property>
+ <property name="margin_top">10</property>
+ <property name="margin_bottom">10</property>
<property name="spacing">10</property>
+ <property name="halign">center</property>
<child>
<object class="GtkButton" id="cheese_button">
<property name="label" translatable="yes">Take a Picture…</property>
@@ -57,11 +105,6 @@
<property name="receives_default">True</property>
<signal name="clicked" handler="on_cheese_clicked" swapped="no"/>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
</child>
<child>
<object class="GtkButton">
@@ -71,17 +114,10 @@
<property name="receives_default">True</property>
<signal name="clicked" handler="on_file_clicked" swapped="no"/>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
</child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
+ <property name="pack_type">end</property>
</packing>
</child>
</object>
diff --git a/data/ui/style.css b/data/ui/style.css
index de2f0f6d..67bd2ad3 100644
--- a/data/ui/style.css
+++ b/data/ui/style.css
@@ -42,6 +42,11 @@
.contacts-avatar-popover .contact-display-name {
font-size: 20px;
}
+flowboxchild.circular {
+ padding: 4px;
+ border-radius: 9999px;
+ -gtk-outline-radius: 9999px;
+}
.avatar-button {
border-radius: 50%;
diff --git a/src/contacts-avatar-selector.vala b/src/contacts-avatar-selector.vala
index fb83e377..fdfdb62a 100644
--- a/src/contacts-avatar-selector.vala
+++ b/src/contacts-avatar-selector.vala
@@ -17,6 +17,44 @@
using Folks;
+const int MAIN_SIZE = 128;
+const int ICONS_SIZE = 64;
+
+private class Contacts.Thumbnail : Gtk.FlowBoxChild {
+ public Gdk.Pixbuf? source_pixbuf { get; construct set; }
+ private Thumbnail (Gdk.Pixbuf? source_pixbuf = null) {
+ Object (visible: true, halign : Gtk.Align.CENTER, source_pixbuf: source_pixbuf);
+ this.get_style_context ().add_class ("circular");
+ var avatar = new Avatar (ICONS_SIZE);
+ avatar.set_pixbuf (source_pixbuf);
+ add (avatar);
+ }
+
+ public Thumbnail.for_persona (Persona persona) {
+ Gdk.Pixbuf? pixbuf = null;
+ var details = persona as AvatarDetails;
+ if (details != null && details.avatar != null) {
+ try {
+ var stream = details.avatar.load (MAIN_SIZE, null);
+ pixbuf = new Gdk.Pixbuf.from_stream (stream);
+ } catch (Error e) {
+ debug ("Couldn't create frame for persona '%s': %s", persona.display_id, e.message);
+ }
+ }
+ this (pixbuf);
+ }
+
+ public Thumbnail.for_filename (string filename) {
+ Gdk.Pixbuf? pixbuf = null;
+ try {
+ pixbuf = new Gdk.Pixbuf.from_file (filename);
+ } catch (Error e) {
+ debug ("Couldn't create frame for file '%s': %s", filename, e.message);
+ }
+ this (pixbuf);
+ }
+}
+
/**
* The AvatarSelector can be used to choose the avatar for a contact.
* This can be done by either choosing a stock thumbnail, an image file
@@ -25,9 +63,7 @@ using Folks;
* After a user has initially chosen an avatar, we provide a cropping tool.
*/
[GtkTemplate (ui = "/org/gnome/Contacts/ui/contacts-avatar-selector.ui")]
-public class Contacts.AvatarSelector : Gtk.Popover {
- const int ICONS_SIZE = 64;
- const int MAIN_SIZE = 128;
+public class Contacts.AvatarSelector : Gtk.Window {
const string AVATAR_BUTTON_CSS_NAME = "avatar-button";
// This will provide the default thumbnails
@@ -35,9 +71,7 @@ public class Contacts.AvatarSelector : Gtk.Popover {
private Individual individual;
[GtkChild]
- private Gtk.FlowBox personas_thumbnail_grid;
- [GtkChild]
- private Gtk.FlowBox stock_thumbnail_grid;
+ private Gtk.FlowBox thumbnail_grid;
#if HAVE_CHEESE
[GtkChild]
@@ -46,12 +80,19 @@ public class Contacts.AvatarSelector : Gtk.Popover {
private Cheese.CameraDeviceMonitor camera_monitor;
#endif
- public AvatarSelector (Gtk.Widget relative, Individual? individual) {
- this.set_relative_to(relative);
+ public AvatarSelector (Individual? individual, Gtk.Window? window = null) {
+ Object (transient_for: window);
this.thumbnail_factory = new Gnome.DesktopThumbnailFactory (Gnome.ThumbnailSize.NORMAL);
this.individual = individual;
- update_thumbnail_grids ();
+ unowned Gtk.BindingSet binding_set = Gtk.BindingSet.by_class (get_class ());
+ Gtk.BindingEntry.add_signal (binding_set,
+ Gdk.Key.Escape,
+ 0,
+ "close",
+ 0);
+
+ update_thumbnail_grid ();
#if HAVE_CHEESE
this.cheese_button.visible = true;
@@ -75,6 +116,16 @@ public class Contacts.AvatarSelector : Gtk.Popover {
#endif
}
+ [Signal (action = true)]
+ public new virtual signal void close () {
+ base.close ();
+ }
+
+ [GtkCallback]
+ public bool on_delete_event () {
+ return hide_on_delete ();
+ }
+
private Gdk.Pixbuf scale_pixbuf_for_avatar_use (Gdk.Pixbuf pixbuf) {
int w = pixbuf.get_width ();
int h = pixbuf.get_height ();
@@ -114,85 +165,57 @@ public class Contacts.AvatarSelector : Gtk.Popover {
this.get_toplevel() as Gtk.Window);
}
}
-
- private Gtk.FlowBoxChild create_thumbnail (Gdk.Pixbuf source_pixbuf) {
- var avatar = new Avatar (ICONS_SIZE);
- avatar.set_pixbuf (source_pixbuf);
-
- var button = new Gtk.Button ();
- button.get_style_context ().add_class (AVATAR_BUTTON_CSS_NAME);
- button.image = avatar;
- button.clicked.connect ( () => {
- selected_pixbuf (scale_pixbuf_for_avatar_use (source_pixbuf));
- this.popdown ();
- });
- var child = new Gtk.FlowBoxChild ();
- child.add (button);
- child.set_halign (Gtk.Align.START);
-
- return child;
- }
-
- private Gtk.FlowBoxChild? thumbnail_for_persona (Persona persona) {
- var details = persona as AvatarDetails;
- if (details == null || details.avatar == null)
- return null;
-
- try {
- var stream = details.avatar.load (MAIN_SIZE, null);
- return create_thumbnail (new Gdk.Pixbuf.from_stream (stream));
- } catch (Error e) {
- debug ("Couldn't create frame for persona '%s': %s", persona.display_id, e.message);
- }
-
- return null;
- }
-
- private Gtk.FlowBoxChild? thumbnail_for_filename (string filename) {
- try {
- return create_thumbnail (new Gdk.Pixbuf.from_file (filename));
- } catch (Error e) {
- debug ("Couldn't create frame for file '%s': %s", filename, e.message);
- }
-
- return null;
- }
-
- private void update_thumbnail_grids () {
+ private void update_thumbnail_grid () {
if (this.individual != null) {
foreach (var p in individual.personas) {
- var button = thumbnail_for_persona (p);
- if (button != null)
- this.personas_thumbnail_grid.add (button);
+ var widget = new Thumbnail.for_persona (p);
+ if (widget.source_pixbuf != null)
+ this.thumbnail_grid.add (widget);
}
}
- this.personas_thumbnail_grid.show_all ();
var stock_files = Utils.get_stock_avatars ();
foreach (var file_name in stock_files) {
- var button = thumbnail_for_filename (file_name);
- if (button != null)
- this.stock_thumbnail_grid.add (button);
+ var widget = new Thumbnail.for_filename (file_name);
+ if (widget.source_pixbuf != null)
+ this.thumbnail_grid.add (widget);
}
- this.stock_thumbnail_grid.show_all ();
+ this.thumbnail_grid.show_all ();
}
[GtkCallback]
private void on_cheese_clicked (Gtk.Button button) {
- var dialog = new CropCheeseDialog.for_cheese ((Window) this.get_toplevel());
+ var dialog = new CropCheeseDialog.for_cheese (this.transient_for);
dialog.show_all ();
dialog.picture_selected.connect ( (pix) => {
selected_pixbuf (scale_pixbuf_for_avatar_use (pix));
+ this.close ();
});
- this.popdown ();
+ }
+
+ [GtkCallback]
+ private void on_cancel_clicked (Gtk.Button button) {
+ this.close ();
+ }
+
+ [GtkCallback]
+ private void on_done_clicked (Gtk.Button button) {
+ var selected_children = thumbnail_grid.get_selected_children ();
+ if (selected_children != null) {
+ var thumbnail = (selected_children.data as Thumbnail);
+ if (thumbnail != null)
+ selected_pixbuf (scale_pixbuf_for_avatar_use (thumbnail.source_pixbuf));
+ }
+
+ this.close ();
}
[GtkCallback]
private void on_file_clicked (Gtk.Button button) {
var chooser = new Gtk.FileChooserNative (_("Browse for more pictures"),
- (Gtk.Window) this.get_toplevel (),
- Gtk.FileChooserAction.OPEN,
- _("_Open"), _("_Cancel"));
+ (Gtk.Window) this.get_toplevel (),
+ Gtk.FileChooserAction.OPEN,
+ _("_Open"), _("_Cancel"));
chooser.set_modal (true);
chooser.set_local_only (false);
var preview = new Gtk.Image ();
@@ -208,36 +231,36 @@ public class Contacts.AvatarSelector : Gtk.Popover {
chooser.set_current_folder (folder);
chooser.response.connect ( (response) => {
- if (response != Gtk.ResponseType.ACCEPT) {
- chooser.destroy ();
- return;
- }
- try {
- var file = File.new_for_uri (chooser.get_uri ());
- var in_stream = file.read ();
- var pixbuf = new Gdk.Pixbuf.from_stream (in_stream, null);
- in_stream.close ();
- if (pixbuf.get_width () > MAIN_SIZE || pixbuf.get_height () > MAIN_SIZE) {
- var dialog = new CropCheeseDialog.for_crop ((Window) this.get_toplevel(),
- pixbuf);
- dialog.picture_selected.connect ( (pix) => {
- selected_pixbuf (scale_pixbuf_for_avatar_use (pix));
- });
- dialog.show_all();
- } else {
- selected_pixbuf (scale_pixbuf_for_avatar_use (pixbuf));
- }
- } catch (GLib.Error e) {
- warning ("Failed to set avatar: %s", e.message);
- Utils.show_error_dialog (_("Failed to set avatar."),
- this.get_toplevel() as Gtk.Window);
+ if (response != Gtk.ResponseType.ACCEPT) {
+ chooser.destroy ();
+ return;
+ }
+ try {
+ var file = File.new_for_uri (chooser.get_uri ());
+ var in_stream = file.read ();
+ var pixbuf = new Gdk.Pixbuf.from_stream (in_stream, null);
+ in_stream.close ();
+ if (pixbuf.get_width () > MAIN_SIZE || pixbuf.get_height () > MAIN_SIZE) {
+ var dialog = new CropCheeseDialog.for_crop (this.transient_for, pixbuf);
+ dialog.picture_selected.connect ( (pix) => {
+ selected_pixbuf (scale_pixbuf_for_avatar_use (pix));
+ this.close ();
+ });
+ dialog.show_all();
+ } else {
+ selected_pixbuf (scale_pixbuf_for_avatar_use (pixbuf));
}
+ } catch (GLib.Error e) {
+ warning ("Failed to set avatar: %s", e.message);
+ Utils.show_error_dialog (_("Failed to set avatar."),
+ this.get_toplevel() as Gtk.Window);
+ }
- chooser.destroy ();
- });
+ chooser.destroy ();
+ });
chooser.run ();
- this.popdown();
+ this.close ();
}
private void update_preview (Gtk.FileChooser chooser) {
diff --git a/src/contacts-contact-editor.vala b/src/contacts-contact-editor.vala
index 09753c94..df08bab2 100644
--- a/src/contacts-contact-editor.vala
+++ b/src/contacts-contact-editor.vala
@@ -57,7 +57,7 @@ public class Contacts.ContactEditor : Gtk.Box {
// Show the avatar popover when the avatar is clicked
private void on_avatar_button_clicked (Gtk.Button avatar_button) {
if (this.avatar_selector == null)
- this.avatar_selector = new AvatarSelector (avatar_button, this.individual);
+ this.avatar_selector = new AvatarSelector (this.individual, (Window) this.get_toplevel());
this.avatar_selector.show();
}
--
2.29.2
......@@ -34,3 +34,6 @@ downgrade_deps.patch
# WIP RFC: ContactSheet: Add make call and send sms button
# https://gitlab.gnome.org/GNOME/gnome-contacts/-/merge_requests/140
0001-ContactSheet-Add-make-call-and-send-sms-button.patch
# avatar-selector: move selector to a dialog
# https://gitlab.gnome.org/GNOME/gnome-contacts/-/merge_requests/141/commits
0001-avatar-selector-move-selector-to-a-dialog.patch
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment