]> cgit.babelmonkeys.de Git - jubjub.git/blobdiff - src/gui/gtk/JubGtkRosterUI.m
Move away from BOOL
[jubjub.git] / src / gui / gtk / JubGtkRosterUI.m
index dcd6f7d8b42553d6e50049a3ea1a39739f366417..432677cb8f1e2c9e92cbebf6efb29f2329931188 100644 (file)
@@ -32,7 +32,7 @@ static void roster_row_activated(GtkTreeView *tree_view, GtkTreePath *path,
 
        [client performSelectorOnMainThread: @selector(chatForContact:)
                                 withObject: contact
-                             waitUntilDone: NO];
+                             waitUntilDone: false];
        [pool release];
 }
 
@@ -50,6 +50,7 @@ static void presence_changed(GtkComboBox *combo_box, gpointer data)
 static gboolean filter_roster_by_presence(GtkTreeModel *model,
     GtkTreeIter *iter, gpointer data)
 {
+       bool *showOffline = data;
        char *status;
        gtk_tree_model_get(model, iter, 2, &status, -1);
 
@@ -57,19 +58,24 @@ static gboolean filter_roster_by_presence(GtkTreeModel *model,
        if (!status)
                return TRUE;
 
-       if (!strcmp(status, "unavailable"))
+       if (!*showOffline && !strcmp(status, "unavailable"))
                return FALSE;
 
        return TRUE;
 }
 
+static void menu_show_offline(GtkCheckMenuItem *checkmenuitem, gpointer data)
+{
+       JubGtkRosterUI *ui = data;
+       ui.showOffline = gtk_check_menu_item_get_active(checkmenuitem);
+}
+
 static void dialog_response_callback(GtkDialog *dialog, gint response_id,
     gpointer user_data)
 {
        void (^block)(gint) = user_data;
        block(response_id);
        [block release];
-       gtk_widget_destroy(GTK_WIDGET(dialog));
 }
 
 @implementation JubGtkRosterUI
@@ -78,12 +84,16 @@ static void dialog_response_callback(GtkDialog *dialog, gint response_id,
        self = [super init];
 
        @try {
+               GtkCheckMenuItem *show_offline_menu_item;
                GtkTreeView *roster_view;
                GtkBuilder *builder;
 
                _groupMap = [[OFMapTable alloc]
                    initWithKeyFunctions: keyFunctions
                          valueFunctions: rowRefFunctions];
+               _subDialogMap = [[OFMapTable alloc]
+                   initWithKeyFunctions: keyFunctions
+                   valueFunctions: gObjectFunctions];
                _contactMap = [[OFMutableDictionary alloc] init];
                _client = [client retain];
 
@@ -106,7 +116,7 @@ static void dialog_response_callback(GtkDialog *dialog, gint response_id,
                    gtk_builder_get_object(builder, "RosterTreeModelFilter"));
 
                gtk_tree_model_filter_set_visible_func(_roster_filter,
-                   filter_roster_by_presence, NULL, NULL);
+                   filter_roster_by_presence, &_showOffline, NULL);
 
                roster_view = GTK_TREE_VIEW(gtk_builder_get_object(builder,
                        "RosterTreeView"));
@@ -121,6 +131,13 @@ static void dialog_response_callback(GtkDialog *dialog, gint response_id,
                    g_signal_connect(_presence_combo, "changed",
                        G_CALLBACK(presence_changed), client);
 
+               show_offline_menu_item =
+                   GTK_CHECK_MENU_ITEM(gtk_builder_get_object(builder,
+                       "showOfflineCheckMenuItem"));
+
+               g_signal_connect(show_offline_menu_item, "toggled",
+                   G_CALLBACK(menu_show_offline), self);
+
                g_object_unref(G_OBJECT(builder));
        } @catch (id e) {
                [self release];
@@ -134,6 +151,7 @@ static void dialog_response_callback(GtkDialog *dialog, gint response_id,
 {
        [_client.avatarManager setDelegate: nil];
        [_client.contactManager removeDelegate: self];
+       [_subDialogMap release];
        [_groupMap release];
        [_contactMap release];
        [_client release];
@@ -143,6 +161,19 @@ static void dialog_response_callback(GtkDialog *dialog, gint response_id,
        [super dealloc];
 }
 
+- (void)Jub_closeSubscribeDialogForRosterItem: (XMPPRosterItem*)rosterItem
+{
+       // Close subscripton dialogs, answered on another client
+       GtkDialog *dialog;
+       OFString *subscription = rosterItem.subscription;
+       OFString *bareJID = [rosterItem.JID bareJID];
+
+       if (([subscription isEqual: @"from"] ||
+            [subscription isEqual: @"both"]) &&
+           (dialog = [_subDialogMap valueForKey: bareJID]) != NULL)
+               gtk_dialog_response(dialog, GTK_RESPONSE_NONE);
+}
+
 /* Roster Delegate methods */
 - (void)Jub_addRosterItem: (XMPPRosterItem*)item
                    group: (OFString*)group
@@ -266,6 +297,8 @@ static void dialog_response_callback(GtkDialog *dialog, gint response_id,
                    Jub_addRosterItem:group:)
                                       withObject: rosterItem
                                       withObject: group];
+
+       [self Jub_closeSubscribeDialogForRosterItem: rosterItem];
 }
 
 - (void)contactManager: (XMPPContactManager*)manager
@@ -288,11 +321,15 @@ static void dialog_response_callback(GtkDialog *dialog, gint response_id,
   didReceiveSubscriptionRequest: (XMPPPresence*)presence
 {
        XMPPJID *JID = presence.from;
+       OFString *bareJID = [JID bareJID];
        OFString *message = [OFString stringWithFormat: @"<b>%@</b> would like "
-           @"to subscribe to your presence.", JID];
-       of_log(@"%@", message);
+           @"to subscribe to your presence.", bareJID];
        g_idle_add_block(^{
                GtkWidget *dialog, *content_area, *label;
+
+               if ([_subDialogMap valueForKey: JID] != NULL)
+                       return;
+
                dialog = gtk_dialog_new_with_buttons("Subscription Request",
                    GTK_WINDOW(_roster_window), GTK_DIALOG_DESTROY_WITH_PARENT,
                    "Accept", GTK_RESPONSE_ACCEPT,
@@ -301,6 +338,7 @@ static void dialog_response_callback(GtkDialog *dialog, gint response_id,
                content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
                label = gtk_label_new(NULL);
                gtk_label_set_markup(GTK_LABEL(label), [message UTF8String]);
+               gtk_container_add(GTK_CONTAINER(content_area), label);
 
                g_signal_connect(dialog, "response",
                    G_CALLBACK(dialog_response_callback),
@@ -309,9 +347,13 @@ static void dialog_response_callback(GtkDialog *dialog, gint response_id,
                                [manager sendSubscribedToJID: JID];
                        else if (response_id == GTK_RESPONSE_REJECT)
                                [manager sendUnsubscribedToJID: JID];
+                       [_subDialogMap removeValueForKey: bareJID];
+                       gtk_widget_destroy(GTK_WIDGET(dialog));
                } copy]);
 
-               gtk_container_add(GTK_CONTAINER(content_area), label);
+               [_subDialogMap setValue: dialog
+                                forKey: bareJID];
+
                gtk_widget_show_all(dialog);
        });
 }
@@ -319,6 +361,8 @@ static void dialog_response_callback(GtkDialog *dialog, gint response_id,
 -           (void)contact: (XMPPContact*)contact
   willUpdateWithRosterItem: (XMPPRosterItem*)rosterItem;
 {
+       [self Jub_closeSubscribeDialogForRosterItem: rosterItem];
+
        // Remove contact from old set of groups
        XMPPRosterItem *oldItem = contact.rosterItem;
        OFArray *groups = oldItem.groups;
@@ -421,7 +465,8 @@ static void dialog_response_callback(GtkDialog *dialog, gint response_id,
                OFArray *groups = contact.rosterItem.groups;;
 
                GdkPixbuf *avatar =
-                   gdk_pixbuf_new_from_file([avatarFile UTF8String], NULL);
+                   gdk_pixbuf_new_from_file_at_size([avatarFile UTF8String],
+                       32, 32, NULL);
 
                if (groups == nil)
                        groups = @[ @"General" ];
@@ -478,4 +523,17 @@ static void dialog_response_callback(GtkDialog *dialog, gint response_id,
                    [tooltip UTF8String]);
        });
 }
+
+- (bool)showOffline
+{
+       OF_GETTER(_showOffline, true);
+}
+
+- (void)setShowOffline: (bool)showOffline
+{
+       _showOffline = showOffline;
+       g_idle_add_block(^{
+               gtk_tree_model_filter_refilter(_roster_filter);
+       });
+}
 @end