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