[geary] Fix ContactEntryCompletion and ContactListStore being leaked.



commit ee61c084e753341634729099eac0748a3239ccf1
Author: Michael James Gratton <mike vee net>
Date:   Fri Sep 23 23:34:15 2016 +1000

    Fix ContactEntryCompletion and ContactListStore being leaked.
    
    Use static methods for sort/match functions to avoid circular refs causing
    the objects to never be disposed.

 src/client/composer/contact-entry-completion.vala |   50 +++++++------
 src/client/composer/contact-list-store.vala       |   81 +++++++++++----------
 2 files changed, 69 insertions(+), 62 deletions(-)
---
diff --git a/src/client/composer/contact-entry-completion.vala 
b/src/client/composer/contact-entry-completion.vala
index 3685711..2f3d24f 100644
--- a/src/client/composer/contact-entry-completion.vala
+++ b/src/client/composer/contact-entry-completion.vala
@@ -5,15 +5,38 @@
  */
 
 public class ContactEntryCompletion : Gtk.EntryCompletion {
+
+
+    private static bool completion_match_func(Gtk.EntryCompletion completion, string key, Gtk.TreeIter iter) 
{
+        ContactEntryCompletion contacts = (ContactEntryCompletion) completion;
+
+        // We don't use the provided key, because the user can enter multiple addresses.
+        int current_address_index;
+        string current_address_key;
+        contacts.get_addresses(completion, out current_address_index, out current_address_key);
+
+        Geary.Contact? contact = contacts.list_store.get_contact(iter);
+        if (contact == null)
+            return false;
+
+        string highlighted_result;
+        if (!contacts.match_prefix_contact(current_address_key, contact, out highlighted_result))
+            return false;
+
+        contacts.list_store.set_highlighted_result(iter, highlighted_result, current_address_key);
+
+        return true;
+    }
+
     private ContactListStore list_store;
     private Gtk.TreeIter? last_iter = null;
-    
+
     public ContactEntryCompletion(ContactListStore list_store) {
         this.list_store = list_store;
-        
+
         model = list_store;
-        set_match_func(completion_match_func);
-        
+        set_match_func(ContactEntryCompletion.completion_match_func);
+
         Gtk.CellRendererText text_renderer = new Gtk.CellRendererText();
         pack_start(text_renderer, true);
         add_attribute(text_renderer, "markup", ContactListStore.Column.CONTACT_MARKUP_NAME);
@@ -65,25 +88,6 @@ public class ContactEntryCompletion : Gtk.EntryCompletion {
         last_iter = null;
     }
     
-    private bool completion_match_func(Gtk.EntryCompletion completion, string key, Gtk.TreeIter iter) {
-        // We don't use the provided key, because the user can enter multiple addresses.
-        int current_address_index;
-        string current_address_key;
-        get_addresses(completion, out current_address_index, out current_address_key);
-        
-        Geary.Contact? contact = list_store.get_contact(iter);
-        if (contact == null)
-            return false;
-        
-        string highlighted_result;
-        if (!match_prefix_contact(current_address_key, contact, out highlighted_result))
-            return false;
-        
-        list_store.set_highlighted_result(iter, highlighted_result, current_address_key);
-        
-        return true;
-    }
-    
     private Gee.List<string> get_addresses(Gtk.EntryCompletion completion,
         out int current_address_index = null, out string current_address_key = null,
         out string current_address_remainder = null) {
diff --git a/src/client/composer/contact-list-store.vala b/src/client/composer/contact-list-store.vala
index 1bc30ea..1e11dbc 100644
--- a/src/client/composer/contact-list-store.vala
+++ b/src/client/composer/contact-list-store.vala
@@ -12,6 +12,46 @@ public class ContactListStore : Gtk.ListStore {
     // Batch size for loading contacts asynchronously
     private uint LOAD_BATCH_SIZE = 4096;
 
+
+    private static int sort_func(Gtk.TreeModel model, Gtk.TreeIter aiter, Gtk.TreeIter biter) {
+        // Order by importance, then by real name, then by email.
+        GLib.Value avalue, bvalue;
+        model.get_value(aiter, Column.CONTACT_OBJECT, out avalue);
+        model.get_value(biter, Column.CONTACT_OBJECT, out bvalue);
+        Geary.Contact? acontact = avalue.get_object() as Geary.Contact;
+        Geary.Contact? bcontact = bvalue.get_object() as Geary.Contact;
+
+        // Contacts can be null if the sort func is called between TreeModel.append and
+        // TreeModel.set.
+        if (acontact == bcontact)
+            return 0;
+        if (acontact == null && bcontact != null)
+            return -1;
+        if (acontact != null && bcontact == null)
+            return 1;
+
+        // First order by importance.
+        if (acontact.highest_importance > bcontact.highest_importance)
+            return -1;
+        if (acontact.highest_importance < bcontact.highest_importance)
+            return 1;
+
+        // Then order by real name.
+        string? anormalized_real_name = acontact.real_name == null ? null :
+            acontact.real_name.normalize().casefold();
+        string? bnormalized_real_name = bcontact.real_name == null ? null :
+            bcontact.real_name.normalize().casefold();
+        // strcmp correctly marks 'null' as first in lexigraphic order, so we don't need to
+        // special-case it.
+        int result = strcmp(anormalized_real_name, bnormalized_real_name);
+        if (result != 0)
+            return result;
+
+        // Finally, order by email.
+        return strcmp(acontact.normalized_email, bcontact.normalized_email);
+    }
+
+
     public enum Column {
         CONTACT_OBJECT,
         CONTACT_MARKUP_NAME,
@@ -55,7 +95,7 @@ public class ContactListStore : Gtk.ListStore {
         }
 
         // set sort function *after* adding all the contacts
-        set_sort_func(Column.CONTACT_OBJECT, sort_func);
+        set_sort_func(Column.CONTACT_OBJECT, ContactListStore.sort_func);
         set_sort_column_id(Column.CONTACT_OBJECT, Gtk.SortType.ASCENDING);
     }
 
@@ -124,43 +164,6 @@ public class ContactListStore : Gtk.ListStore {
     private void on_contact_updated(Geary.Contact contact) {
         update_contact(contact);
     }
-    
-    private int sort_func(Gtk.TreeModel model, Gtk.TreeIter aiter, Gtk.TreeIter biter) {
-        // Order by importance, then by real name, then by email.
-        GLib.Value avalue, bvalue;
-        model.get_value(aiter, Column.CONTACT_OBJECT, out avalue);
-        model.get_value(biter, Column.CONTACT_OBJECT, out bvalue);
-        Geary.Contact? acontact = avalue.get_object() as Geary.Contact;
-        Geary.Contact? bcontact = bvalue.get_object() as Geary.Contact;
-        
-        // Contacts can be null if the sort func is called between TreeModel.append and
-        // TreeModel.set.
-        if (acontact == bcontact)
-            return 0;
-        if (acontact == null && bcontact != null)
-            return -1;
-        if (acontact != null && bcontact == null)
-            return 1;
-        
-        // First order by importance.
-        if (acontact.highest_importance > bcontact.highest_importance)
-            return -1;
-        if (acontact.highest_importance < bcontact.highest_importance)
-            return 1;
-        
-        // Then order by real name.
-        string? anormalized_real_name = acontact.real_name == null ? null :
-            acontact.real_name.normalize().casefold();
-        string? bnormalized_real_name = bcontact.real_name == null ? null :
-            bcontact.real_name.normalize().casefold();
-        // strcmp correctly marks 'null' as first in lexigraphic order, so we don't need to
-        // special-case it.
-        int result = strcmp(anormalized_real_name, bnormalized_real_name);
-        if (result != 0)
-            return result;
-        
-        // Finally, order by email.
-        return strcmp(acontact.normalized_email, bcontact.normalized_email);
-    }
+
 }
 


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