]> cgit.babelmonkeys.de Git - jubjub.git/blobdiff - src/gui/gtk/JubGtkUI.m
Filter roster model based on received presences
[jubjub.git] / src / gui / gtk / JubGtkUI.m
index 48278b86244dc555f48fd6926ad47ff00e3a8682..359f4837ef56129481f5a08d1a00dfc804b21de4 100644 (file)
@@ -9,6 +9,32 @@ void on_roster_window_destroy(GObject *object, gpointer user_data)
        gtk_main_quit();
 }
 
+static gboolean filter_roster_by_presence(GtkTreeModel *model,
+    GtkTreeIter *iter, gpointer data)
+{
+       char *jid_s;
+       OFString *jid;
+       OFCountedSet *presences = data;
+
+       gtk_tree_model_get(model, iter, 1, &jid_s, -1);
+
+       // Groups have no JID
+       if (!jid_s)
+               return TRUE;
+
+       jid = [[OFString alloc] initWithUTF8String: jid_s];
+
+       g_free(jid_s);
+
+       if ([presences countForObject: jid]) {
+               [jid release];
+               return TRUE;
+       } else {
+               [jid release];
+               return FALSE;
+       }
+}
+
 @implementation JubGtkUI
 - init
 {
@@ -19,6 +45,7 @@ void on_roster_window_destroy(GObject *object, gpointer user_data)
                    initWithKeyFunctions: keyFunctions
                          valueFunctions: rowRefFunctions];
                contactMap = [[OFMutableDictionary alloc] init];
+               presences = [[OFCountedSet alloc] init];
        } @catch (id e) {
                [self release];
                @throw e;
@@ -32,6 +59,7 @@ void on_roster_window_destroy(GObject *object, gpointer user_data)
 
        [groupMap release];
        [contactMap release];
+       [presences release];
 
        if (roster_model)
                g_object_unref(roster_model);
@@ -61,6 +89,12 @@ void on_roster_window_destroy(GObject *object, gpointer user_data)
        roster_model =
            GTK_TREE_STORE(gtk_builder_get_object(builder, "RosterTreeStore"));
 
+       roster_filter = GTK_TREE_MODEL_FILTER(
+           gtk_builder_get_object(builder,"RosterTreeModelFilter"));
+
+       gtk_tree_model_filter_set_visible_func(roster_filter,
+           filter_roster_by_presence, presences, NULL);
+
        gtk_builder_connect_signals(builder, NULL);
        g_object_unref(G_OBJECT(builder));
 
@@ -80,6 +114,25 @@ void on_roster_window_destroy(GObject *object, gpointer user_data)
        return self;
 }
 
+/* Presence handling */
+static gboolean refilter_roster(gpointer data)
+{
+       gtk_tree_model_filter_refilter(data);
+
+       return FALSE;
+}
+
+-   (void)connection: (XMPPConnection*)connection
+  didReceivePresence: (XMPPPresence*)presence
+{
+       if ([presence.type isEqual: @"available"])
+               [presences addObject: [presence.from bareJID]];
+       else
+               [presences removeObject: [presence.from bareJID]];
+
+       g_idle_add(refilter_roster, roster_filter);
+}
+
 /* Roster Delegate methods */
 struct add_roster_item_param {
        OFString *group;
@@ -149,37 +202,6 @@ static gboolean add_roster_item(gpointer user_data)
        return FALSE;
 }
 
-- (void)rosterWasReceived: (XMPPRoster*)roster_
-{
-       [[roster_ rosterItems] enumerateKeysAndObjectsUsingBlock:
-           ^(OFString *bareJID, XMPPRosterItem *item, BOOL *stop) {
-               OFArray *groups;
-               OFMapTable *contactRows = [OFMapTable
-                   mapTableWithKeyFunctions: keyFunctions
-                             valueFunctions: rowRefFunctions];
-
-               [contactMap setObject: contactRows
-                              forKey: bareJID];
-
-               if (item.groups != nil)
-                       groups = item.groups;
-               else
-                       groups = @[@"General"];
-
-               for (OFString *group in groups) {
-                       struct add_roster_item_param *params =
-                           malloc(sizeof(*params));
-                       params->group = [group retain];
-                       params->name = [item.name retain];
-                       params->jid = [bareJID retain];
-                       params->groupMap = [groupMap retain];
-                       params->contactRows = [contactRows retain];
-                       params->roster_model = g_object_ref(roster_model);
-                       g_idle_add(add_roster_item, params);
-               }
-       }];
-}
-
 struct remove_roster_item_param {
        OFString *group;
        OFMapTable *groupMap;
@@ -223,6 +245,37 @@ static gboolean remove_roster_item(gpointer user_data)
        return FALSE;
 }
 
+- (void)rosterWasReceived: (XMPPRoster*)roster_
+{
+       [[roster_ rosterItems] enumerateKeysAndObjectsUsingBlock:
+           ^(OFString *bareJID, XMPPRosterItem *item, BOOL *stop) {
+               OFArray *groups;
+               OFMapTable *contactRows = [OFMapTable
+                   mapTableWithKeyFunctions: keyFunctions
+                             valueFunctions: rowRefFunctions];
+
+               [contactMap setObject: contactRows
+                              forKey: bareJID];
+
+               if (item.groups != nil)
+                       groups = item.groups;
+               else
+                       groups = @[@"General"];
+
+               for (OFString *group in groups) {
+                       struct add_roster_item_param *params =
+                           malloc(sizeof(*params));
+                       params->group = [group retain];
+                       params->name = [item.name retain];
+                       params->jid = [bareJID retain];
+                       params->groupMap = [groupMap retain];
+                       params->contactRows = [contactRows retain];
+                       params->roster_model = g_object_ref(roster_model);
+                       g_idle_add(add_roster_item, params);
+               }
+       }];
+}
+
 -         (void)roster: (XMPPRoster*)roster_
   didReceiveRosterItem: (XMPPRosterItem*)item
 {