summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNiels De Graef <nielsdegraef@gmail.com>2022-08-17 01:22:38 +0200
committerNiels De Graef <nielsdegraef@gmail.com>2022-08-17 01:25:56 +0200
commit3f2f996accb803ed14828f8c2a6834a2324569c5 (patch)
treefc1325becc2bdc8c69d7e992a46e213757fee9b6 /src
parent27478965cb0f3696de9761c27e57d61bc37ad50f (diff)
downloadgnome-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.vala75
-rw-r--r--src/contacts-contact-sheet.vala23
-rw-r--r--src/contacts-editor-property.vala19
-rw-r--r--src/contacts-utils.vala56
-rw-r--r--src/meson.build1
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',