+/* Roster Delegate methods */
+- (void)Jub_addRosterItem: (XMPPRosterItem*)item
+ group: (OFString*)group
+{
+ g_idle_add_block(^{
+ GtkTreeIter group_iter, contact_iter;
+ GtkTreeRowReference *group_ref, *contact_ref;
+ GtkTreePath *group_path, *contact_path;
+ OFMapTable *contactRows =
+ [contactMap objectForKey: [item.JID bareJID]];
+
+ group_ref = [groupMap valueForKey: group];
+
+ if (!group_ref) {
+ // Create new group row
+ gtk_tree_store_append(roster_model, &group_iter, NULL);
+ gtk_tree_store_set(roster_model, &group_iter,
+ 0, [group UTF8String], -1);
+
+ group_path = gtk_tree_model_get_path(GTK_TREE_MODEL(
+ roster_model), &group_iter);
+
+ group_ref = gtk_tree_row_reference_new(GTK_TREE_MODEL(
+ roster_model), group_path);
+
+ [groupMap setValue: group_ref
+ forKey: group];
+ } else {
+ // Get iter for existing group row
+ group_path = gtk_tree_row_reference_get_path(group_ref);
+
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(roster_model),
+ &group_iter, group_path);
+ }
+ gtk_tree_path_free(group_path);
+
+ // Create new contact row
+ gtk_tree_store_append(roster_model, &contact_iter, &group_iter);
+ if (item.name)
+ gtk_tree_store_set(roster_model, &contact_iter,
+ 0, [item.name UTF8String],
+ 1, [[item.JID bareJID] UTF8String], -1);
+ else
+ gtk_tree_store_set(roster_model, &contact_iter,
+ 0, [item.JID.node UTF8String],
+ 1, [[item.JID bareJID] UTF8String], -1);