[geary] Fix ContactEntryCompletion and ContactListStore being leaked.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary] Fix ContactEntryCompletion and ContactListStore being leaked.
- Date: Fri, 23 Sep 2016 13:59:53 +0000 (UTC)
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]