]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-new-chatroom-dialog.c
Updatre python binding
[empathy.git] / libempathy-gtk / empathy-new-chatroom-dialog.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2006-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: Martyn Russell <martyn@imendio.com>
22  *          Xavier Claessens <xclaesse@gmail.com>
23  */
24
25 #include "config.h"
26
27 #include <string.h>
28 #include <stdio.h>
29
30 #include <gtk/gtk.h>
31 #include <glade/glade.h>
32 #include <glib.h>
33 #include <glib/gi18n.h>
34
35 #include <libmissioncontrol/mission-control.h>
36 #include <libmissioncontrol/mc-account.h>
37 #include <libmissioncontrol/mc-profile.h>
38
39 #include <libempathy/empathy-tp-roomlist.h>
40 #include <libempathy/empathy-chatroom.h>
41 #include <libempathy/empathy-utils.h>
42 #include <libempathy/empathy-debug.h>
43
44 #include "empathy-new-chatroom-dialog.h"
45 #include "empathy-account-chooser.h"
46 #include "empathy-ui-utils.h"
47 #include "ephy-spinner.h"
48
49 #define DEBUG_DOMAIN "NewChatroomDialog"
50
51 typedef struct {
52         EmpathyTpRoomlist *room_list;
53
54         GtkWidget         *window;
55         GtkWidget         *vbox_widgets;
56         GtkWidget         *table_info;
57         GtkWidget         *label_account;
58         GtkWidget         *account_chooser;
59         GtkWidget         *label_server;
60         GtkWidget         *entry_server;
61         GtkWidget         *togglebutton_refresh;
62         GtkWidget         *label_room;
63         GtkWidget         *entry_room;
64         GtkWidget         *vbox_browse;
65         GtkWidget         *image_status;
66         GtkWidget         *label_status;
67         GtkWidget         *hbox_status;
68         GtkWidget         *throbber;
69         GtkWidget         *treeview;
70         GtkTreeModel      *model;
71         GtkWidget         *button_join;
72         GtkWidget         *button_close;
73 } EmpathyNewChatroomDialog;
74
75 enum {
76         COL_NAME,
77         COL_ROOM,
78         COL_COUNT
79 };
80
81 static void     new_chatroom_dialog_response_cb                     (GtkWidget               *widget,
82                                                                      gint                     response,
83                                                                      EmpathyNewChatroomDialog *dialog);
84 static void     new_chatroom_dialog_destroy_cb                      (GtkWidget               *widget,
85                                                                      EmpathyNewChatroomDialog *dialog);
86 static void     new_chatroom_dialog_model_setup                     (EmpathyNewChatroomDialog *dialog);
87 static void     new_chatroom_dialog_model_add_columns               (EmpathyNewChatroomDialog *dialog);
88 static void     new_chatroom_dialog_update_widgets                  (EmpathyNewChatroomDialog *dialog);
89 static void     new_chatroom_dialog_account_changed_cb              (GtkComboBox              *combobox,
90                                                                      EmpathyNewChatroomDialog *dialog);
91 static void     new_chatroom_dialog_roomlist_destroy_cb             (EmpathyTpRoomlist        *room_list,
92                                                                      EmpathyNewChatroomDialog *dialog);
93 static void     new_chatroom_dialog_new_room_cb                     (EmpathyTpRoomlist        *room_list,
94                                                                      EmpathyChatroom          *chatroom,
95                                                                      EmpathyNewChatroomDialog *dialog);
96 static void     new_chatroom_dialog_listing_cb                      (EmpathyTpRoomlist        *room_list,
97                                                                      gboolean                  listing,
98                                                                      EmpathyNewChatroomDialog *dialog);
99 static void     new_chatroom_dialog_model_clear                     (EmpathyNewChatroomDialog *dialog);
100 static void     new_chatroom_dialog_model_row_activated_cb          (GtkTreeView             *tree_view,
101                                                                      GtkTreePath             *path,
102                                                                      GtkTreeViewColumn       *column,
103                                                                      EmpathyNewChatroomDialog *dialog);
104 static void     new_chatroom_dialog_model_selection_changed         (GtkTreeSelection        *selection,
105                                                                      EmpathyNewChatroomDialog *dialog);
106 static void     new_chatroom_dialog_join                            (EmpathyNewChatroomDialog *dialog);
107 static void     new_chatroom_dialog_entry_changed_cb                (GtkWidget               *entry,
108                                                                      EmpathyNewChatroomDialog *dialog);
109 static void     new_chatroom_dialog_browse_start                    (EmpathyNewChatroomDialog *dialog);
110 static void     new_chatroom_dialog_browse_stop                     (EmpathyNewChatroomDialog *dialog);
111 static void     new_chatroom_dialog_entry_server_activate_cb        (GtkWidget               *widget,
112                                                                      EmpathyNewChatroomDialog *dialog);
113 static void     new_chatroom_dialog_togglebutton_refresh_toggled_cb (GtkWidget               *widget,
114                                                                      EmpathyNewChatroomDialog *dialog);
115
116 static EmpathyNewChatroomDialog *dialog_p = NULL;
117
118 void
119 empathy_new_chatroom_dialog_show (GtkWindow *parent)
120 {
121         EmpathyNewChatroomDialog *dialog;
122         GladeXML                 *glade;
123         GtkSizeGroup             *size_group;
124
125         if (dialog_p) {
126                 gtk_window_present (GTK_WINDOW (dialog_p->window));
127                 return;
128         }
129
130         dialog_p = dialog = g_new0 (EmpathyNewChatroomDialog, 1);
131
132         glade = empathy_glade_get_file ("empathy-new-chatroom-dialog.glade",
133                                        "new_chatroom_dialog",
134                                        NULL,
135                                        "new_chatroom_dialog", &dialog->window,
136                                        "table_info", &dialog->table_info,
137                                        "label_account", &dialog->label_account,
138                                        "label_server", &dialog->label_server,
139                                        "label_room", &dialog->label_room,
140                                        "entry_server", &dialog->entry_server,
141                                        "entry_room", &dialog->entry_room,
142                                        "togglebutton_refresh", &dialog->togglebutton_refresh,
143                                        "vbox_browse", &dialog->vbox_browse,
144                                        "image_status", &dialog->image_status,
145                                        "label_status", &dialog->label_status,
146                                        "hbox_status", &dialog->hbox_status,
147                                        "treeview", &dialog->treeview,
148                                        "button_join", &dialog->button_join,
149                                        NULL);
150
151         empathy_glade_connect (glade,
152                               dialog,
153                               "new_chatroom_dialog", "response", new_chatroom_dialog_response_cb,
154                               "new_chatroom_dialog", "destroy", new_chatroom_dialog_destroy_cb,
155                               "entry_server", "changed", new_chatroom_dialog_entry_changed_cb,
156                               "entry_server", "activate", new_chatroom_dialog_entry_server_activate_cb,
157                               "entry_room", "changed", new_chatroom_dialog_entry_changed_cb,
158                               "togglebutton_refresh", "toggled", new_chatroom_dialog_togglebutton_refresh_toggled_cb,
159                               NULL);
160
161         g_object_unref (glade);
162
163         g_object_add_weak_pointer (G_OBJECT (dialog->window), (gpointer) &dialog_p);
164
165         /* Label alignment */
166         size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
167
168         gtk_size_group_add_widget (size_group, dialog->label_account);
169         gtk_size_group_add_widget (size_group, dialog->label_server);
170         gtk_size_group_add_widget (size_group, dialog->label_room);
171
172         g_object_unref (size_group);
173
174         /* Set up chatrooms treeview */
175         new_chatroom_dialog_model_setup (dialog);
176
177         /* Add throbber */
178         dialog->throbber = ephy_spinner_new ();
179         ephy_spinner_set_size (EPHY_SPINNER (dialog->throbber), GTK_ICON_SIZE_LARGE_TOOLBAR);
180         gtk_widget_show (dialog->throbber);
181
182         gtk_box_pack_start (GTK_BOX (dialog->hbox_status), dialog->throbber, 
183                             FALSE, FALSE, 0);
184
185         /* Account chooser for custom */
186         dialog->account_chooser = empathy_account_chooser_new ();
187         empathy_account_chooser_set_filter (EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser),
188                                             empathy_account_chooser_filter_is_connected,
189                                             NULL);
190         gtk_table_attach_defaults (GTK_TABLE (dialog->table_info),
191                                    dialog->account_chooser,
192                                    1, 3, 0, 1);
193         gtk_widget_show (dialog->account_chooser);
194
195         g_signal_connect (GTK_COMBO_BOX (dialog->account_chooser), "changed",
196                           G_CALLBACK (new_chatroom_dialog_account_changed_cb),
197                           dialog);
198         new_chatroom_dialog_account_changed_cb (GTK_COMBO_BOX (dialog->account_chooser),
199                                                 dialog);
200
201         if (parent) {
202                 gtk_window_set_transient_for (GTK_WINDOW (dialog->window),
203                                               GTK_WINDOW (parent));
204         }
205
206         gtk_widget_show (dialog->window);
207 }
208
209 static void
210 new_chatroom_dialog_response_cb (GtkWidget               *widget,
211                                  gint                     response,
212                                  EmpathyNewChatroomDialog *dialog)
213 {
214         if (response == GTK_RESPONSE_OK) {
215                 new_chatroom_dialog_join (dialog);
216         }
217
218         gtk_widget_destroy (widget);
219 }
220
221 static void
222 new_chatroom_dialog_destroy_cb (GtkWidget               *widget,
223                                 EmpathyNewChatroomDialog *dialog)
224 {
225         if (dialog->room_list) {
226                 g_object_unref (dialog->room_list);
227         }
228         g_object_unref (dialog->model);  
229
230         g_free (dialog);
231 }
232
233 static void
234 new_chatroom_dialog_model_setup (EmpathyNewChatroomDialog *dialog)
235 {
236         GtkTreeView      *view;
237         GtkListStore     *store;
238         GtkTreeSelection *selection;
239
240         /* View */
241         view = GTK_TREE_VIEW (dialog->treeview);
242
243         g_signal_connect (view, "row-activated",
244                           G_CALLBACK (new_chatroom_dialog_model_row_activated_cb),
245                           dialog);
246
247         /* Store/Model */
248         store = gtk_list_store_new (COL_COUNT,
249                                     G_TYPE_STRING,       /* Image */
250                                     G_TYPE_STRING,       /* Text */
251                                     G_TYPE_STRING);      /* Room */
252
253         dialog->model = GTK_TREE_MODEL (store);
254         gtk_tree_view_set_model (view, dialog->model);
255
256         /* Selection */
257         selection = gtk_tree_view_get_selection (view);
258         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
259                                               COL_NAME, GTK_SORT_ASCENDING);
260
261         g_signal_connect (selection, "changed",
262                           G_CALLBACK (new_chatroom_dialog_model_selection_changed),
263                           dialog);
264
265         /* Columns */
266         new_chatroom_dialog_model_add_columns (dialog);
267 }
268
269 static void
270 new_chatroom_dialog_model_add_columns (EmpathyNewChatroomDialog *dialog)
271 {
272         GtkTreeView       *view;
273         GtkTreeViewColumn *column;
274         GtkCellRenderer   *cell;
275
276         view = GTK_TREE_VIEW (dialog->treeview);
277         gtk_tree_view_set_headers_visible (view, FALSE);
278
279         cell = gtk_cell_renderer_text_new ();
280         g_object_set (cell,
281                       "xpad", (guint) 4,
282                       "ypad", (guint) 1,
283                       "ellipsize", PANGO_ELLIPSIZE_END,
284                       NULL);
285
286         column = gtk_tree_view_column_new_with_attributes (_("Chat Rooms"),
287                                                            cell,
288                                                            "text", COL_NAME,
289                                                            NULL);
290
291         gtk_tree_view_column_set_expand (column, TRUE);
292         gtk_tree_view_append_column (view, column);
293 }
294
295 static void
296 new_chatroom_dialog_update_widgets (EmpathyNewChatroomDialog *dialog)
297 {
298         EmpathyAccountChooser *account_chooser;
299         McAccount             *account;
300         McProfile             *profile;
301         const gchar           *protocol;
302         const gchar           *room;
303         
304         account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
305         account = empathy_account_chooser_get_account (account_chooser);
306         profile = mc_account_get_profile (account);
307         protocol = mc_profile_get_protocol_name (profile);
308
309         gtk_entry_set_text (GTK_ENTRY (dialog->entry_server), "");
310
311         /* hardcode here known protocols */
312         if (strcmp (protocol, "jabber") == 0) {
313                 gtk_widget_set_sensitive (dialog->entry_server, TRUE);
314                 gtk_widget_show (dialog->vbox_browse);
315
316         }
317         else if (strcmp (protocol, "local-xmpp") == 0) {
318                 gtk_widget_set_sensitive (dialog->entry_server, FALSE);
319                 gtk_widget_show (dialog->vbox_browse);          
320         }
321         else if (strcmp (protocol, "irc") == 0) {
322                 gtk_widget_set_sensitive (dialog->entry_server, FALSE);
323                 gtk_widget_show (dialog->vbox_browse);          
324         } else {
325                 gtk_widget_set_sensitive (dialog->entry_server, TRUE);
326                 gtk_widget_show (dialog->vbox_browse);
327         }
328
329         room = gtk_entry_get_text (GTK_ENTRY (dialog->entry_room));
330         gtk_widget_set_sensitive (dialog->button_join, !G_STR_EMPTY (room));
331
332         /* Final set up of the dialog */
333         gtk_widget_grab_focus (dialog->entry_room);
334
335         g_object_unref (account);
336         g_object_unref (profile);
337 }
338
339 static void
340 new_chatroom_dialog_account_changed_cb (GtkComboBox             *combobox,
341                                         EmpathyNewChatroomDialog *dialog)
342 {
343         EmpathyAccountChooser *account_chooser;
344         McAccount             *account;
345         gboolean               listing = FALSE;
346
347         if (dialog->room_list) {
348                 g_object_unref (dialog->room_list);
349         }
350
351         ephy_spinner_stop (EPHY_SPINNER (dialog->throbber));
352         new_chatroom_dialog_model_clear (dialog);
353
354         account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
355         account = empathy_account_chooser_get_account (account_chooser);
356         dialog->room_list = empathy_tp_roomlist_new (account);
357
358         if (dialog->room_list)  {
359                 g_signal_connect (dialog->room_list, "destroy",
360                                   G_CALLBACK (new_chatroom_dialog_roomlist_destroy_cb),
361                                   dialog);
362                 g_signal_connect (dialog->room_list, "new-room",
363                                   G_CALLBACK (new_chatroom_dialog_new_room_cb),
364                                   dialog);
365                 g_signal_connect (dialog->room_list, "listing",
366                                   G_CALLBACK (new_chatroom_dialog_listing_cb),
367                                   dialog);
368
369                 listing = empathy_tp_roomlist_is_listing (dialog->room_list);
370                 if (listing) {
371                         ephy_spinner_start (EPHY_SPINNER (dialog->throbber));
372                 }
373         }
374
375         new_chatroom_dialog_update_widgets (dialog);
376 }
377
378 static void
379 new_chatroom_dialog_roomlist_destroy_cb (EmpathyTpRoomlist        *room_list,
380                                          EmpathyNewChatroomDialog *dialog)
381 {
382         g_object_unref (dialog->room_list);
383         dialog->room_list = NULL;
384 }
385
386 static void
387 new_chatroom_dialog_new_room_cb (EmpathyTpRoomlist        *room_list,
388                                  EmpathyChatroom          *chatroom,
389                                  EmpathyNewChatroomDialog *dialog)
390 {
391         GtkTreeView      *view;
392         GtkTreeSelection *selection;
393         GtkListStore     *store;
394         GtkTreeIter       iter;
395
396         empathy_debug (DEBUG_DOMAIN, "New chatroom listed: %s (%s)",
397                        empathy_chatroom_get_name (chatroom),
398                        empathy_chatroom_get_room (chatroom));
399
400         /* Add to model */
401         view = GTK_TREE_VIEW (dialog->treeview);
402         selection = gtk_tree_view_get_selection (view);
403         store = GTK_LIST_STORE (dialog->model);
404
405         gtk_list_store_append (store, &iter);
406         gtk_list_store_set (store, &iter,
407                             COL_NAME, empathy_chatroom_get_name (chatroom),
408                             COL_ROOM, empathy_chatroom_get_room (chatroom),
409                             -1);
410 }
411
412 static void
413 new_chatroom_dialog_listing_cb (EmpathyTpRoomlist        *room_list,
414                                 gboolean                  listing,
415                                 EmpathyNewChatroomDialog *dialog)
416 {
417         /* Update the throbber */
418         if (listing) {
419                 ephy_spinner_start (EPHY_SPINNER (dialog->throbber));           
420         } else {
421                 ephy_spinner_stop (EPHY_SPINNER (dialog->throbber));
422         }
423
424         /* Update the refresh toggle button */
425         g_signal_handlers_block_by_func (dialog->togglebutton_refresh,
426                                          new_chatroom_dialog_togglebutton_refresh_toggled_cb,
427                                          dialog);
428         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->togglebutton_refresh),
429                                       listing);
430         g_signal_handlers_unblock_by_func (dialog->togglebutton_refresh,
431                                            new_chatroom_dialog_togglebutton_refresh_toggled_cb,
432                                            dialog);
433 }
434
435 static void
436 new_chatroom_dialog_model_clear (EmpathyNewChatroomDialog *dialog)
437 {
438         GtkListStore *store;
439
440         store = GTK_LIST_STORE (dialog->model);
441         gtk_list_store_clear (store);
442 }
443
444 static void
445 new_chatroom_dialog_model_row_activated_cb (GtkTreeView             *tree_view,
446                                             GtkTreePath             *path,
447                                             GtkTreeViewColumn       *column,
448                                             EmpathyNewChatroomDialog *dialog)
449 {
450         gtk_widget_activate (dialog->button_join);
451 }
452
453 static void
454 new_chatroom_dialog_model_selection_changed (GtkTreeSelection         *selection,
455                                              EmpathyNewChatroomDialog *dialog)
456 {       
457         GtkTreeModel *model;
458         GtkTreeIter   iter;
459         gchar        *room = NULL;
460         gchar        *server = NULL;
461
462         if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
463                 return;
464         }
465
466         gtk_tree_model_get (model, &iter, COL_ROOM, &room, -1);
467         server = strstr (room, "@");
468         if (server) {
469                 *server = '\0';
470                 server++;
471         }
472
473         gtk_entry_set_text (GTK_ENTRY (dialog->entry_server), server ? server : "");
474         gtk_entry_set_text (GTK_ENTRY (dialog->entry_room), room ? room : "");
475
476         g_free (room);
477 }
478
479 static void
480 new_chatroom_dialog_join (EmpathyNewChatroomDialog *dialog)
481 {
482         McAccount            *account;
483         EmpathyAccountChooser *account_chooser;
484         MissionControl       *mc;
485         const gchar          *room;
486         const gchar          *server = NULL;
487         gchar                *room_name = NULL;
488
489         room = gtk_entry_get_text (GTK_ENTRY (dialog->entry_room));
490         server = gtk_entry_get_text (GTK_ENTRY (dialog->entry_server));
491
492         account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
493         account = empathy_account_chooser_get_account (account_chooser);
494
495         if (!G_STR_EMPTY (server)) {
496                 room_name = g_strconcat (room, "@", server, NULL);
497         } else {
498                 room_name = g_strdup (room);
499         }
500
501         empathy_debug (DEBUG_DOMAIN, "Requesting channel for '%s'", room_name);
502
503         mc = empathy_mission_control_new ();
504         mission_control_request_channel_with_string_handle (mc,
505                                                             account,
506                                                             TP_IFACE_CHANNEL_TYPE_TEXT,
507                                                             room_name,
508                                                             TP_HANDLE_TYPE_ROOM,
509                                                             NULL, NULL);        
510         g_free (room_name);
511         g_object_unref (mc);
512 }
513
514 static void
515 new_chatroom_dialog_entry_changed_cb (GtkWidget                *entry,
516                                       EmpathyNewChatroomDialog *dialog)
517 {
518         if (entry == dialog->entry_room) {
519                 const gchar *room;
520
521                 room = gtk_entry_get_text (GTK_ENTRY (dialog->entry_room));
522                 gtk_widget_set_sensitive (dialog->button_join, !G_STR_EMPTY (room));
523                 /* FIXME: Select the room in the list */
524         }
525 }
526
527 static void
528 new_chatroom_dialog_browse_start (EmpathyNewChatroomDialog *dialog)
529 {
530         new_chatroom_dialog_model_clear (dialog);
531         if (dialog->room_list) {
532                 empathy_tp_roomlist_start (dialog->room_list);
533         }
534 }
535
536 static void
537 new_chatroom_dialog_browse_stop (EmpathyNewChatroomDialog *dialog)
538 {
539         if (dialog->room_list) {
540                 empathy_tp_roomlist_stop (dialog->room_list);
541         }
542 }
543
544 static void
545 new_chatroom_dialog_entry_server_activate_cb (GtkWidget                *widget,
546                                               EmpathyNewChatroomDialog  *dialog)
547 {
548         new_chatroom_dialog_togglebutton_refresh_toggled_cb (dialog->togglebutton_refresh, 
549                                                              dialog);
550 }
551
552 static void
553 new_chatroom_dialog_togglebutton_refresh_toggled_cb (GtkWidget               *widget,
554                                                      EmpathyNewChatroomDialog *dialog)
555 {
556         gboolean toggled;
557
558         toggled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
559         
560         if (toggled) {
561                 new_chatroom_dialog_browse_start (dialog);
562         } else {
563                 new_chatroom_dialog_browse_stop (dialog);
564         }
565 }
566