diff options
author | Niels De Graef <nielsdegraef@gmail.com> | 2022-08-17 01:22:38 +0200 |
---|---|---|
committer | Niels De Graef <nielsdegraef@gmail.com> | 2022-08-17 01:25:56 +0200 |
commit | 3f2f996accb803ed14828f8c2a6834a2324569c5 (patch) | |
tree | fc1325becc2bdc8c69d7e992a46e213757fee9b6 /src | |
parent | 27478965cb0f3696de9761c27e57d61bc37ad50f (diff) | |
download | gnome-contacts-3f2f996accb803ed14828f8c2a6834a2324569c5.tar.gz |
Create a custom sorter for AbstractFieldDetails
This allows us to split off the logic for filtering and sorting personas
from the generic `Utils` namespace, and allows us to expand on our
GListModel usage, which allows for some bigger cleanups planned ahead.
Diffstat (limited to 'src')
-rw-r--r-- | src/contacts-abstract-field-details-sorter.vala | 75 | ||||
-rw-r--r-- | src/contacts-contact-sheet.vala | 23 | ||||
-rw-r--r-- | src/contacts-editor-property.vala | 19 | ||||
-rw-r--r-- | src/contacts-utils.vala | 56 | ||||
-rw-r--r-- | src/meson.build | 1 |
5 files changed, 109 insertions, 65 deletions
diff --git a/src/contacts-abstract-field-details-sorter.vala b/src/contacts-abstract-field-details-sorter.vala new file mode 100644 index 0000000..430cac5 --- /dev/null +++ b/src/contacts-abstract-field-details-sorter.vala @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2022 Niels De Graef <nielsdegraef@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +using Folks; + +/** + * A custom sorter that provides a consistent way of sorting + * {@link Folks.AbstractFieldDetails} within the whole application. + */ +public class Contacts.AbstractFieldDetailsSorter : Gtk.Sorter { + + public override Gtk.SorterOrder get_order () { + return Gtk.SorterOrder.PARTIAL; + } + + public override Gtk.Ordering compare (Object? item1, Object? item2) { + unowned var a = (AbstractFieldDetails) item1; + unowned var b = (AbstractFieldDetails) item2; + + // Fields with a PREF hint always go first (see VCard PREF attribute) + var a_has_pref = has_pref (a); + if (a_has_pref != has_pref (b)) + return (a_has_pref)? Gtk.Ordering.SMALLER : Gtk.Ordering.LARGER; + + // sort by field type first (e.g. "Home", "Work") + unowned var type_set = select_typeset_from_fielddetails (a); + var result = type_set.format_type (a).ascii_casecmp (type_set.format_type (b)); + if (result != 0) + return Gtk.Ordering.from_cmpfunc (result); + + // Try to compare by value if types are equal + unowned var aa = a as AbstractFieldDetails<string>; + unowned var bb = b as AbstractFieldDetails<string>; + if (aa != null && bb != null) + return Gtk.Ordering.from_cmpfunc (strcmp (aa.value, bb.value)); + + // No heuristics to fall back to. + warning ("Unsupported AbstractFieldDetails value type"); + return Gtk.Ordering.EQUAL; + } + + private bool has_pref (AbstractFieldDetails details) { + var evolution_pref = details.get_parameter_values ("x-evolution-ui-slot"); + if (evolution_pref != null && Utils.get_first (evolution_pref) == "1") + return true; + + foreach (var param in details.parameters["type"]) { + if (param.ascii_casecmp ("PREF") == 0) + return true; + } + return false; + } + + private unowned TypeSet select_typeset_from_fielddetails (AbstractFieldDetails a) { + if (a is EmailFieldDetails) + return TypeSet.email; + if (a is PhoneFieldDetails) + return TypeSet.phone; + return TypeSet.general; + } +} diff --git a/src/contacts-contact-sheet.vala b/src/contacts-contact-sheet.vala index 1b0eecf..81b3293 100644 --- a/src/contacts-contact-sheet.vala +++ b/src/contacts-contact-sheet.vala @@ -223,9 +223,11 @@ public class Contacts.ContactSheet : Gtk.Grid { if (details == null) return; - var roles = Utils.sort_fields<RoleFieldDetails>(details.roles); + var roles = Utils.fields_to_sorted (details.roles); var rows = new GLib.List<Gtk.ListBoxRow> (); - foreach (var role in roles) { + for (uint i = 0; i < roles.get_n_items (); i++) { + var role = (RoleFieldDetails) roles.get_item (i); + if (role.value.is_empty ()) continue; @@ -254,9 +256,11 @@ public class Contacts.ContactSheet : Gtk.Grid { if (details == null) return; - var emails = Utils.sort_fields<EmailFieldDetails>(details.email_addresses); + var emails = Utils.fields_to_sorted (details.email_addresses); var rows = new GLib.List<Gtk.ListBoxRow> (); - foreach (var email in emails) { + for (uint i = 0; i < emails.get_n_items (); i++) { + var email = (EmailFieldDetails) emails.get_item (i); + if (email.value == "") continue; @@ -281,9 +285,11 @@ public class Contacts.ContactSheet : Gtk.Grid { if (phone_details == null) return; - var phones = Utils.sort_fields<PhoneFieldDetails>(phone_details.phone_numbers); + var phones = Utils.fields_to_sorted (phone_details.phone_numbers); var rows = new GLib.List<Gtk.ListBoxRow> (); - foreach (var phone in phones) { + for (uint i = 0; i < phones.get_n_items (); i++) { + var phone = (PhoneFieldDetails) phones.get_item (i); + if (phone.value == "") continue; @@ -336,7 +342,10 @@ public class Contacts.ContactSheet : Gtk.Grid { return; var rows = new GLib.List<Gtk.ListBoxRow> (); - foreach (var url in url_details.urls) { + var urls = Utils.fields_to_sorted (url_details.urls); + for (uint i = 0; i < urls.get_n_items (); i++) { + var url = (UrlFieldDetails) urls.get_item (i); + if (url.value == "") continue; diff --git a/src/contacts-editor-property.vala b/src/contacts-editor-property.vala index fe6aed6..85c40e2 100644 --- a/src/contacts-editor-property.vala +++ b/src/contacts-editor-property.vala @@ -440,9 +440,10 @@ public class Contacts.EditorProperty : Object, ListModel { case "email-addresses": unowned var details = p as EmailDetails; if (details != null) { - var emails = Utils.sort_fields<EmailFieldDetails>(details.email_addresses); + var emails = Utils.fields_to_sorted (details.email_addresses); if (!only_new) - foreach (var email in emails) { + for (uint i = 0; i < emails.get_n_items (); i++) { + var email = (EmailFieldDetails) emails.get_item (i); this.rows.add (create_for_email (details.email_addresses, email)); } if (this.writeable) @@ -452,9 +453,10 @@ public class Contacts.EditorProperty : Object, ListModel { case "phone-numbers": unowned var details = p as PhoneDetails; if (details != null) { - var phones = Utils.sort_fields<PhoneFieldDetails>(details.phone_numbers); + var phones = Utils.fields_to_sorted (details.phone_numbers); if (!only_new) - foreach (var phone in phones) { + for (uint i = 0; i < phones.get_n_items (); i++) { + var phone = (PhoneFieldDetails) phones.get_item (i); this.rows.add (create_for_phone (details.phone_numbers, phone)); } if (this.writeable) @@ -464,9 +466,10 @@ public class Contacts.EditorProperty : Object, ListModel { case "urls": unowned var details = p as UrlDetails; if (details != null) { - var urls = Utils.sort_fields<UrlFieldDetails>(details.urls); + var urls = Utils.fields_to_sorted (details.urls); if (!only_new) - foreach (var url in urls) { + for (uint i = 0; i < urls.get_n_items (); i++) { + var url = (UrlFieldDetails) urls.get_item (i); this.rows.add (create_for_url (details.urls, url)); } this.rows.add (create_for_url (details.urls)); @@ -510,7 +513,9 @@ public class Contacts.EditorProperty : Object, ListModel { unowned var role_details = p as RoleDetails; if (role_details != null) { if (!only_new) { - foreach (var role in role_details.roles) { + var roles = Utils.fields_to_sorted (role_details.roles); + for (uint i = 0; i < roles.get_n_items (); i++) { + var role = (RoleFieldDetails) roles.get_item (i); this.rows.add (create_for_role (role_details.roles, role)); } } diff --git a/src/contacts-utils.vala b/src/contacts-utils.vala index f0d2d43..4bfd810 100644 --- a/src/contacts-utils.vala +++ b/src/contacts-utils.vala @@ -134,57 +134,11 @@ namespace Contacts.Utils { return !has_main_persona (self) || !has_mainable_persona (other); } - private bool has_pref (AbstractFieldDetails details) { - var evolution_pref = details.get_parameter_values ("x-evolution-ui-slot"); - if (evolution_pref != null && Utils.get_first (evolution_pref) == "1") - return true; - - foreach (var param in details.parameters["type"]) { - if (param.ascii_casecmp ("PREF") == 0) - return true; - } - return false; - } - - private TypeSet select_typeset_from_fielddetails (AbstractFieldDetails a) { - if (a is EmailFieldDetails) - return TypeSet.email; - if (a is PhoneFieldDetails) - return TypeSet.phone; - return TypeSet.general; - } - - public int compare_fields (void* _a, void* _b) { - var a = (AbstractFieldDetails) _a; - var b = (AbstractFieldDetails) _b; - - // Fields with a PREF hint always go first (see VCard PREF attribute) - var a_has_pref = has_pref (a); - if (a_has_pref != has_pref (b)) - return (a_has_pref)? -1 : 1; - - // sort by field type first (e.g. "Home", "Work") - var type_set = select_typeset_from_fielddetails (a); - var result = type_set.format_type (a).ascii_casecmp (type_set.format_type (b)); - if (result != 0) - return result; - - // Try to compare by value if types are equal - var aa = a as AbstractFieldDetails<string>; - var bb = b as AbstractFieldDetails<string>; - if (aa != null && bb != null) - return strcmp (aa.value, bb.value); - - // No heuristics to fall back to. - warning ("Unsupported AbstractFieldDetails value type"); - return 0; - } - - public Gee.List<T> sort_fields<T> (Gee.Collection<T> fields) { - var res = new Gee.ArrayList<T>(); - res.add_all (fields); - res.sort (Contacts.Utils.compare_fields); - return res; + public ListModel fields_to_sorted (Gee.Collection<AbstractFieldDetails> fields) { + var res = new ListStore (typeof (AbstractFieldDetails)); + foreach (var afd in fields) + res.append (afd); + return new Gtk.SortListModel ((owned) res, new AbstractFieldDetailsSorter ()); } public string[] format_address (PostalAddress addr) { diff --git a/src/meson.build b/src/meson.build index 96d455f..b439d60 100644 --- a/src/meson.build +++ b/src/meson.build @@ -8,6 +8,7 @@ install_data('org.gnome.Contacts.gschema.xml', # Common library libcontacts_sources = files( + 'contacts-abstract-field-details-sorter.vala', 'contacts-delete-operation.vala', 'contacts-esd-setup.vala', 'contacts-fake-persona-store.vala', |