+- (void)contact: (XMPPContact*)contact
+ didSendPresence: (XMPPPresence*)presence
+{
+ OFDictionary *allPresences = [contact presences];
+ XMPPPresence *highPresence = [[[allPresences allObjects] sortedArray]
+ lastObject];
+ OFMutableString *tooltip =
+ [OFMutableString stringWithString: @"<b>Resources:</b>"];
+
+ [allPresences enumerateKeysAndObjectsUsingBlock:
+ ^(OFString *resource, XMPPPresence *pres, BOOL *stop) {
+ [tooltip appendString: @"\n"];
+ [tooltip appendString: resource];
+ if ([pres.type isEqual: @"available"]) {
+ if (pres.show != nil)
+ [tooltip appendFormat: @" (%@)", pres.show];
+ else
+ [tooltip appendString: @" (available)"];
+ } else
+ [tooltip appendString: @" (unavailable)"];
+
+ if (pres.status)
+ [tooltip appendFormat: @": <i>%@</i>", pres.status];
+ }];
+
+ g_idle_add_block(^{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ GtkTreeRowReference *ref;
+ OFString *bareJID = [contact.rosterItem.JID bareJID];
+ OFMapTable *contactRows = [_contactMap objectForKey: bareJID];
+
+ for (OFString *group in contact.rosterItem.groups) {
+ ref = [contactRows valueForKey: group];
+ path = gtk_tree_row_reference_get_path(ref);
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(_roster_model),
+ &iter, path);
+ gtk_tree_path_free(path);
+
+ if ([highPresence.type isEqual: @"available"]) {
+ if (highPresence.show != nil)
+ gtk_tree_store_set(_roster_model, &iter,
+ 2, [highPresence.show UTF8String],
+ -1);
+ else
+ gtk_tree_store_set(_roster_model, &iter,
+ 2, "available", -1);
+ } else
+ gtk_tree_store_set(_roster_model, &iter,
+ 2, "unavailable", -1);
+
+ gtk_tree_store_set(_roster_model, &iter,
+ 3, [tooltip UTF8String], -1);
+ }
+
+ gtk_tree_model_filter_refilter(_roster_filter);
+ });
+}
+
+- (void)client: (JubChatClient*)client_
+ didChangePresence: (XMPPPresence*)presence
+{
+ OFString *tooltip = @"";
+ OFString *show =
+ [[presence elementForName: @"show"
+ namespace: XMPP_NS_CLIENT] stringValue];
+ OFString *status =
+ [[presence elementForName: @"status"
+ namespace: XMPP_NS_CLIENT] stringValue];
+
+ if (status != nil)
+ tooltip = [@"<b>Status:</b> " stringByAppendingString: status];
+
+ g_idle_add_block(^{
+ // Block the PresenceComboBox's changed handler, so it doesn't
+ // fire and resend presence
+ g_signal_handler_block(_presence_combo,
+ _presence_combo_changed_handler_id);
+
+ if ([presence.type isEqual: @"unavailable"])
+ gtk_combo_box_set_active_id(_presence_combo,
+ "unavailable");
+ else if (show == nil)
+ gtk_combo_box_set_active_id(_presence_combo,
+ "available");
+ else
+ gtk_combo_box_set_active_id(_presence_combo,
+ [show UTF8String]);
+
+ // Unblock the changed handler
+ g_signal_handler_unblock(_presence_combo,
+ _presence_combo_changed_handler_id);
+
+ gtk_widget_set_tooltip_markup(GTK_WIDGET(_presence_combo),
+ [tooltip UTF8String]);
+ });
+}