]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-account-widget-irc.c
Ensure EmpathyConnectionManagers stays alive when still emitting signals
[empathy.git] / libempathy-gtk / empathy-account-widget-irc.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 #include <libempathy/empathy-irc-network-manager.h>
32
33 #include "empathy-irc-network-dialog.h"
34 #include "empathy-account-widget.h"
35 #include "empathy-account-widget-irc.h"
36 #include "empathy-ui-utils.h"
37
38 #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT | EMPATHY_DEBUG_IRC
39 #include <libempathy/empathy-debug.h>
40
41 #define IRC_NETWORKS_FILENAME "irc-networks.xml"
42
43 typedef struct {
44   EmpathyAccountSettings *settings;
45   EmpathyIrcNetworkManager *network_manager;
46
47   GtkWidget *vbox_settings;
48
49   GtkWidget *combobox_network;
50 } EmpathyAccountWidgetIrc;
51
52 enum {
53   COL_NETWORK_OBJ,
54   COL_NETWORK_NAME,
55 };
56
57 static void
58 account_widget_irc_destroy_cb (GtkWidget *widget,
59                                EmpathyAccountWidgetIrc *settings)
60 {
61   g_object_unref (settings->network_manager);
62   g_object_unref (settings->settings);
63   g_slice_free (EmpathyAccountWidgetIrc, settings);
64 }
65
66 static void
67 unset_server_params (EmpathyAccountWidgetIrc *settings)
68 {
69   DEBUG ("Unset server, port and use-ssl");
70   empathy_account_settings_unset (settings->settings, "server");
71   empathy_account_settings_unset (settings->settings, "port");
72   empathy_account_settings_unset (settings->settings, "use-ssl");
73 }
74
75 static void
76 update_server_params (EmpathyAccountWidgetIrc *settings)
77 {
78   GtkTreeIter iter;
79   GtkTreeModel *model;
80   EmpathyIrcNetwork *network;
81   GSList *servers;
82   gchar *charset;
83
84   if (!gtk_combo_box_get_active_iter (
85         GTK_COMBO_BOX (settings->combobox_network), &iter))
86     {
87       unset_server_params (settings);
88       return;
89     }
90
91   model = gtk_combo_box_get_model (GTK_COMBO_BOX (settings->combobox_network));
92   gtk_tree_model_get (model, &iter, COL_NETWORK_OBJ, &network, -1);
93
94   g_assert (network != NULL);
95
96   g_object_get (network, "charset", &charset, NULL);
97   DEBUG ("Setting charset to %s", charset);
98   empathy_account_settings_set_string (settings->settings, "charset", charset);
99   g_free (charset);
100
101   servers = empathy_irc_network_get_servers (network);
102   if (g_slist_length (servers) > 0)
103     {
104       /* set the first server as CM server */
105       EmpathyIrcServer *server = servers->data;
106       gchar *address;
107       guint port;
108       gboolean ssl;
109
110       g_object_get (server,
111           "address", &address,
112           "port", &port,
113           "ssl", &ssl,
114           NULL);
115
116       DEBUG ("Setting server to %s", address);
117       empathy_account_settings_set_string (settings->settings,
118         "server", address);
119       DEBUG ("Setting port to %u", port);
120       empathy_account_settings_set_uint32 (settings->settings, "port", port);
121       DEBUG ("Setting use-ssl to %s", ssl ? "TRUE": "FALSE" );
122       empathy_account_settings_set_boolean (settings->settings,
123         "use-ssl", ssl);
124
125       g_free (address);
126     }
127   else
128     {
129       /* No server. Unset values */
130       unset_server_params (settings);
131     }
132
133   g_slist_foreach (servers, (GFunc) g_object_unref, NULL);
134   g_slist_free (servers);
135   g_object_unref (network);
136 }
137
138 static void
139 irc_network_dialog_destroy_cb (GtkWidget *widget,
140                                EmpathyAccountWidgetIrc *settings)
141 {
142   GtkTreeIter iter;
143   GtkTreeModel *model;
144   EmpathyIrcNetwork *network;
145   gchar *name;
146
147   /* name could be changed */
148   gtk_combo_box_get_active_iter (GTK_COMBO_BOX (settings->combobox_network),
149       &iter);
150   model = gtk_combo_box_get_model (GTK_COMBO_BOX (settings->combobox_network));
151   gtk_tree_model_get (model, &iter, COL_NETWORK_OBJ, &network, -1);
152
153   g_object_get (network, "name", &name, NULL);
154   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
155       COL_NETWORK_NAME, name, -1);
156
157   update_server_params (settings);
158
159   g_object_unref (network);
160   g_free (name);
161 }
162
163 static void
164 display_irc_network_dialog (EmpathyAccountWidgetIrc *settings,
165                             EmpathyIrcNetwork *network)
166 {
167   GtkWindow *window;
168   GtkWidget *dialog;
169
170   window = empathy_get_toplevel_window (settings->vbox_settings);
171   dialog = empathy_irc_network_dialog_show (network, GTK_WIDGET (window));
172   g_signal_connect (dialog, "destroy",
173       G_CALLBACK (irc_network_dialog_destroy_cb), settings);
174 }
175
176 static void
177 account_widget_irc_button_edit_network_clicked_cb (
178     GtkWidget *button,
179     EmpathyAccountWidgetIrc *settings)
180 {
181   GtkTreeIter iter;
182   GtkTreeModel *model;
183   EmpathyIrcNetwork *network;
184
185   gtk_combo_box_get_active_iter (GTK_COMBO_BOX (settings->combobox_network),
186       &iter);
187   model = gtk_combo_box_get_model (GTK_COMBO_BOX (settings->combobox_network));
188   gtk_tree_model_get (model, &iter, COL_NETWORK_OBJ, &network, -1);
189
190   g_assert (network != NULL);
191
192   display_irc_network_dialog (settings, network);
193
194   g_object_unref (network);
195 }
196
197 static void
198 account_widget_irc_button_remove_clicked_cb (GtkWidget *button,
199                                              EmpathyAccountWidgetIrc *settings)
200 {
201   EmpathyIrcNetwork *network;
202   GtkTreeIter iter;
203   GtkTreeModel *model;
204   gchar *name;
205
206   gtk_combo_box_get_active_iter (GTK_COMBO_BOX (settings->combobox_network),
207       &iter);
208   model = gtk_combo_box_get_model (GTK_COMBO_BOX (settings->combobox_network));
209   gtk_tree_model_get (model, &iter, COL_NETWORK_OBJ, &network, -1);
210
211   g_assert (network != NULL);
212
213   g_object_get (network, "name", &name, NULL);
214   DEBUG ("Remove network %s", name);
215
216   gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
217   empathy_irc_network_manager_remove (settings->network_manager, network);
218
219   /* Select the first network */
220   if (gtk_tree_model_get_iter_first (model, &iter))
221     {
222       gtk_combo_box_set_active_iter (
223           GTK_COMBO_BOX (settings->combobox_network), &iter);
224     }
225
226   g_free (name);
227   g_object_unref (network);
228 }
229
230 static void
231 account_widget_irc_button_add_network_clicked_cb (GtkWidget *button,
232                                                   EmpathyAccountWidgetIrc *settings)
233 {
234   EmpathyIrcNetwork *network;
235   GtkTreeModel *model;
236   GtkListStore *store;
237   gchar *name;
238   GtkTreeIter iter;
239
240   network = empathy_irc_network_new (_("New Network"));
241   empathy_irc_network_manager_add (settings->network_manager, network);
242
243   model = gtk_combo_box_get_model (GTK_COMBO_BOX (settings->combobox_network));
244   store = GTK_LIST_STORE (model);
245
246   g_object_get (network, "name", &name, NULL);
247
248   gtk_list_store_insert_with_values (store, &iter, -1,
249       COL_NETWORK_OBJ, network,
250       COL_NETWORK_NAME, name,
251       -1);
252
253   gtk_combo_box_set_active_iter (GTK_COMBO_BOX (settings->combobox_network),
254       &iter);
255
256   display_irc_network_dialog (settings, network);
257
258   g_free (name);
259   g_object_unref (network);
260 }
261
262 static void
263 account_widget_irc_combobox_network_changed_cb (GtkWidget *combobox,
264                                                 EmpathyAccountWidgetIrc *settings)
265 {
266   update_server_params (settings);
267 }
268
269 static void
270 fill_networks_model (EmpathyAccountWidgetIrc *settings,
271                      EmpathyIrcNetwork *network_to_select)
272 {
273   GSList *networks, *l;
274   GtkTreeModel *model;
275   GtkListStore *store;
276
277   networks = empathy_irc_network_manager_get_networks (
278       settings->network_manager);
279
280   model = gtk_combo_box_get_model (GTK_COMBO_BOX (settings->combobox_network));
281   store = GTK_LIST_STORE (model);
282
283   for (l = networks; l != NULL; l = g_slist_next (l))
284     {
285       gchar *name;
286       EmpathyIrcNetwork *network = l->data;
287       GtkTreeIter iter;
288
289       g_object_get (network, "name", &name, NULL);
290
291       gtk_list_store_insert_with_values (store, &iter, -1,
292           COL_NETWORK_OBJ, network,
293           COL_NETWORK_NAME, name,
294           -1);
295
296        if (network == network_to_select)
297          {
298            gtk_combo_box_set_active_iter (
299                GTK_COMBO_BOX (settings->combobox_network), &iter);
300          }
301
302       g_free (name);
303       g_object_unref (network);
304     }
305
306   if (network_to_select == NULL)
307     {
308       /* Select the first network */
309       GtkTreeIter iter;
310
311       if (gtk_tree_model_get_iter_first (model, &iter))
312         {
313           gtk_combo_box_set_active_iter (
314               GTK_COMBO_BOX (settings->combobox_network), &iter);
315
316           update_server_params (settings);
317         }
318     }
319
320   g_slist_free (networks);
321 }
322
323 static void
324 account_widget_irc_setup (EmpathyAccountWidgetIrc *settings)
325 {
326   const gchar *nick = NULL;
327   const gchar *fullname = NULL;
328   const gchar *server = NULL;
329   gint port = 6667;
330   const gchar *charset;
331   gboolean ssl = FALSE;
332   EmpathyIrcNetwork *network = NULL;
333
334   nick = empathy_account_settings_get_string (settings->settings, "account");
335   fullname = empathy_account_settings_get_string (settings->settings,
336       "fullname");
337   server = empathy_account_settings_get_string (settings->settings, "server");
338   charset = empathy_account_settings_get_string (settings->settings, "charset");
339   port = empathy_account_settings_get_uint32 (settings->settings, "port");
340   ssl = empathy_account_settings_get_boolean (settings->settings, "use-ssl");
341
342   if (!nick)
343     {
344       nick = g_strdup (g_get_user_name ());
345       empathy_account_settings_set_string (settings->settings,
346         "account", nick);
347     }
348
349   if (!fullname)
350     {
351       fullname = g_strdup (g_get_real_name ());
352       if (!fullname)
353         {
354           fullname = g_strdup (nick);
355         }
356       empathy_account_settings_set_string (settings->settings,
357           "fullname", fullname);
358     }
359
360   if (server != NULL)
361     {
362       GtkListStore *store;
363
364       network = empathy_irc_network_manager_find_network_by_address (
365           settings->network_manager, server);
366
367
368       store = GTK_LIST_STORE (gtk_combo_box_get_model (
369             GTK_COMBO_BOX (settings->combobox_network)));
370
371       if (network != NULL)
372         {
373           gchar *name;
374
375           g_object_set (network, "charset", charset, NULL);
376
377           g_object_get (network, "name", &name, NULL);
378           DEBUG ("Account use network %s", name);
379
380           g_free (name);
381         }
382       else
383         {
384           /* We don't have this network. Let's create it */
385           EmpathyIrcServer *srv;
386           GtkTreeIter iter;
387
388           DEBUG ("Create a network %s", server);
389           network = empathy_irc_network_new (server);
390           srv = empathy_irc_server_new (server, port, ssl);
391
392           empathy_irc_network_append_server (network, srv);
393           empathy_irc_network_manager_add (settings->network_manager, network);
394
395           gtk_list_store_insert_with_values (store, &iter, -1,
396               COL_NETWORK_OBJ, network,
397               COL_NETWORK_NAME, server,
398               -1);
399
400           gtk_combo_box_set_active_iter (
401               GTK_COMBO_BOX (settings->combobox_network), &iter);
402
403           g_object_unref (srv);
404           g_object_unref (network);
405         }
406     }
407
408
409   fill_networks_model (settings, network);
410 }
411
412 /**
413  * empathy_account_widget_irc_new:
414  * @settings: the #EmpathyAccountSettings to configure
415  *
416  * Creates a new IRC account widget to configure a given #EmpathyAccount
417  *
418  * Returns: The toplevel container of the configuration widget
419  */
420 GtkWidget *
421 empathy_account_widget_irc_new (EmpathyAccountSettings *account_settings)
422 {
423   EmpathyAccountWidgetIrc *settings;
424   gchar *dir, *user_file_with_path, *global_file_with_path;
425   GtkBuilder *gui;
426   GtkWidget *widget;
427   GtkListStore *store;
428   GtkCellRenderer *renderer;
429   gchar *filename;
430
431   settings = g_slice_new0 (EmpathyAccountWidgetIrc);
432   settings->settings = g_object_ref (account_settings);
433
434   dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL);
435   g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR);
436   user_file_with_path = g_build_filename (dir, IRC_NETWORKS_FILENAME, NULL);
437   g_free (dir);
438
439   global_file_with_path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"),
440       "libempathy-gtk", IRC_NETWORKS_FILENAME, NULL);
441   if (!g_file_test (global_file_with_path, G_FILE_TEST_EXISTS))
442     {
443       g_free (global_file_with_path);
444       global_file_with_path = g_build_filename (DATADIR, "empathy",
445           IRC_NETWORKS_FILENAME, NULL);
446     }
447
448   settings->network_manager = empathy_irc_network_manager_new (
449       global_file_with_path,
450       user_file_with_path);
451
452   g_free (global_file_with_path);
453   g_free (user_file_with_path);
454
455   filename = empathy_file_lookup ("empathy-account-widget-irc.ui",
456       "libempathy-gtk");
457   gui = empathy_builder_get_file (filename,
458       "vbox_irc", &widget,
459       "table_irc_settings", &settings->vbox_settings,
460       "combobox_network", &settings->combobox_network,
461       NULL);
462   g_free (filename);
463
464   /* Fill the networks combobox */
465   store = gtk_list_store_new (2, G_TYPE_OBJECT, G_TYPE_STRING);
466
467   gtk_cell_layout_clear (GTK_CELL_LAYOUT (settings->combobox_network));
468   renderer = gtk_cell_renderer_text_new ();
469   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (settings->combobox_network),
470       renderer, TRUE);
471   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (settings->combobox_network),
472       renderer,
473       "text", COL_NETWORK_NAME,
474       NULL);
475
476   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
477       COL_NETWORK_NAME,
478       GTK_SORT_ASCENDING);
479
480   gtk_combo_box_set_model (GTK_COMBO_BOX (settings->combobox_network),
481       GTK_TREE_MODEL (store));
482   g_object_unref (store);
483
484   account_widget_irc_setup (settings);
485
486   empathy_account_widget_handle_params (account_settings, gui,
487       "entry_nick", "account",
488       "entry_fullname", "fullname",
489       "entry_password", "password",
490       "entry_quit_message", "quit-message",
491       NULL);
492
493   empathy_builder_connect (gui, settings,
494       "table_irc_settings", "destroy", account_widget_irc_destroy_cb,
495       "button_network", "clicked",
496           account_widget_irc_button_edit_network_clicked_cb,
497       "button_add_network", "clicked",
498           account_widget_irc_button_add_network_clicked_cb,
499       "button_remove_network", "clicked",
500           account_widget_irc_button_remove_clicked_cb,
501       "combobox_network", "changed",
502           account_widget_irc_combobox_network_changed_cb,
503       NULL);
504
505   empathy_account_widget_set_default_focus (gui, "entry_nick");
506   empathy_account_widget_add_apply_button (account_settings, widget);
507
508   return empathy_builder_unref_and_keep_widget (gui, widget);
509 }