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