]> git.0d.be Git - empathy.git/blob - src/empathy-chatrooms-window.c
Move modules that make no sense to be used in other applicaton from libempathy-gtk...
[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., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, 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 <glade/glade.h>
33 #include <glib.h>
34 #include <glib/gi18n.h>
35
36 #include <libempathy/empathy-chatroom-manager.h>
37 #include <libempathy/empathy-utils.h>
38
39 #include <libempathy-gtk/empathy-account-chooser.h>
40 #include <libempathy-gtk/empathy-ui-utils.h>
41
42 #include "empathy-chatrooms-window.h"
43 #include "empathy-new-chatroom-dialog.h"
44
45 typedef struct {
46         EmpathyChatroomManager *manager;
47
48         GtkWidget             *window;
49         GtkWidget             *hbox_account;
50         GtkWidget             *label_account;
51         GtkWidget             *account_chooser;
52         GtkWidget             *treeview;
53         GtkWidget             *button_remove;
54         GtkWidget             *button_edit;
55         GtkWidget             *button_close;
56
57         gint                   room_column;
58 } EmpathyChatroomsWindow;
59
60 static void             chatrooms_window_destroy_cb                      (GtkWidget             *widget,
61                                                                           EmpathyChatroomsWindow *window);
62 static void             chatrooms_window_model_setup                     (EmpathyChatroomsWindow *window);
63 static void             chatrooms_window_model_add_columns               (EmpathyChatroomsWindow *window);
64 static void             chatrooms_window_model_refresh_data              (EmpathyChatroomsWindow *window,
65                                                                           gboolean               first_time);
66 static void             chatrooms_window_model_add                       (EmpathyChatroomsWindow *window,
67                                                                           EmpathyChatroom        *chatroom,
68                                                                           gboolean               set_active);
69 static void             chatrooms_window_model_cell_auto_connect_toggled (GtkCellRendererToggle  *cell,
70                                                                           gchar                  *path_string,
71                                                                           EmpathyChatroomsWindow  *window);
72 static EmpathyChatroom * chatrooms_window_model_get_selected              (EmpathyChatroomsWindow *window);
73 static void             chatrooms_window_model_action_selected           (EmpathyChatroomsWindow *window);
74 static void             chatrooms_window_row_activated_cb                (GtkTreeView           *tree_view,
75                                                                           GtkTreePath           *path,
76                                                                           GtkTreeViewColumn     *column,
77                                                                           EmpathyChatroomsWindow *window);
78 static void             chatrooms_window_button_remove_clicked_cb        (GtkWidget             *widget,
79                                                                           EmpathyChatroomsWindow *window);
80 static void             chatrooms_window_button_edit_clicked_cb          (GtkWidget             *widget,
81                                                                           EmpathyChatroomsWindow *window);
82 static void             chatrooms_window_button_close_clicked_cb         (GtkWidget             *widget,
83                                                                           EmpathyChatroomsWindow *window);
84 static void             chatrooms_window_chatroom_added_cb               (EmpathyChatroomManager *manager,
85                                                                           EmpathyChatroom        *chatroom,
86                                                                           EmpathyChatroomsWindow *window);
87 static void             chatrooms_window_chatroom_removed_cb             (EmpathyChatroomManager *manager,
88                                                                           EmpathyChatroom        *chatroom,
89                                                                           EmpathyChatroomsWindow *window);
90 static gboolean         chatrooms_window_remove_chatroom_foreach         (GtkTreeModel          *model,
91                                                                           GtkTreePath           *path,
92                                                                           GtkTreeIter           *iter,
93                                                                           EmpathyChatroom        *chatroom);
94 static void             chatrooms_window_account_changed_cb              (GtkWidget             *combo_box,
95                                                                           EmpathyChatroomsWindow *window);
96
97 enum {
98         COL_IMAGE,
99         COL_NAME,
100         COL_ROOM,
101         COL_AUTO_CONNECT,
102         COL_POINTER,
103         COL_COUNT
104 };
105
106 void
107 empathy_chatrooms_window_show (GtkWindow *parent)
108 {
109         static EmpathyChatroomsWindow *window = NULL;
110         GladeXML                     *glade;
111
112         if (window) {
113                 gtk_window_present (GTK_WINDOW (window->window));
114                 return;
115         }
116
117         window = g_new0 (EmpathyChatroomsWindow, 1);
118
119         glade = empathy_glade_get_file ("empathy-chatrooms-window.glade",
120                                        "chatrooms_window",
121                                        NULL,
122                                        "chatrooms_window", &window->window,
123                                        "hbox_account", &window->hbox_account,
124                                        "label_account", &window->label_account,
125                                        "treeview", &window->treeview,
126                                        "button_edit", &window->button_edit,
127                                        "button_remove", &window->button_remove,
128                                        "button_close", &window->button_close,
129                                        NULL);
130
131         empathy_glade_connect (glade,
132                               window,
133                               "chatrooms_window", "destroy", chatrooms_window_destroy_cb,
134                               "button_remove", "clicked", chatrooms_window_button_remove_clicked_cb,
135                               "button_edit", "clicked", chatrooms_window_button_edit_clicked_cb,
136                               "button_close", "clicked", chatrooms_window_button_close_clicked_cb,
137                               NULL);
138
139         g_object_unref (glade);
140
141         g_object_add_weak_pointer (G_OBJECT (window->window), (gpointer) &window);
142
143         /* Get the session and chat room manager */
144         window->manager = empathy_chatroom_manager_new ();
145
146         g_signal_connect (window->manager, "chatroom-added",
147                           G_CALLBACK (chatrooms_window_chatroom_added_cb),
148                           window);
149         g_signal_connect (window->manager, "chatroom-removed",
150                           G_CALLBACK (chatrooms_window_chatroom_removed_cb),
151                           window);
152
153         /* Account chooser for chat rooms */
154         window->account_chooser = empathy_account_chooser_new ();
155         empathy_account_chooser_set_filter (EMPATHY_ACCOUNT_CHOOSER (window->account_chooser),
156                                             empathy_account_chooser_filter_is_connected,
157                                             NULL);
158         g_object_set (window->account_chooser, 
159                       "has-all-option", TRUE,
160                       NULL);
161         empathy_account_chooser_set_account (EMPATHY_ACCOUNT_CHOOSER (window->account_chooser), NULL);
162
163         gtk_box_pack_start (GTK_BOX (window->hbox_account),
164                             window->account_chooser,
165                             TRUE, TRUE, 0);
166
167         g_signal_connect (window->account_chooser, "changed",
168                           G_CALLBACK (chatrooms_window_account_changed_cb),
169                           window);
170
171         gtk_widget_show (window->account_chooser);
172
173         /* Set up chatrooms */
174         chatrooms_window_model_setup (window);
175
176         /* Set focus */
177         gtk_widget_grab_focus (window->treeview);
178
179         /* Last touches */
180         if (parent) {
181                 gtk_window_set_transient_for (GTK_WINDOW (window->window),
182                                               GTK_WINDOW (parent));
183         }
184
185         gtk_widget_show (window->window);
186 }
187
188 static void
189 chatrooms_window_destroy_cb (GtkWidget             *widget,
190                              EmpathyChatroomsWindow *window)
191 {
192         g_signal_handlers_disconnect_by_func (window->manager,
193                                               chatrooms_window_chatroom_added_cb,
194                                               window);
195         g_signal_handlers_disconnect_by_func (window->manager,
196                                               chatrooms_window_chatroom_removed_cb,
197                                               window);
198         g_object_unref (window->manager);
199         g_free (window);
200 }
201
202 static void
203 chatrooms_window_model_setup (EmpathyChatroomsWindow *window)
204 {
205         GtkTreeView      *view;
206         GtkListStore     *store;
207         GtkTreeSelection *selection;
208
209         /* View */
210         view = GTK_TREE_VIEW (window->treeview);
211
212         g_signal_connect (view, "row-activated",
213                           G_CALLBACK (chatrooms_window_row_activated_cb),
214                           window);
215
216         /* Store */
217         store = gtk_list_store_new (COL_COUNT,
218                                     G_TYPE_STRING,         /* Image */
219                                     G_TYPE_STRING,         /* Name */
220                                     G_TYPE_STRING,         /* Room */
221                                     G_TYPE_BOOLEAN,        /* Auto start */
222                                     EMPATHY_TYPE_CHATROOM); /* Chatroom */
223
224         gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
225
226         /* Selection */ 
227         selection = gtk_tree_view_get_selection (view);
228         gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
229
230         /* Columns */
231         chatrooms_window_model_add_columns (window);
232
233         /* Add data */
234         chatrooms_window_model_refresh_data (window, TRUE);
235
236         /* Clean up */
237         g_object_unref (store);
238 }
239
240 static void
241 chatrooms_window_model_add_columns (EmpathyChatroomsWindow *window)
242 {
243         GtkTreeView       *view;
244         GtkTreeModel      *model;
245         GtkTreeViewColumn *column;
246         GtkCellRenderer   *cell;
247         gint               count;
248
249         view = GTK_TREE_VIEW (window->treeview);
250         model = gtk_tree_view_get_model (view);
251
252         gtk_tree_view_set_headers_visible (view, TRUE);
253         gtk_tree_view_set_headers_clickable (view, TRUE);
254
255         /* Name & Status */
256         column = gtk_tree_view_column_new ();
257         count = gtk_tree_view_append_column (view, column);
258
259         gtk_tree_view_column_set_title (column, _("Name"));
260         gtk_tree_view_column_set_expand (column, TRUE);
261         gtk_tree_view_column_set_sort_column_id (column, count - 1);
262
263         cell = gtk_cell_renderer_pixbuf_new ();
264         gtk_tree_view_column_pack_start (column, cell, FALSE);
265         gtk_tree_view_column_add_attribute (column, cell, "icon-name", COL_IMAGE);
266
267         cell = gtk_cell_renderer_text_new ();
268         g_object_set (cell,
269                       "xpad", 4,
270                       "ypad", 1,
271                       NULL);
272         gtk_tree_view_column_pack_start (column, cell, TRUE);
273         gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME);
274
275         /* Room */
276         cell = gtk_cell_renderer_text_new ();
277         column = gtk_tree_view_column_new_with_attributes (_("Room"), cell, 
278                                                            "text", COL_ROOM, 
279                                                            NULL);
280         count = gtk_tree_view_append_column (view, column);
281         gtk_tree_view_column_set_sort_column_id (column, count - 1);
282         window->room_column = count - 1;
283
284         /* Chatroom auto connect */
285         cell = gtk_cell_renderer_toggle_new ();
286         column = gtk_tree_view_column_new_with_attributes (_("Auto Connect"), cell,
287                                                            "active", COL_AUTO_CONNECT,
288                                                            NULL);
289         count = gtk_tree_view_append_column (view, column);
290         gtk_tree_view_column_set_sort_column_id (column, count - 1);
291
292         g_signal_connect (cell, "toggled",
293                           G_CALLBACK (chatrooms_window_model_cell_auto_connect_toggled),
294                           window);
295
296         /* Sort model */
297         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), 0, 
298                                               GTK_SORT_ASCENDING);
299 }
300
301 static void
302 chatrooms_window_model_refresh_data (EmpathyChatroomsWindow *window,
303                                      gboolean               first_time)
304 {
305         GtkTreeView           *view;
306         GtkTreeSelection      *selection;
307         GtkTreeModel          *model;
308         GtkListStore          *store;
309         GtkTreeIter            iter;
310         GtkTreeViewColumn     *column;
311         EmpathyAccountChooser  *account_chooser;
312         McAccount             *account;
313         GList                 *chatrooms, *l;
314
315         view = GTK_TREE_VIEW (window->treeview);
316         selection = gtk_tree_view_get_selection (view);
317         model = gtk_tree_view_get_model (view);
318         store = GTK_LIST_STORE (model);
319
320         /* Look up chatrooms */
321         account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
322         account = empathy_account_chooser_get_account (account_chooser);
323
324         chatrooms = empathy_chatroom_manager_get_chatrooms (window->manager, account);
325
326         /* Sort out columns, we only show the server column for
327          * selected protocol types, such as Jabber. 
328          */
329         if (account) {
330                 column = gtk_tree_view_get_column (view, window->room_column);
331                 gtk_tree_view_column_set_visible (column, TRUE);
332         } else {
333                 column = gtk_tree_view_get_column (view, window->room_column);
334                 gtk_tree_view_column_set_visible (column, FALSE);
335         }
336
337         /* Clean out the store */
338         gtk_list_store_clear (store);
339
340         /* Populate with chatroom list. */
341         for (l = chatrooms; l; l = l->next) {
342                 chatrooms_window_model_add (window, l->data,  FALSE);
343         }
344
345         if (gtk_tree_model_get_iter_first (model, &iter)) {
346                 gtk_tree_selection_select_iter (selection, &iter);
347         }
348
349         if (account) {
350                 g_object_unref (account);
351         }
352
353         g_list_free (chatrooms);
354 }
355
356 static void
357 chatrooms_window_model_add (EmpathyChatroomsWindow *window,
358                             EmpathyChatroom        *chatroom,
359                             gboolean               set_active)
360 {
361         GtkTreeView      *view;
362         GtkTreeModel     *model;
363         GtkTreeSelection *selection;
364         GtkListStore     *store;
365         GtkTreeIter       iter;
366
367         view = GTK_TREE_VIEW (window->treeview);
368         selection = gtk_tree_view_get_selection (view);
369         model = gtk_tree_view_get_model (view);
370         store = GTK_LIST_STORE (model);
371
372         gtk_list_store_append (store, &iter);
373         gtk_list_store_set (store, &iter,
374                             COL_NAME, empathy_chatroom_get_name (chatroom),
375                             COL_ROOM, empathy_chatroom_get_room (chatroom),
376                             COL_AUTO_CONNECT, empathy_chatroom_get_auto_connect (chatroom),
377                             COL_POINTER, chatroom,
378                             -1);
379
380         if (set_active) {
381                 gtk_tree_selection_select_iter (selection, &iter);
382         }
383 }
384
385 static void
386 chatrooms_window_model_cell_auto_connect_toggled (GtkCellRendererToggle  *cell,
387                                                   gchar                  *path_string,
388                                                   EmpathyChatroomsWindow  *window)
389 {
390         EmpathyChatroom *chatroom;
391         gboolean        enabled;
392         GtkTreeView    *view;
393         GtkTreeModel   *model;
394         GtkListStore   *store;
395         GtkTreePath    *path;
396         GtkTreeIter     iter;
397
398         view = GTK_TREE_VIEW (window->treeview);
399         model = gtk_tree_view_get_model (view);
400         store = GTK_LIST_STORE (model);
401
402         path = gtk_tree_path_new_from_string (path_string);
403
404         gtk_tree_model_get_iter (model, &iter, path);
405         gtk_tree_model_get (model, &iter,
406                             COL_AUTO_CONNECT, &enabled,
407                             COL_POINTER, &chatroom,
408                             -1);
409
410         enabled = !enabled;
411
412         empathy_chatroom_set_auto_connect (chatroom, enabled);
413         empathy_chatroom_manager_store (window->manager);
414
415         gtk_list_store_set (store, &iter, COL_AUTO_CONNECT, enabled, -1);
416         gtk_tree_path_free (path);
417         g_object_unref (chatroom);
418 }
419
420 static EmpathyChatroom *
421 chatrooms_window_model_get_selected (EmpathyChatroomsWindow *window)
422 {
423         GtkTreeView      *view;
424         GtkTreeModel     *model;
425         GtkTreeSelection *selection;
426         GtkTreeIter       iter;
427         EmpathyChatroom   *chatroom = NULL;
428
429         view = GTK_TREE_VIEW (window->treeview);
430         selection = gtk_tree_view_get_selection (view);
431
432         if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
433                 gtk_tree_model_get (model, &iter, COL_POINTER, &chatroom, -1);
434         }
435
436         return chatroom;
437 }
438
439 static void
440 chatrooms_window_model_action_selected (EmpathyChatroomsWindow *window)
441 {
442         EmpathyChatroom *chatroom;
443         GtkTreeView    *view;
444         GtkTreeModel   *model;
445
446         view = GTK_TREE_VIEW (window->treeview);
447         model = gtk_tree_view_get_model (view);
448
449         chatroom = chatrooms_window_model_get_selected (window);
450         if (!chatroom) {
451                 return;
452         }
453
454         //empathy_edit_chatroom_dialog_show (GTK_WINDOW (window->window), chatroom);
455
456         g_object_unref (chatroom);
457 }
458
459 static void
460 chatrooms_window_row_activated_cb (GtkTreeView           *tree_view,
461                                    GtkTreePath           *path,
462                                    GtkTreeViewColumn     *column,
463                                    EmpathyChatroomsWindow *window)
464 {
465         if (GTK_WIDGET_IS_SENSITIVE (window->button_edit)) {
466                 chatrooms_window_model_action_selected (window);
467         }
468 }
469
470 static void
471 chatrooms_window_button_remove_clicked_cb (GtkWidget             *widget,
472                                            EmpathyChatroomsWindow *window)
473 {
474         EmpathyChatroom        *chatroom;
475         GtkTreeView           *view;
476         GtkTreeModel          *model;
477         GtkTreeSelection      *selection;
478         GtkTreeIter            iter;
479
480         /* Remove from treeview */
481         view = GTK_TREE_VIEW (window->treeview);
482         selection = gtk_tree_view_get_selection (view);
483
484         if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
485                 return;
486         }
487
488         gtk_tree_model_get (model, &iter, COL_POINTER, &chatroom, -1);
489         gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
490
491         /* Remove from config */
492         empathy_chatroom_manager_remove (window->manager, chatroom);
493
494         g_object_unref (chatroom);
495 }
496
497 static void
498 chatrooms_window_button_edit_clicked_cb (GtkWidget             *widget,
499                                          EmpathyChatroomsWindow *window)
500 {
501         EmpathyChatroom *chatroom;
502
503         chatroom = chatrooms_window_model_get_selected (window);
504         if (!chatroom) {
505                 return;
506         }
507
508         //empathy_edit_chatroom_dialog_show (GTK_WINDOW (window->window), chatroom);
509
510         g_object_unref (chatroom);
511 }
512
513 static void
514 chatrooms_window_button_close_clicked_cb (GtkWidget             *widget,
515                                           EmpathyChatroomsWindow *window)
516 {
517         gtk_widget_destroy (window->window);
518 }
519
520 static void
521 chatrooms_window_chatroom_added_cb (EmpathyChatroomManager *manager,
522                                     EmpathyChatroom        *chatroom,
523                                     EmpathyChatroomsWindow *window)
524 {
525         EmpathyAccountChooser *account_chooser;
526         McAccount            *account;
527
528         account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
529         account = empathy_account_chooser_get_account (account_chooser);
530
531         if (!account) {
532                 chatrooms_window_model_add (window, chatroom, FALSE);
533         } else {
534                 if (empathy_account_equal (account, empathy_chatroom_get_account (chatroom))) {
535                         chatrooms_window_model_add (window, chatroom, FALSE);
536                 }
537
538                 g_object_unref (account);
539         }
540 }
541
542 static void
543 chatrooms_window_chatroom_removed_cb (EmpathyChatroomManager *manager,
544                                       EmpathyChatroom        *chatroom,
545                                       EmpathyChatroomsWindow *window)
546 {
547         GtkTreeModel *model;
548
549         model = gtk_tree_view_get_model (GTK_TREE_VIEW (window->treeview));
550
551         gtk_tree_model_foreach (model,
552                                 (GtkTreeModelForeachFunc) chatrooms_window_remove_chatroom_foreach,
553                                 chatroom);
554 }
555
556 static gboolean
557 chatrooms_window_remove_chatroom_foreach (GtkTreeModel   *model,
558                                           GtkTreePath    *path,
559                                           GtkTreeIter    *iter,
560                                           EmpathyChatroom *chatroom)
561 {
562         EmpathyChatroom *this_chatroom;
563
564         gtk_tree_model_get (model, iter, COL_POINTER, &this_chatroom, -1);
565
566         if (empathy_chatroom_equal (chatroom, this_chatroom)) {
567                 gtk_list_store_remove (GTK_LIST_STORE (model), iter);
568                 g_object_unref (this_chatroom);
569                 return TRUE;
570         }
571
572         g_object_unref (this_chatroom);
573
574         return FALSE;
575 }
576
577 static void
578 chatrooms_window_account_changed_cb (GtkWidget             *combo_box,
579                                      EmpathyChatroomsWindow *window)
580 {
581         chatrooms_window_model_refresh_data (window, FALSE);
582 }
583