]> git.0d.be Git - empathy.git/blob - src/empathy-chatrooms-window.c
Merge branch 'sasl'
[empathy.git] / src / empathy-chatrooms-window.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2004-2007 Imendio AB
4  * Copyright (C) 2007-2008 Collabora Ltd.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public
17  * License along with this program; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA  02110-1301  USA
20  *
21  * Authors: Xavier Claessens <xclaesse@gmail.com>
22  *          Martyn Russell <martyn@imendio.com>
23  *          Mikael Hallendal <micke@imendio.com>
24  */
25
26 #include <config.h>
27
28 #include <string.h>
29 #include <stdio.h>
30
31 #include <gtk/gtk.h>
32 #include <glib.h>
33 #include <glib/gi18n.h>
34
35 #include <libempathy/empathy-chatroom-manager.h>
36 #include <libempathy/empathy-utils.h>
37
38 #include <libempathy-gtk/empathy-account-chooser.h>
39 #include <libempathy-gtk/empathy-ui-utils.h>
40
41 #include "empathy-chatrooms-window.h"
42 #include "empathy-new-chatroom-dialog.h"
43
44 typedef struct {
45         EmpathyChatroomManager *manager;
46
47         GtkWidget             *window;
48         GtkWidget             *hbox_account;
49         GtkWidget             *label_account;
50         GtkWidget             *account_chooser;
51         GtkWidget             *treeview;
52         GtkWidget             *button_remove;
53         GtkWidget             *button_close;
54 } EmpathyChatroomsWindow;
55
56 static void             chatrooms_window_destroy_cb                      (GtkWidget             *widget,
57                                                                           EmpathyChatroomsWindow *window);
58 static void             chatrooms_window_model_setup                     (EmpathyChatroomsWindow *window);
59 static void             chatrooms_window_model_add_columns               (EmpathyChatroomsWindow *window);
60 static void             chatrooms_window_model_refresh_data              (EmpathyChatroomsWindow *window,
61                                                                           gboolean               first_time);
62 static void             chatrooms_window_model_add                       (EmpathyChatroomsWindow *window,
63                                                                           EmpathyChatroom        *chatroom,
64                                                                           gboolean               set_active);
65 static void             chatrooms_window_model_cell_auto_connect_toggled (GtkCellRendererToggle  *cell,
66                                                                           gchar                  *path_string,
67                                                                           EmpathyChatroomsWindow  *window);
68 static void             chatrooms_window_button_remove_clicked_cb        (GtkWidget             *widget,
69                                                                           EmpathyChatroomsWindow *window);
70 static void             chatrooms_window_button_close_clicked_cb         (GtkWidget             *widget,
71                                                                           EmpathyChatroomsWindow *window);
72 static void             chatrooms_window_chatroom_added_cb               (EmpathyChatroomManager *manager,
73                                                                           EmpathyChatroom        *chatroom,
74                                                                           EmpathyChatroomsWindow *window);
75 static void             chatrooms_window_chatroom_removed_cb             (EmpathyChatroomManager *manager,
76                                                                           EmpathyChatroom        *chatroom,
77                                                                           EmpathyChatroomsWindow *window);
78 static gboolean         chatrooms_window_remove_chatroom_foreach         (GtkTreeModel          *model,
79                                                                           GtkTreePath           *path,
80                                                                           GtkTreeIter           *iter,
81                                                                           EmpathyChatroom        *chatroom);
82 static void             chatrooms_window_account_changed_cb              (GtkWidget             *combo_box,
83                                                                           EmpathyChatroomsWindow *window);
84
85 enum {
86         COL_IMAGE,
87         COL_NAME,
88         COL_ROOM,
89         COL_AUTO_CONNECT,
90         COL_POINTER,
91         COL_COUNT
92 };
93
94 void
95 empathy_chatrooms_window_show (GtkWindow *parent)
96 {
97         static EmpathyChatroomsWindow *window = NULL;
98         GtkBuilder                    *gui;
99         gchar                         *filename;
100
101         if (window) {
102                 gtk_window_present (GTK_WINDOW (window->window));
103                 return;
104         }
105
106         window = g_new0 (EmpathyChatroomsWindow, 1);
107
108         filename = empathy_file_lookup ("empathy-chatrooms-window.ui", "src");
109         gui = empathy_builder_get_file (filename,
110                                        "chatrooms_window", &window->window,
111                                        "hbox_account", &window->hbox_account,
112                                        "label_account", &window->label_account,
113                                        "treeview", &window->treeview,
114                                        "button_remove", &window->button_remove,
115                                        "button_close", &window->button_close,
116                                        NULL);
117         g_free (filename);
118
119         empathy_builder_connect (gui, window,
120                               "chatrooms_window", "destroy", chatrooms_window_destroy_cb,
121                               "button_remove", "clicked", chatrooms_window_button_remove_clicked_cb,
122                               "button_close", "clicked", chatrooms_window_button_close_clicked_cb,
123                               NULL);
124
125         g_object_unref (gui);
126
127         g_object_add_weak_pointer (G_OBJECT (window->window), (gpointer) &window);
128
129         /* Get the session and chat room manager */
130         window->manager = empathy_chatroom_manager_dup_singleton (NULL);
131
132         g_signal_connect (window->manager, "chatroom-added",
133                           G_CALLBACK (chatrooms_window_chatroom_added_cb),
134                           window);
135         g_signal_connect (window->manager, "chatroom-removed",
136                           G_CALLBACK (chatrooms_window_chatroom_removed_cb),
137                           window);
138
139         /* Account chooser for chat rooms */
140         window->account_chooser = empathy_account_chooser_new ();
141         empathy_account_chooser_set_filter (EMPATHY_ACCOUNT_CHOOSER (window->account_chooser),
142                                             empathy_account_chooser_filter_is_connected,
143                                             NULL);
144         g_object_set (window->account_chooser,
145                       "has-all-option", TRUE,
146                       NULL);
147         empathy_account_chooser_set_account (EMPATHY_ACCOUNT_CHOOSER (window->account_chooser), NULL);
148
149         gtk_box_pack_start (GTK_BOX (window->hbox_account),
150                             window->account_chooser,
151                             TRUE, TRUE, 0);
152
153         g_signal_connect (window->account_chooser, "changed",
154                           G_CALLBACK (chatrooms_window_account_changed_cb),
155                           window);
156
157         gtk_widget_show (window->account_chooser);
158
159         /* Set up chatrooms */
160         chatrooms_window_model_setup (window);
161
162         /* Set focus */
163         gtk_widget_grab_focus (window->treeview);
164
165         /* Last touches */
166         if (parent) {
167                 gtk_window_set_transient_for (GTK_WINDOW (window->window),
168                                               GTK_WINDOW (parent));
169         }
170
171         gtk_widget_show (window->window);
172 }
173
174 static void
175 chatrooms_window_destroy_cb (GtkWidget             *widget,
176                              EmpathyChatroomsWindow *window)
177 {
178         g_signal_handlers_disconnect_by_func (window->manager,
179                                               chatrooms_window_chatroom_added_cb,
180                                               window);
181         g_signal_handlers_disconnect_by_func (window->manager,
182                                               chatrooms_window_chatroom_removed_cb,
183                                               window);
184         g_object_unref (window->manager);
185         g_free (window);
186 }
187
188 static void
189 chatrooms_window_model_setup (EmpathyChatroomsWindow *window)
190 {
191         GtkTreeView      *view;
192         GtkListStore     *store;
193         GtkTreeSelection *selection;
194
195         /* View */
196         view = GTK_TREE_VIEW (window->treeview);
197
198         /* Store */
199         store = gtk_list_store_new (COL_COUNT,
200                                     G_TYPE_STRING,         /* Image */
201                                     G_TYPE_STRING,         /* Name */
202                                     G_TYPE_STRING,         /* Room */
203                                     G_TYPE_BOOLEAN,        /* Auto start */
204                                     EMPATHY_TYPE_CHATROOM); /* Chatroom */
205
206         gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
207
208         /* Selection */
209         selection = gtk_tree_view_get_selection (view);
210         gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
211
212         /* Columns */
213         chatrooms_window_model_add_columns (window);
214
215         /* Add data */
216         chatrooms_window_model_refresh_data (window, TRUE);
217
218         /* Clean up */
219         g_object_unref (store);
220 }
221
222 static void
223 chatrooms_window_model_add_columns (EmpathyChatroomsWindow *window)
224 {
225         GtkTreeView       *view;
226         GtkTreeModel      *model;
227         GtkTreeViewColumn *column;
228         GtkCellRenderer   *cell;
229         gint               count;
230
231         view = GTK_TREE_VIEW (window->treeview);
232         model = gtk_tree_view_get_model (view);
233
234         gtk_tree_view_set_headers_visible (view, TRUE);
235         gtk_tree_view_set_headers_clickable (view, TRUE);
236
237         /* Name & Status */
238         column = gtk_tree_view_column_new ();
239         count = gtk_tree_view_append_column (view, column);
240
241         gtk_tree_view_column_set_title (column, _("Name"));
242         gtk_tree_view_column_set_expand (column, TRUE);
243         gtk_tree_view_column_set_sort_column_id (column, count - 1);
244
245         cell = gtk_cell_renderer_pixbuf_new ();
246         gtk_tree_view_column_pack_start (column, cell, FALSE);
247         gtk_tree_view_column_add_attribute (column, cell, "icon-name", COL_IMAGE);
248
249         cell = gtk_cell_renderer_text_new ();
250         g_object_set (cell,
251                       "xpad", 4,
252                       "ypad", 1,
253                       NULL);
254         gtk_tree_view_column_pack_start (column, cell, TRUE);
255         gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME);
256
257         /* Room */
258         cell = gtk_cell_renderer_text_new ();
259         column = gtk_tree_view_column_new_with_attributes (_("Room"), cell,
260                                                            "text", COL_ROOM,
261                                                            NULL);
262         count = gtk_tree_view_append_column (view, column);
263         gtk_tree_view_column_set_sort_column_id (column, count - 1);
264
265         /* Chatroom auto connect */
266         cell = gtk_cell_renderer_toggle_new ();
267         column = gtk_tree_view_column_new_with_attributes (_("Auto-Connect"), cell,
268                                                            "active", COL_AUTO_CONNECT,
269                                                            NULL);
270         count = gtk_tree_view_append_column (view, column);
271         gtk_tree_view_column_set_sort_column_id (column, count - 1);
272
273         g_signal_connect (cell, "toggled",
274                           G_CALLBACK (chatrooms_window_model_cell_auto_connect_toggled),
275                           window);
276
277         /* Sort model */
278         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), 0,
279                                               GTK_SORT_ASCENDING);
280 }
281
282 static void
283 chatrooms_window_model_refresh_data (EmpathyChatroomsWindow *window,
284                                      gboolean               first_time)
285 {
286         GtkTreeView           *view;
287         GtkTreeSelection      *selection;
288         GtkTreeModel          *model;
289         GtkListStore          *store;
290         GtkTreeIter            iter;
291         EmpathyAccountChooser  *account_chooser;
292         TpAccount             *account;
293         GList                 *chatrooms, *l;
294
295         view = GTK_TREE_VIEW (window->treeview);
296         selection = gtk_tree_view_get_selection (view);
297         model = gtk_tree_view_get_model (view);
298         store = GTK_LIST_STORE (model);
299
300         /* Look up chatrooms */
301         account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
302         account = empathy_account_chooser_dup_account (account_chooser);
303
304         chatrooms = empathy_chatroom_manager_get_chatrooms (window->manager, account);
305
306         /* Clean out the store */
307         gtk_list_store_clear (store);
308
309         /* Populate with chatroom list. */
310         for (l = chatrooms; l; l = l->next) {
311                 chatrooms_window_model_add (window, l->data,  FALSE);
312         }
313
314         if (gtk_tree_model_get_iter_first (model, &iter)) {
315                 gtk_tree_selection_select_iter (selection, &iter);
316         }
317
318         if (account) {
319                 g_object_unref (account);
320         }
321
322         g_list_free (chatrooms);
323 }
324
325 static void
326 chatrooms_window_model_add (EmpathyChatroomsWindow *window,
327                             EmpathyChatroom        *chatroom,
328                             gboolean               set_active)
329 {
330         GtkTreeView      *view;
331         GtkTreeModel     *model;
332         GtkTreeSelection *selection;
333         GtkListStore     *store;
334         GtkTreeIter       iter;
335
336         view = GTK_TREE_VIEW (window->treeview);
337         selection = gtk_tree_view_get_selection (view);
338         model = gtk_tree_view_get_model (view);
339         store = GTK_LIST_STORE (model);
340
341         gtk_list_store_append (store, &iter);
342         gtk_list_store_set (store, &iter,
343                             COL_NAME, empathy_chatroom_get_name (chatroom),
344                             COL_ROOM, empathy_chatroom_get_room (chatroom),
345                             COL_AUTO_CONNECT, empathy_chatroom_get_auto_connect (chatroom),
346                             COL_POINTER, chatroom,
347                             -1);
348
349         if (set_active) {
350                 gtk_tree_selection_select_iter (selection, &iter);
351         }
352 }
353
354 static void
355 chatrooms_window_model_cell_auto_connect_toggled (GtkCellRendererToggle  *cell,
356                                                   gchar                  *path_string,
357                                                   EmpathyChatroomsWindow  *window)
358 {
359         EmpathyChatroom *chatroom;
360         gboolean        enabled;
361         GtkTreeView    *view;
362         GtkTreeModel   *model;
363         GtkListStore   *store;
364         GtkTreePath    *path;
365         GtkTreeIter     iter;
366
367         view = GTK_TREE_VIEW (window->treeview);
368         model = gtk_tree_view_get_model (view);
369         store = GTK_LIST_STORE (model);
370
371         path = gtk_tree_path_new_from_string (path_string);
372
373         gtk_tree_model_get_iter (model, &iter, path);
374         gtk_tree_model_get (model, &iter,
375                             COL_AUTO_CONNECT, &enabled,
376                             COL_POINTER, &chatroom,
377                             -1);
378
379         enabled = !enabled;
380
381         empathy_chatroom_set_auto_connect (chatroom, enabled);
382
383         gtk_list_store_set (store, &iter, COL_AUTO_CONNECT, enabled, -1);
384         gtk_tree_path_free (path);
385         g_object_unref (chatroom);
386 }
387
388 static void
389 chatrooms_window_button_remove_clicked_cb (GtkWidget             *widget,
390                                            EmpathyChatroomsWindow *window)
391 {
392         EmpathyChatroom        *chatroom;
393         GtkTreeView           *view;
394         GtkTreeModel          *model;
395         GtkTreeSelection      *selection;
396         GtkTreeIter            iter;
397
398         /* Remove from treeview */
399         view = GTK_TREE_VIEW (window->treeview);
400         selection = gtk_tree_view_get_selection (view);
401
402         if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
403                 return;
404         }
405
406         gtk_tree_model_get (model, &iter, COL_POINTER, &chatroom, -1);
407         gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
408
409         /* Remove from config */
410         empathy_chatroom_manager_remove (window->manager, chatroom);
411
412         g_object_unref (chatroom);
413 }
414
415 static void
416 chatrooms_window_button_close_clicked_cb (GtkWidget             *widget,
417                                           EmpathyChatroomsWindow *window)
418 {
419         gtk_widget_destroy (window->window);
420 }
421
422 static void
423 chatrooms_window_chatroom_added_cb (EmpathyChatroomManager *manager,
424                                     EmpathyChatroom        *chatroom,
425                                     EmpathyChatroomsWindow *window)
426 {
427         EmpathyAccountChooser *account_chooser;
428         TpAccount             *account;
429
430         account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
431         account = empathy_account_chooser_dup_account (account_chooser);
432
433         if (!account) {
434                 chatrooms_window_model_add (window, chatroom, FALSE);
435         } else {
436                 if (account == empathy_chatroom_get_account (chatroom)) {
437                         chatrooms_window_model_add (window, chatroom, FALSE);
438                 }
439
440                 g_object_unref (account);
441         }
442 }
443
444 static void
445 chatrooms_window_chatroom_removed_cb (EmpathyChatroomManager *manager,
446                                       EmpathyChatroom        *chatroom,
447                                       EmpathyChatroomsWindow *window)
448 {
449         GtkTreeModel *model;
450
451         model = gtk_tree_view_get_model (GTK_TREE_VIEW (window->treeview));
452
453         gtk_tree_model_foreach (model,
454                                 (GtkTreeModelForeachFunc) chatrooms_window_remove_chatroom_foreach,
455                                 chatroom);
456 }
457
458 static gboolean
459 chatrooms_window_remove_chatroom_foreach (GtkTreeModel   *model,
460                                           GtkTreePath    *path,
461                                           GtkTreeIter    *iter,
462                                           EmpathyChatroom *chatroom)
463 {
464         EmpathyChatroom *this_chatroom;
465
466         gtk_tree_model_get (model, iter, COL_POINTER, &this_chatroom, -1);
467
468         if (empathy_chatroom_equal (chatroom, this_chatroom)) {
469                 gtk_list_store_remove (GTK_LIST_STORE (model), iter);
470                 g_object_unref (this_chatroom);
471                 return TRUE;
472         }
473
474         g_object_unref (this_chatroom);
475
476         return FALSE;
477 }
478
479 static void
480 chatrooms_window_account_changed_cb (GtkWidget             *combo_box,
481                                      EmpathyChatroomsWindow *window)
482 {
483         chatrooms_window_model_refresh_data (window, FALSE);
484 }
485