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