summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels De Graef <nielsdegraef@gmail.com>2018-02-05 21:54:32 +0100
committerNiels De Graef <nielsdegraef@gmail.com>2018-02-05 21:58:37 +0100
commitb3ad2643092ba8679b18cf1e623541f4a574e56a (patch)
tree54683f28d44ae1e502f79c26c69d16a00bb0bbd6
parent83af90f9c0bc6f685d49d859c1ec717fc34894cc (diff)
downloadgnome-contacts-b3ad2643092ba8679b18cf1e623541f4a574e56a.tar.gz
Allow sorting by first name or surname.
Fixes #54.
-rw-r--r--data/ui/contacts-window.ui91
-rw-r--r--src/contacts-app.vala2
-rw-r--r--src/contacts-contact-list.vala22
-rw-r--r--src/contacts-list-pane.vala4
-rw-r--r--src/contacts-settings.vala14
-rw-r--r--src/contacts-window.vala17
-rw-r--r--src/org.gnome.Contacts.gschema.xml8
7 files changed, 143 insertions, 15 deletions
diff --git a/data/ui/contacts-window.ui b/data/ui/contacts-window.ui
index cef3289..e88721c 100644
--- a/data/ui/contacts-window.ui
+++ b/data/ui/contacts-window.ui
@@ -1,7 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.15.2 on Thu Aug 15 15:33:02 2013 -->
<interface>
- <!-- interface-requires gtk+ 3.10 -->
+ <!-- interface-requires gtk+ 3.22 -->
+ <object class="GtkPopover" id="hamburger_menu_popover">
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="row_spacing">6</property>
+ <property name="margin">18</property>
+ <property name="width_request">200</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">List contacts by:</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="sort_on_firstname_button">
+ <property name="visible">True</property>
+ <property name="group">sort_on_firstname_button</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">First name</property>
+ <property name="mnemonic_widget">sort_on_firstname_button</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="sort_on_surname_button">
+ <property name="visible">True</property>
+ <property name="group">sort_on_firstname_button</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="left_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Surname</property>
+ <property name="mnemonic_widget">sort_on_surname_button</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="left_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
<template class="ContactsWindow" parent="GtkApplicationWindow">
<property name="can_focus">False</property>
<property name="default_width">800</property>
@@ -51,6 +120,24 @@
</packing>
</child>
<child>
+ <object class="GtkMenuButton" id="hamburger_menu_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="popover">hamburger_menu_popover</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">open-menu-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkButton" id="select_cancel_button">
<property name="visible">False</property>
<property name="can_focus">True</property>
diff --git a/src/contacts-app.vala b/src/contacts-app.vala
index 3b0224b..b2a0e58 100644
--- a/src/contacts-app.vala
+++ b/src/contacts-app.vala
@@ -226,7 +226,7 @@ public class Contacts.App : Gtk.Application {
}
private void create_window () {
- this.window = new Contacts.Window (this, this.contacts_store);
+ this.window = new Contacts.Window (this.settings, this, this.contacts_store);
}
private void schedule_window_creation () {
diff --git a/src/contacts-contact-list.vala b/src/contacts-contact-list.vala
index fd51d06..2696002 100644
--- a/src/contacts-contact-list.vala
+++ b/src/contacts-contact-list.vala
@@ -102,9 +102,11 @@ public class Contacts.ContactList : ListBox {
private Store store;
+ private Settings settings;
+
public UiState state { get; set; }
- public ContactList (Store store, Query query) {
+ public ContactList (Settings settings, Store store, Query query) {
this.selection_mode = Gtk.SelectionMode.BROWSE;
this.store = store;
this.filter_query = query;
@@ -113,6 +115,9 @@ public class Contacts.ContactList : ListBox {
this.notify["state"].connect (on_ui_state_changed);
+ this.settings = settings;
+ this.settings.changed["sort-on-surname"].connect(invalidate_sort);
+
this.store.added.connect (contact_added_cb);
this.store.removed.connect (contact_removed_cb);
foreach (var c in this.store.get_contacts ())
@@ -146,8 +151,19 @@ public class Contacts.ContactList : ListBox {
if (a.is_favourite != b.is_favourite)
return a.is_favourite? -1 : 1;
- // Both are (non-)favourites: sort by name
- return a.display_name.collate (b.display_name);
+ // Both are (non-)favourites: sort by either first name or surname (user preference)
+ unowned string? a_name = this.settings.sort_on_surname? try_get_surname(a) : a.display_name;
+ unowned string? b_name = this.settings.sort_on_surname? try_get_surname(b) : b.display_name;
+
+ return a_name.collate (b_name);
+ }
+
+ private unowned string try_get_surname (Individual indiv) {
+ if (indiv.structured_name != null && indiv.structured_name.family_name != "")
+ return indiv.structured_name.family_name;
+
+ // Fall back to the display_name
+ return indiv.display_name;
}
private void update_header (ListBoxRow row, ListBoxRow? before) {
diff --git a/src/contacts-list-pane.vala b/src/contacts-list-pane.vala
index 2c60e15..9f4d3f1 100644
--- a/src/contacts-list-pane.vala
+++ b/src/contacts-list-pane.vala
@@ -48,7 +48,7 @@ public class Contacts.ListPane : Frame {
public signal void delete_contacts (LinkedList<Contact> contacts);
public signal void contacts_marked (int contacts_marked);
- public ListPane (Store contacts_store) {
+ public ListPane (Settings settings, Store contacts_store) {
this.store = contacts_store;
this.notify["state"].connect (on_ui_state_changed);
@@ -60,7 +60,7 @@ public class Contacts.ListPane : Frame {
// Load the ContactsView and connect the necessary signals
- this.contacts_list = new ContactList (contacts_store, this.filter_query);
+ this.contacts_list = new ContactList (settings, contacts_store, this.filter_query);
bind_property ("state", this.contacts_list, "state", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE);
this.contacts_list_container.add (this.contacts_list);
diff --git a/src/contacts-settings.vala b/src/contacts-settings.vala
index bfb11b8..1327f2d 100644
--- a/src/contacts-settings.vala
+++ b/src/contacts-settings.vala
@@ -18,15 +18,19 @@
/**
* Provides a convenient interface to deal with the settings.
*/
-public class Contacts.Settings {
- private GLib.Settings settings;
+public class Contacts.Settings : GLib.Settings {
public bool did_initial_setup {
- get { return settings.get_boolean ("did-initial-setup"); }
- set { settings.set_boolean ("did-initial-setup", value); }
+ get { return get_boolean ("did-initial-setup"); }
+ set { set_boolean ("did-initial-setup", value); }
+ }
+
+ public bool sort_on_surname {
+ get { return get_boolean ("sort-on-surname"); }
+ set { set_boolean ("sort-on-surname", value); }
}
public Settings (App app) {
- this.settings = new GLib.Settings (app.application_id);
+ Object (schema_id: app.application_id);
}
}
diff --git a/src/contacts-window.vala b/src/contacts-window.vala
index 1b25885..a43a268 100644
--- a/src/contacts-window.vala
+++ b/src/contacts-window.vala
@@ -40,6 +40,10 @@ public class Contacts.Window : Gtk.ApplicationWindow {
[GtkChild]
private Button select_cancel_button;
[GtkChild]
+ private MenuButton hamburger_menu_button;
+ [GtkChild]
+ private RadioButton sort_on_surname_button;
+ [GtkChild]
private ToggleButton favorite_button;
private bool ignore_favorite_button_toggled;
[GtkChild]
@@ -55,17 +59,25 @@ public class Contacts.Window : Gtk.ApplicationWindow {
public UiState state { get; set; default = UiState.NORMAL; }
+ private Settings settings;
+
public Store store {
get; construct set;
}
- public Window (App app, Store contacts_store) {
+ public Window (Settings settings, App app, Store contacts_store) {
Object (
application: app,
show_menubar: false,
store: contacts_store
);
+ this.settings = settings;
+ this.sort_on_surname_button.active = this.settings.sort_on_surname;
+ this.sort_on_surname_button.toggled.connect (() => {
+ this.settings.sort_on_surname = this.sort_on_surname_button.active;
+ });
+
this.notify["state"].connect (on_ui_state_changed);
create_contact_pane ();
@@ -90,7 +102,7 @@ public class Contacts.Window : Gtk.ApplicationWindow {
if (list_pane != null)
return;
- list_pane = new ListPane (store);
+ list_pane = new ListPane (this.settings, store);
bind_property ("state", this.list_pane, "state", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE);
list_pane.selection_changed.connect (list_pane_selection_changed_cb);
list_pane.link_contacts.connect (list_pane_link_contacts_cb);
@@ -117,6 +129,7 @@ public class Contacts.Window : Gtk.ApplicationWindow {
private void on_ui_state_changed (Object obj, ParamSpec pspec) {
// UI when we're not editing of selecting stuff
this.add_button.visible
+ = this.hamburger_menu_button.visible
= this.right_header.show_close_button
= (this.state == UiState.NORMAL || this.state == UiState.SHOWING);
diff --git a/src/org.gnome.Contacts.gschema.xml b/src/org.gnome.Contacts.gschema.xml
index 568e6ce..98d2f4e 100644
--- a/src/org.gnome.Contacts.gschema.xml
+++ b/src/org.gnome.Contacts.gschema.xml
@@ -5,5 +5,13 @@
<summary>First-time setup done.</summary>
<description>Set to true after the user has run the first-time setup wizard.</description>
</key>
+ <key name="sort-on-surname" type="b">
+ <default>false</default>
+ <summary>Sort contacts on surname.</summary>
+ <description>
+ If this is set to true, the list of contacts will be sorted on their surnames.
+ Otherwise, it will be sorted on the first names of the contacts.
+ </description>
+ </key>
</schema>
</schemalist>