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