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