From ad56d57251f67ac416ff7ad71a76f30836d2ccb3 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 26 Jun 2010 00:11:08 +0200 Subject: Added groups to roster --- src/gui/Roster.vala | 392 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 283 insertions(+), 109 deletions(-) (limited to 'src/gui/Roster.vala') diff --git a/src/gui/Roster.vala b/src/gui/Roster.vala index be0a5ed..65119e2 100644 --- a/src/gui/Roster.vala +++ b/src/gui/Roster.vala @@ -1,154 +1,328 @@ -public class Roster : Object, Gtk.TreeModel { - private int stamp; - private Gee.TreeMap entries = new Gee.TreeMap(); +public class Roster { + private Gtk.VBox rosterView; + private RosterModel model; + private Gee.TreeMap groups = new Gee.TreeMap(); + public signal void start_conversation(string jid); - public Roster() { - stamp = 0; + + public Roster(Gtk.VBox rosterView0) { + rosterView = rosterView0; + model = new RosterModel(this); + } + + public Gtk.TreeModel get_model() { + return model; } 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); + model.update_contact(c); } public Contact get_contact(string jid) { - string bareJID = jid.split("/", 2)[0]; - - return entries[bareJID]; + return model.get_contact(jid); } - public Type get_column_type (int index) { - switch(index) { - case 0: - return typeof(Contact); - } + private Gtk.TreeView new_tree_view() { + Gtk.TreeView view = new Gtk.TreeView(); + + view.headers_visible = false; + + view.query_tooltip.connect((x, y, keyboard_tip, tooltip) => { + Gtk.TreeModel model; + Gtk.TreeIter iter; + + if(!view.get_tooltip_context(out x, out y, keyboard_tip, out model, null, out iter)) + return false; + + Value value; + model.get_value(iter, 0, out value); + + Contact? c = value.get_object() as Contact; + if(c == null) + return false; + + Gee.Map.Entry? r = c.get_resource_with_highest_priority(); + + if(r == null) + return false; + + tooltip.set_text("Resource: " + r.key + " (" + r.value.priority.to_string() + ")"); + + return true; + }); + view.has_tooltip = true; + + view.row_activated.connect((view, path, column) => { + Gtk.TreeIter iter; + view.model.get_iter(out iter, path); + + Value value; + view.model.get_value(iter, 0, out value); + + Contact contact = value.get_object() as Contact; + if(contact == null) + return; + + Gee.Map.Entry res = contact.get_resource_with_highest_priority(); + if(res == null) + return; //FIXME + + start_conversation(contact.jid + "/" + res.key); + }); + + Gtk.TreeViewColumn presenceColumn = new Gtk.TreeViewColumn.with_attributes(null, new CellRendererPresence(), "contact", 0, null); + presenceColumn.min_width = 32; + view.append_column(presenceColumn); + + Gtk.TreeViewColumn contactColumn = new Gtk.TreeViewColumn(); - return Type.INVALID; + Gtk.CellRenderer cellRendererContact = new CellRendererContact(); + contactColumn.pack_start(cellRendererContact, true); + contactColumn.set_attributes(cellRendererContact, "contact", 0, null); + + Gtk.CellRenderer cellRendererAvatar = new CellRendererAvatar(); + contactColumn.pack_end(cellRendererAvatar, false); + contactColumn.set_attributes(cellRendererAvatar, "contact", 0, null); + + view.append_column(contactColumn); + + return view; } + + private void update_groups() { + int i = 0; - public Gtk.TreeModelFlags get_flags () { - return Gtk.TreeModelFlags.LIST_ONLY; + foreach(Gee.Map.Entry group in groups) { + if(group.value.count <= 0) { + rosterView.remove(group.value.expander); + group.value.expander.remove(group.value.view); + groups.remove(group.key); + continue; + } + + if(group.value.count > 0 && group.value.view == null) { + group.value.view = new_tree_view(); + group.value.view.model = new GroupFilter(this, group.key); + + group.value.expander = new Gtk.Expander("" + Markup.escape_text(group.key) + ""); + group.value.expander.set_use_markup(true); + group.value.expander.expanded = true; + group.value.expander.add(group.value.view); + group.value.expander.show_all(); + + rosterView.pack_start(group.value.expander, false, false, 0); + } + + rosterView.reorder_child(group.value.expander, i++); + } } + + private class RosterModel : Object, Gtk.TreeModel { + private Roster roster; + private int stamp = 0; + private Gee.TreeMap entries = new Gee.TreeMap(); + - public bool get_iter (out Gtk.TreeIter iter, Gtk.TreePath path) { - if(path.get_depth() != 1) - return false; + public RosterModel(Roster roster0) { + roster = roster0; + } + + public void update_contact(Contact c) { + ++stamp; + bool added = true; + if(c.jid in entries) { + added = false; + + foreach(string group in entries[c.jid].get_groups()) { + if(group in roster.groups) { + roster.groups[group].count--; + } + else { + warn_if_reached(); + } + } + } - 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(); + entries[c.jid] = c; - iter.stamp = stamp; - iter.user_data = this; - iter.user_data2 = it.get_value(); + Gtk.TreeIter iter = Gtk.TreeIter(); + iter.stamp = stamp; + iter.user_data = this; + iter.user_data2 = c; - return true; - } + Gtk.TreePath path = get_path(iter); + + if(added) + row_inserted(path, iter); + else + row_changed(path, iter); + + foreach(string group in c.get_groups()) { + if(!(group in roster.groups)) + roster.groups[group] = new GroupInfo(); + + roster.groups[group].count++; + } + + roster.update_groups(); + } - public int get_n_columns () { - return 1; - } + public Contact get_contact(string jid) { + string bareJID = jid.split("/", 2)[0]; + + return entries[bareJID]; + } + + 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 Gtk.TreePath get_path (Gtk.TreeIter iter) { - if(iter.stamp != stamp || iter.user_data != this) - return (Gtk.TreePath)null; + 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; + int index = 0; - foreach(Contact c in entries.values) { - if(c == iter.user_data2) - break; + foreach(Contact c in entries.values) { + if(c == iter.user_data2) + break; - ++index; - } + ++index; + } - return new Gtk.TreePath.from_indices(index, -1); - } + 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) { - value = Value(Type.INVALID); - return; + public void get_value(Gtk.TreeIter iter, int column, out Value value) { + if (column != 0 || iter.stamp != stamp || iter.user_data != this) { + value = Value(Type.INVALID); + 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; + } - Contact c = iter.user_data2 as Contact; - value = Value(typeof(Contact)); - value.take_object(c); - } + return get_iter(out iter, new Gtk.TreePath.from_indices(0, -1)); + } - public bool iter_children (out Gtk.TreeIter iter, Gtk.TreeIter? parent) { - if (parent != null) { - iter.stamp = -1; + public bool iter_has_child(Gtk.TreeIter iter) { 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 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; + 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; - } + bool next = false; + foreach(Contact c in entries.values) { + if(next) { + iter.user_data2 = c; + return true; + } - if(c == iter.user_data2) - next = 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; + } - iter.stamp = -1; - return false; - } + return get_iter(out iter, new Gtk.TreePath.from_indices(n, -1)); + } - public bool iter_nth_child (out Gtk.TreeIter iter, Gtk.TreeIter? parent, int n) { - if (parent != null) { + 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) {} + } + + private class GroupFilter : Gtk.TreeModelFilter { + private Roster roster; + private string group; + + public GroupFilter(Roster roster0, string group0) { + Object(child_model: roster0.model); + + roster = roster0; + group = group0; - return get_iter(out iter, new Gtk.TreePath.from_indices(n, -1)); + set_visible_func((model, iter) => { + Value value; + model.get_value(iter, 0, out value); + + Contact c = value.get_object() as Contact; + + if(c == null) + return true; + + return (group in c.get_groups()); + }); + } } - - public bool iter_parent (out Gtk.TreeIter iter, Gtk.TreeIter child) { - iter.stamp = -1; - return false; + + private class GroupInfo { + public int count = 0; + public Gtk.Expander expander = null; + public Gtk.TreeView view = null; } - - public void ref_node (Gtk.TreeIter iter) {} - public void unref_node (Gtk.TreeIter iter) {} } -- cgit v1.2.3