]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-irc-network-dialog.c
Use a flat namespace for internal includes
[empathy.git] / libempathy-gtk / empathy-irc-network-dialog.c
1 /*
2  * Copyright (C) 2007-2008 Guillaume Desmottes
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Authors: Guillaume Desmottes <gdesmott@gnome.org>
19  */
20
21 #include "config.h"
22
23 #include <glib/gi18n-lib.h>
24
25 #include "empathy-utils.h"
26
27 #include "empathy-ui-utils.h"
28 #include "totem-subtitle-encoding.h"
29
30 #include "empathy-irc-network-dialog.h"
31
32 typedef struct {
33   EmpathyIrcNetwork *network;
34
35   GtkWidget *dialog;
36   GtkWidget *button_close;
37
38   GtkWidget *entry_network;
39   GtkWidget *combobox_charset;
40
41   GtkWidget *treeview_servers;
42   GtkWidget *button_add;
43   GtkWidget *button_remove;
44   GtkWidget *button_up;
45   GtkWidget *button_down;
46 } EmpathyIrcNetworkDialog;
47
48 static void
49 irc_network_dialog_destroy_cb (GtkWidget *widget,
50                                EmpathyIrcNetworkDialog *dialog)
51 {
52   g_object_unref (dialog->network);
53
54   g_slice_free (EmpathyIrcNetworkDialog, dialog);
55 }
56
57 static void
58 irc_network_dialog_close_clicked_cb (GtkWidget *widget,
59                                      EmpathyIrcNetworkDialog *dialog)
60 {
61   gtk_widget_destroy (dialog->dialog);
62 }
63
64 enum {
65   COL_SRV_OBJ,
66   COL_ADR,
67   COL_PORT,
68   COL_SSL
69 };
70
71 static void
72 add_server_to_store (GtkListStore *store,
73                      EmpathyIrcServer *server,
74                      GtkTreeIter *iter)
75 {
76   gchar *address;
77   guint port;
78   gboolean ssl;
79
80   g_object_get (server,
81       "address", &address,
82       "port", &port,
83       "ssl", &ssl,
84       NULL);
85
86   gtk_list_store_insert_with_values (store, iter, -1,
87       COL_SRV_OBJ, server,
88       COL_ADR, address,
89       COL_PORT, port,
90       COL_SSL, ssl,
91       -1);
92
93   g_free (address);
94 }
95
96 static void
97 irc_network_dialog_setup (EmpathyIrcNetworkDialog *dialog)
98 {
99   gchar *name, *charset;
100   GSList *servers, *l;
101   GtkListStore *store;
102
103   g_object_get (dialog->network,
104       "name", &name,
105       "charset", &charset,
106       NULL);
107   gtk_entry_set_text (GTK_ENTRY (dialog->entry_network), name);
108
109   store = GTK_LIST_STORE (gtk_tree_view_get_model (
110         GTK_TREE_VIEW (dialog->treeview_servers)));
111
112   servers = empathy_irc_network_get_servers (dialog->network);
113   for (l = servers; l != NULL; l = g_slist_next (l))
114     {
115       EmpathyIrcServer *server = l->data;
116       GtkTreeIter iter;
117
118       add_server_to_store (store, server, &iter);
119     }
120
121   totem_subtitle_encoding_set (GTK_COMBO_BOX (dialog->combobox_charset),
122       charset);
123
124   g_slist_foreach (servers, (GFunc) g_object_unref, NULL);
125   g_slist_free (servers);
126   g_free (name);
127   g_free (charset);
128 }
129
130 static void
131 irc_network_dialog_address_edited_cb (GtkCellRendererText *renderer,
132                                       gchar *path,
133                                       gchar *new_text,
134                                       EmpathyIrcNetworkDialog *dialog)
135 {
136   EmpathyIrcServer *server;
137   GtkTreeModel *model;
138   GtkTreePath  *treepath;
139   GtkTreeIter iter;
140
141   model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview_servers));
142   treepath = gtk_tree_path_new_from_string (path);
143   gtk_tree_model_get_iter (model, &iter, treepath);
144   gtk_tree_model_get (model, &iter,
145       COL_SRV_OBJ, &server,
146       -1);
147   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
148       COL_ADR, new_text,
149       -1);
150
151   g_object_set (server, "address", new_text, NULL);
152
153   gtk_tree_path_free (treepath);
154   g_object_unref (server);
155 }
156
157 static void
158 irc_network_dialog_port_edited_cb (GtkCellRendererText *renderer,
159                                    gchar *path,
160                                    gchar *new_text,
161                                    EmpathyIrcNetworkDialog *dialog)
162 {
163   EmpathyIrcServer *server;
164   GtkTreeModel *model;
165   GtkTreePath  *treepath;
166   GtkTreeIter iter;
167   guint port;
168
169   port = strtoul (new_text, NULL, 10);
170   model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview_servers));
171   treepath = gtk_tree_path_new_from_string (path);
172   gtk_tree_model_get_iter (model, &iter, treepath);
173   gtk_tree_model_get (model, &iter,
174       COL_SRV_OBJ, &server,
175       -1);
176   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
177       COL_PORT, port,
178       -1);
179
180   g_object_set (server, "port", port, NULL);
181
182   gtk_tree_path_free (treepath);
183   g_object_unref (server);
184 }
185
186 static void
187 irc_network_dialog_ssl_toggled_cb (GtkCellRendererText *renderer,
188                                    gchar *path,
189                                    EmpathyIrcNetworkDialog *dialog)
190 {
191   EmpathyIrcServer *server;
192   GtkTreeModel *model;
193   GtkTreePath  *treepath;
194   GtkTreeIter iter;
195   gboolean ssl;
196
197   model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview_servers));
198   treepath = gtk_tree_path_new_from_string (path);
199   gtk_tree_model_get_iter (model, &iter, treepath);
200   gtk_tree_model_get (model, &iter,
201       COL_SRV_OBJ, &server,
202       COL_SSL, &ssl,
203       -1);
204   ssl = !ssl;
205   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
206       COL_SSL, ssl,
207       -1);
208
209   g_object_set (server, "ssl", ssl, NULL);
210
211   gtk_tree_path_free (treepath);
212   g_object_unref (server);
213 }
214
215 static gboolean
216 irc_network_dialog_network_focus_cb (GtkWidget *widget,
217                                      GdkEventFocus *event,
218                                      EmpathyIrcNetworkDialog *dialog)
219 {
220   const gchar *str;
221
222   str = gtk_entry_get_text (GTK_ENTRY (widget));
223
224   g_object_set (dialog->network, "name", str, NULL);
225
226   return FALSE;
227 }
228
229 static void
230 irc_network_dialog_network_update_buttons (EmpathyIrcNetworkDialog *dialog)
231 {
232   GtkTreeSelection *selection;
233   GtkTreeModel *model;
234   GtkTreePath *path;
235   GtkTreeIter iter;
236   gboolean can_remove = FALSE, can_move_up = FALSE, can_move_down = FALSE;
237   int selected;
238
239   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (
240         dialog->treeview_servers));
241
242   if (gtk_tree_selection_get_selected (selection, &model, &iter))
243   {
244     path = gtk_tree_model_get_path (model, &iter);
245
246     selected = gtk_tree_path_get_indices (path)[0];
247
248     can_remove = TRUE;
249     can_move_up = selected > 0;
250     can_move_down =
251       selected < gtk_tree_model_iter_n_children (model, NULL) - 1;
252
253     gtk_tree_path_free (path);
254   }
255
256   gtk_widget_set_sensitive (dialog->button_remove, can_remove);
257   gtk_widget_set_sensitive (dialog->button_up, can_move_up);
258   gtk_widget_set_sensitive (dialog->button_down, can_move_down);
259 }
260
261 static void
262 irc_network_dialog_button_add_clicked_cb (GtkWidget *widget,
263                                           EmpathyIrcNetworkDialog *dialog)
264 {
265   EmpathyIrcServer *server;
266   GtkListStore *store;
267   GtkTreeIter iter;
268   GtkTreePath *path;
269   GtkTreeViewColumn *column;
270
271   store = GTK_LIST_STORE (gtk_tree_view_get_model (
272         GTK_TREE_VIEW (dialog->treeview_servers)));
273
274   server = empathy_irc_server_new (_("new server"), 6667, FALSE);
275   empathy_irc_network_append_server (dialog->network, server);
276   add_server_to_store (store, server, &iter);
277
278   path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
279   column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->treeview_servers),
280       0);
281   gtk_tree_view_set_cursor (GTK_TREE_VIEW (dialog->treeview_servers), path,
282       column, TRUE);
283
284   irc_network_dialog_network_update_buttons (dialog);
285
286   gtk_tree_path_free (path);
287   g_object_unref (server);
288 }
289
290 static void
291 irc_network_dialog_button_remove_clicked_cb (GtkWidget *widget,
292                                              EmpathyIrcNetworkDialog *dialog)
293 {
294   GtkTreeSelection *selection;
295   GtkTreeModel *model;
296   GtkTreeIter iter;
297   EmpathyIrcServer *server;
298
299   selection = gtk_tree_view_get_selection (
300       GTK_TREE_VIEW (dialog->treeview_servers));
301
302   if (!gtk_tree_selection_get_selected (selection, &model, &iter))
303     return;
304
305   gtk_tree_model_get (model, &iter, COL_SRV_OBJ, &server, -1);
306
307   gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
308   empathy_irc_network_remove_server (dialog->network, server);
309
310   irc_network_dialog_network_update_buttons (dialog);
311
312   g_object_unref (server);
313 }
314
315 static void
316 irc_network_dialog_button_up_clicked_cb (GtkWidget *widget,
317                                          EmpathyIrcNetworkDialog *dialog)
318 {
319   GtkTreeSelection *selection;
320   GtkTreeModel *model;
321   GtkTreeIter iter, iter_prev;
322   GtkTreePath *path;
323   gint *pos;
324   EmpathyIrcServer *server;
325
326   selection = gtk_tree_view_get_selection (
327       GTK_TREE_VIEW (dialog->treeview_servers));
328
329   if (!gtk_tree_selection_get_selected (selection, &model, &iter))
330     return;
331
332   path = gtk_tree_model_get_path (model, &iter);
333
334   if (!gtk_tree_path_prev (path))
335   {
336     gtk_tree_path_free (path);
337     return;
338   }
339
340   gtk_tree_model_get (model, &iter, COL_SRV_OBJ, &server, -1);
341
342   gtk_tree_model_get_iter (model, &iter_prev, path);
343   gtk_list_store_swap (GTK_LIST_STORE (model), &iter_prev, &iter);
344
345   pos = gtk_tree_path_get_indices (path);
346   empathy_irc_network_set_server_position (dialog->network, server, *pos);
347
348   irc_network_dialog_network_update_buttons (dialog);
349
350   g_object_unref (server);
351   gtk_tree_path_free (path);
352 }
353
354 static void
355 irc_network_dialog_button_down_clicked_cb (GtkWidget *widget,
356                                            EmpathyIrcNetworkDialog *dialog)
357 {
358   GtkTreeSelection *selection;
359   GtkTreeModel *model;
360   GtkTreeIter iter, iter_prev;
361   GtkTreePath *path;
362   EmpathyIrcServer *server;
363   gint *pos;
364
365   selection = gtk_tree_view_get_selection (
366       GTK_TREE_VIEW (dialog->treeview_servers));
367
368   if (!gtk_tree_selection_get_selected (selection, &model, &iter))
369     return;
370
371   path = gtk_tree_model_get_path (model, &iter);
372
373   gtk_tree_path_next (path);
374   if (!gtk_tree_model_get_iter (model, &iter_prev, path))
375     {
376       gtk_tree_path_free (path);
377       return;
378     }
379
380   gtk_tree_model_get (model, &iter, COL_SRV_OBJ, &server, -1);
381
382   gtk_list_store_swap (GTK_LIST_STORE (model), &iter_prev, &iter);
383
384   pos = gtk_tree_path_get_indices (path);
385   empathy_irc_network_set_server_position (dialog->network, server, *pos);
386
387   irc_network_dialog_network_update_buttons (dialog);
388
389   gtk_tree_path_free (path);
390 }
391
392 static void
393 irc_network_dialog_selection_changed_cb (GtkTreeSelection  *treeselection,
394                                          EmpathyIrcNetworkDialog *dialog)
395 {
396   irc_network_dialog_network_update_buttons (dialog);
397 }
398
399 static void
400 irc_network_dialog_combobox_charset_changed_cb (GtkWidget *combobox,
401                                                 EmpathyIrcNetworkDialog *dialog)
402 {
403   const gchar *charset;
404
405   charset = totem_subtitle_encoding_get_selected (GTK_COMBO_BOX (combobox));
406   g_object_set (dialog->network, "charset", charset, NULL);
407 }
408
409 static void
410 change_network (EmpathyIrcNetworkDialog *dialog,
411                 EmpathyIrcNetwork *network)
412 {
413   GtkListStore *store;
414
415   if (dialog->network == network)
416     /* No need to change */
417     return;
418
419   if (dialog->network != NULL)
420     {
421       g_object_unref (dialog->network);
422     }
423
424   dialog->network = network;
425   g_object_ref (network);
426
427   store = GTK_LIST_STORE (gtk_tree_view_get_model (
428         GTK_TREE_VIEW (dialog->treeview_servers)));
429   gtk_list_store_clear (store);
430
431   irc_network_dialog_setup (dialog);
432 }
433
434 /**
435  * empathy_irc_network_dialog_show:
436  * @network: the #EmpathyIrcNetwork to configure
437  * @parent: the parent of this dialog
438  *
439  * Display a dialog to configure a given #EmpathyIrcNetwork.
440  * This function is a singleton so if a configuration dialog already
441  * exists we use this one to edit the network.
442  *
443  * Returns: The displayed #GtkDialog
444  */
445 GtkWidget *
446 empathy_irc_network_dialog_show (EmpathyIrcNetwork *network,
447                                  GtkWidget *parent)
448 {
449   static EmpathyIrcNetworkDialog *dialog = NULL;
450   GtkBuilder *gui;
451   GtkListStore *store;
452   GtkCellRenderer *renderer;
453   GtkAdjustment *adjustment;
454   GtkTreeSelection *selection;
455   GtkTreeViewColumn *column;
456   GtkWidget *sw, *toolbar;
457   GtkStyleContext *context;
458
459   g_return_val_if_fail (network != NULL, NULL);
460
461   if (dialog != NULL)
462     {
463       change_network (dialog, network);
464       gtk_window_present (GTK_WINDOW (dialog->dialog));
465
466       return dialog->dialog;
467     }
468
469   dialog = g_slice_new0 (EmpathyIrcNetworkDialog);
470
471   dialog->network = network;
472   g_object_ref (dialog->network);
473
474   gui = empathy_builder_get_resource (ACCOUNT_WIDGETS_RESOURCES_PREFIX "/empathy-account-widget-irc.ui",
475       "irc_network_dialog", &dialog->dialog,
476       "button_close", &dialog->button_close,
477       "entry_network", &dialog->entry_network,
478       "combobox_charset", &dialog->combobox_charset,
479       "treeview_servers", &dialog->treeview_servers,
480       "button_add", &dialog->button_add,
481       "button_remove", &dialog->button_remove,
482       "button_up", &dialog->button_up,
483       "button_down", &dialog->button_down,
484       "scrolledwindow_network_server", &sw,
485       "toolbar_network_server", &toolbar,
486       NULL);
487
488   store = gtk_list_store_new (4, G_TYPE_OBJECT, G_TYPE_STRING,
489       G_TYPE_UINT, G_TYPE_BOOLEAN);
490   gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->treeview_servers),
491       GTK_TREE_MODEL (store));
492   g_object_unref (store);
493
494   /* address */
495   renderer = gtk_cell_renderer_text_new ();
496   g_object_set (renderer, "editable", TRUE, NULL);
497   g_signal_connect (renderer, "edited",
498       G_CALLBACK (irc_network_dialog_address_edited_cb), dialog);
499   gtk_tree_view_insert_column_with_attributes (
500       GTK_TREE_VIEW (dialog->treeview_servers),
501       -1, _("Server"), renderer, "text", COL_ADR,
502       NULL);
503   column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->treeview_servers),
504       0);
505
506   gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
507   gtk_tree_view_column_set_expand (column, TRUE);
508
509   /* port */
510   adjustment = (GtkAdjustment *) gtk_adjustment_new (6667, 1, G_MAXUINT16,
511       1, 10, 0);
512   renderer = gtk_cell_renderer_spin_new ();
513   g_object_set (renderer,
514       "editable", TRUE,
515       "adjustment", adjustment,
516       NULL);
517   g_signal_connect (renderer, "edited",
518       G_CALLBACK (irc_network_dialog_port_edited_cb), dialog);
519
520   gtk_tree_view_insert_column_with_attributes (
521       GTK_TREE_VIEW (dialog->treeview_servers),
522       -1, _("Port"), renderer, "text", COL_PORT,
523       NULL);
524
525   column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->treeview_servers),
526       1);
527   gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
528   gtk_tree_view_column_set_expand (column, TRUE);
529
530   /* SSL */
531   renderer = gtk_cell_renderer_toggle_new ();
532   g_object_set (renderer, "activatable", TRUE, NULL);
533   g_signal_connect (renderer, "toggled",
534       G_CALLBACK (irc_network_dialog_ssl_toggled_cb), dialog);
535   gtk_tree_view_insert_column_with_attributes (
536       GTK_TREE_VIEW (dialog->treeview_servers),
537       -1, _("SSL"), renderer, "active", COL_SSL,
538       NULL);
539
540   selection = gtk_tree_view_get_selection (
541       GTK_TREE_VIEW (dialog->treeview_servers));
542   gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
543
544   column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->treeview_servers),
545       2);
546   gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
547
548   gtk_tree_view_column_set_expand (column, TRUE);
549   /* charset */
550   totem_subtitle_encoding_init (GTK_COMBO_BOX (dialog->combobox_charset));
551
552   irc_network_dialog_setup (dialog);
553
554   empathy_builder_connect (gui, dialog,
555       "irc_network_dialog", "destroy", irc_network_dialog_destroy_cb,
556       "button_close", "clicked", irc_network_dialog_close_clicked_cb,
557       "entry_network", "focus-out-event", irc_network_dialog_network_focus_cb,
558       "button_add", "clicked", irc_network_dialog_button_add_clicked_cb,
559       "button_remove", "clicked", irc_network_dialog_button_remove_clicked_cb,
560       "button_up", "clicked", irc_network_dialog_button_up_clicked_cb,
561       "button_down", "clicked", irc_network_dialog_button_down_clicked_cb,
562       "combobox_charset", "changed", irc_network_dialog_combobox_charset_changed_cb,
563       NULL);
564
565   g_object_unref (gui);
566
567   g_object_add_weak_pointer (G_OBJECT (dialog->dialog),
568       (gpointer) &dialog);
569
570   g_signal_connect (selection, "changed",
571       G_CALLBACK (irc_network_dialog_selection_changed_cb),
572       dialog);
573
574   gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog),
575       GTK_WINDOW (parent));
576   gtk_window_set_modal (GTK_WINDOW (dialog->dialog), TRUE);
577
578   /* join the add/remove toolbar to the treeview */
579   context = gtk_widget_get_style_context (sw);
580   gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
581
582   context = gtk_widget_get_style_context (toolbar);
583   gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
584
585   irc_network_dialog_network_update_buttons (dialog);
586   gtk_widget_show_all (dialog->dialog);
587
588   gtk_window_set_resizable (GTK_WINDOW (dialog->dialog), FALSE);
589
590   return dialog->dialog;
591 }