public class Roster : Object, Gtk.TreeModel { private int stamp; private Gee.TreeMap entries = new Gee.TreeMap(); public Roster() { stamp = 0; } public void update_contact(Contact c) { ++stamp; bool added = !entries.has_key(c.jid); entries[c.jid] = c; Gtk.TreeIter iter = Gtk.TreeIter(); iter.stamp = stamp; iter.user_data = this; iter.user_data2 = c; Gtk.TreePath path = get_path(iter); if (added) row_inserted(path, iter); else row_changed(path, iter); } public Type get_column_type (int index) { switch(index) { case 0: return typeof(Contact); } return Type.INVALID; } public Gtk.TreeModelFlags get_flags () { return Gtk.TreeModelFlags.LIST_ONLY; } public bool get_iter (out Gtk.TreeIter iter, Gtk.TreePath path) { if(path.get_depth() != 1) return false; int index = path.get_indices()[0]; if(index < 0 || index >= entries.size) return false; Gee.MapIterator it = entries.map_iterator(); it.first(); for(int i = 0; i < index; ++i) it.next(); iter.stamp = stamp; iter.user_data = this; iter.user_data2 = it.get_value(); return true; } public int get_n_columns () { return 1; } public Gtk.TreePath get_path (Gtk.TreeIter iter) { if(iter.stamp != stamp || iter.user_data != this) return (Gtk.TreePath)null; int index = 0; foreach(Contact c in entries.values) { if(c == iter.user_data2) break; ++index; } return new Gtk.TreePath.from_indices(index, -1); } public void get_value (Gtk.TreeIter iter, int column, out Value value) { if (column != 0 || iter.stamp != stamp || iter.user_data != this) return; Contact c = iter.user_data2 as Contact; value = Value(typeof(Contact)); value.take_object(c); } public bool iter_children (out Gtk.TreeIter iter, Gtk.TreeIter? parent) { if (parent != null) { iter.stamp = -1; return false; } return get_iter(out iter, new Gtk.TreePath.from_indices(0, -1)); } public bool iter_has_child (Gtk.TreeIter iter) { return false; } public int iter_n_children (Gtk.TreeIter? iter) { if (iter == null) return entries.size; else return 0; } public bool iter_next (ref Gtk.TreeIter iter) { if(iter.stamp != stamp || iter.user_data != this) return false; bool next = false; foreach(Contact c in entries.values) { if(next) { iter.user_data2 = c; return true; } if(c == iter.user_data2) next = true; } iter.stamp = -1; return false; } public bool iter_nth_child (out Gtk.TreeIter iter, Gtk.TreeIter? parent, int n) { if (parent != null) { iter.stamp = -1; return false; } return get_iter(out iter, new Gtk.TreePath.from_indices(n, -1)); } public bool iter_parent (out Gtk.TreeIter iter, Gtk.TreeIter child) { iter.stamp = -1; return false; } public void ref_node (Gtk.TreeIter iter) {} public void unref_node (Gtk.TreeIter iter) {} }