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