[gnome-contacts/nielsdg/core-should-stay-core: 5/11] Make sure `BinChunkChild`ren are sorted




commit 4ec2456f9fbc43ff8403e244a22d40a0aa514af5
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Wed Sep 7 10:14:23 2022 +0200

    Make sure `BinChunkChild`ren are sorted
    
    Certain child properties should be sorted differently from others,
    namely the ones tagged as the "preferred" value (like the vCard PREF
    attribute) and any empty ones (which we would like to keep at the
    bottom).
    
    This means we can also remove the `AbstractFieldSorter` class, as that
    stopped being used when we ported everything to use the `Chunk` class
    (but we did forget to port its logic, which is now done with this
    commit)

 src/contacts-abstract-field-details-sorter.vala | 75 -------------------------
 src/core/contacts-bin-chunk.vala                | 51 ++++++++++++++++-
 src/meson.build                                 |  1 -
 3 files changed, 48 insertions(+), 79 deletions(-)
---
diff --git a/src/core/contacts-bin-chunk.vala b/src/core/contacts-bin-chunk.vala
index 3229ddda..24b2f044 100644
--- a/src/core/contacts-bin-chunk.vala
+++ b/src/core/contacts-bin-chunk.vala
@@ -45,7 +45,9 @@ public abstract class Contacts.BinChunk : Chunk, GLib.ListModel {
 
   /**
    * Should be called by subclasses when they add a child.
-   * It will make sure to attach the emptines check is appropriately applied.
+   *
+   * It will make sure to add the child in the appropriate position and that
+   * the emptines check is appropriately applied.
    */
   protected void add_child (BinChunkChild child) {
     if (child.is_empty && has_empty_child ())
@@ -55,8 +57,16 @@ public abstract class Contacts.BinChunk : Chunk, GLib.ListModel {
       debug ("Child 'is-empty' changed, doing emptiness check");
       emptiness_check ();
     });
-    this.elements.add (child);
-    items_changed (this.elements.length - 1, 0, 1);
+
+    // Add in a sorted manner
+    int i = 0;
+    while (i < this.elements.length) {
+      if (child.compare (this.elements[i]) < 0)
+        break;
+      i++;
+    }
+    this.elements.insert (i, child);
+    items_changed (i, 0, 1);
   }
 
   /**
@@ -168,4 +178,39 @@ public abstract class Contacts.BinChunkChild : GLib.Object {
     if (notify_empty)
       notify_property ("is-empty");
   }
+
+  /**
+   * Compares 2 children in an intuitive manner, so that preferred children go
+   * first and empty children are last
+   */
+  public int compare (BinChunkChild other) {
+    // Fields with a PREF hint always go first (see vCard PREF attribute)
+    var has_pref = has_pref_marker ();
+    if (has_pref != other.has_pref_marker ())
+      return has_pref? -1 : 1;
+
+    // Empty fields go last
+    var empty = this.is_empty;
+    if (empty != other.is_empty)
+      return empty? 1 : -1;
+
+    // FIXME: maybe also compare the types? (e.g. put HOME before WORK)
+    return 0;
+  }
+
+  /**
+   * Returns whether this child is marked as the "preferred" child, similar to
+   * the vCard PREF attribute
+   */
+  public bool has_pref_marker () {
+    var evolution_pref = this.parameters["x-evolution-ui-slot"];
+    if (evolution_pref != null && Utils.get_first (evolution_pref) == "1")
+      return true;
+
+    foreach (var param in this.parameters["type"]) {
+      if (param.ascii_casecmp ("PREF") == 0)
+        return true;
+    }
+    return false;
+  }
 }
diff --git a/src/meson.build b/src/meson.build
index 5c2ef5dd..b29028e1 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -28,7 +28,6 @@ libcontacts_sources = files(
   'core/contacts-urls-chunk.vala',
   'core/contacts-vcard-type-mapping.vala',
 
-  'contacts-abstract-field-details-sorter.vala',
   'contacts-chunk-filter.vala',
   'contacts-chunk-empty-filter.vala',
   'contacts-chunk-property-filter.vala',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]