]> cgit.babelmonkeys.de Git - jubjub.git/commitdiff
Filter roster model based on received presences
authorFlorian Zeitz <florob@babelmonkeys.de>
Sat, 15 Dec 2012 00:25:04 +0000 (01:25 +0100)
committerFlorian Zeitz <florob@babelmonkeys.de>
Sat, 15 Dec 2012 00:25:04 +0000 (01:25 +0100)
data/gtk/roster.ui
src/core/main.m
src/gui/common/JubUI.h
src/gui/gtk/JubGtkUI.h
src/gui/gtk/JubGtkUI.m

index b2e05df7de367b0586b5404a4686bb5eb0e52146..359de0150800d3626cd0580244e32a5c728cd4ab 100644 (file)
@@ -43,6 +43,9 @@
       <column type="gchararray"/>
     </columns>
   </object>
+  <object class="GtkTreeModelFilter" id="RosterTreeModelFilter">
+    <property name="child_model">RosterTreeStore</property>
+  </object>
   <object class="GtkWindow" id="RosterWindow">
     <property name="can_focus">False</property>
     <property name="title" translatable="yes">JubJub</property>
               <object class="GtkTreeView" id="RosterTreeView">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="model">RosterTreeStore</property>
+                <property name="model">RosterTreeModelFilter</property>
                 <property name="search_column">0</property>
                 <child internal-child="selection">
                   <object class="GtkTreeSelection" id="RosterTreeViewSelection"/>
index e40a02f328fe7ed2b0ea14bd1420c0ac3a082e8b..ff97a3b602b56b98e01f071e7c3040923f23e912 100644 (file)
@@ -4,7 +4,7 @@
 #import "JubGtkUI.h"
 
 @interface AppDelegate: OFObject
-    <OFApplicationDelegate, XMPPConnectionDelegate>
+    <OFApplicationDelegate, XMPPConnectionDelegate, XMPPRosterDelegate>
 {
        XMPPConnection *connection;
        XMPPRoster *roster;
@@ -29,8 +29,11 @@ OF_APPLICATION_DELEGATE(AppDelegate)
        [connection connect];
        [connection handleConnection];
 
+       [connection addDelegate: [ui rosterDelegate]];
+
        roster = [[XMPPRoster alloc] initWithConnection: connection];
        [roster addDelegate: [ui rosterDelegate]];
+       [roster addDelegate: self];
 
        [ui startUIThread];
 }
@@ -43,6 +46,11 @@ OF_APPLICATION_DELEGATE(AppDelegate)
        [roster requestRoster];
 }
 
+- (void)rosterWasReceived: (XMPPRoster*)roster
+{
+       [connection sendStanza: [XMPPPresence presence]];
+}
+
 -  (void)connection: (XMPPConnection*)conn
   didReceiveElement: (OFXMLElement*)element
 {
index 3fd08b3370e5bf7d012c806919a38b00ea602088..2ec2cf717cad1aade76c43cec3b2f6262cc14c0f 100644 (file)
@@ -2,5 +2,5 @@
 
 @protocol JubUI
 - (void)startUIThread;
-- (id<XMPPRosterDelegate>)rosterDelegate;
+- (id<XMPPRosterDelegate, XMPPConnectionDelegate>)rosterDelegate;
 @end
index 31e6902f2b0879c07a3bba334753339870eddd3c..15481944461c316b8deb603aa5c81c7e64c618df 100644 (file)
@@ -3,10 +3,12 @@
 
 #import "JubUI.h"
 
-@interface JubGtkUI: OFObject <JubUI, XMPPRosterDelegate>
+@interface JubGtkUI: OFObject <JubUI, XMPPRosterDelegate, XMPPConnectionDelegate>
 {
        GtkTreeStore *roster_model;
+       GtkTreeModelFilter *roster_filter;
        OFMapTable *groupMap;
        OFMutableDictionary *contactMap;
+       OFCountedSet *presences;
 }
 @end
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
 {