]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-irc-network-chooser.c
e19b3e8abd6be7f0c28222ab8c430d96bc61bad3
[empathy.git] / libempathy-gtk / empathy-irc-network-chooser.c
1 /*
2  * Copyright (C) 2007-2008 Guillaume Desmottes
3  * Copyright (C) 2010 Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  * Authors: Guillaume Desmottes <gdesmott@gnome.org>
20  */
21
22 #include "config.h"
23
24 #include <libempathy/empathy-utils.h>
25 #include <libempathy/empathy-irc-network-manager.h>
26
27 #include "empathy-ui-utils.h"
28 #include "empathy-irc-network-chooser-dialog.h"
29
30 #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT | EMPATHY_DEBUG_IRC
31 #include <libempathy/empathy-debug.h>
32
33 #include "empathy-irc-network-chooser.h"
34
35 #define DEFAULT_IRC_NETWORK "irc.gimp.org"
36 #define DEFAULT_IRC_PORT 6667
37 #define DEFAULT_IRC_SSL FALSE
38
39 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIrcNetworkChooser)
40
41 enum {
42     PROP_SETTINGS = 1
43 };
44
45 enum {
46     SIG_CHANGED,
47     LAST_SIGNAL
48 };
49
50 static guint signals[LAST_SIGNAL] = { 0 };
51
52 typedef struct {
53     EmpathyAccountSettings *settings;
54
55     EmpathyIrcNetworkManager *network_manager;
56     GtkWidget *dialog;
57     /* Displayed network */
58     EmpathyIrcNetwork *network;
59 } EmpathyIrcNetworkChooserPriv;
60
61 G_DEFINE_TYPE (EmpathyIrcNetworkChooser, empathy_irc_network_chooser,
62     GTK_TYPE_BUTTON);
63
64 static void
65 empathy_irc_network_chooser_set_property (GObject *object,
66     guint prop_id,
67     const GValue *value,
68     GParamSpec *pspec)
69 {
70   EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (object);
71
72   switch (prop_id)
73     {
74       case PROP_SETTINGS:
75         priv->settings = g_value_dup_object (value);
76         break;
77       default:
78         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
79         break;
80     }
81 }
82
83 static void
84 empathy_irc_network_chooser_get_property (GObject *object,
85     guint prop_id,
86     GValue *value,
87     GParamSpec *pspec)
88 {
89   EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (object);
90
91   switch (prop_id)
92     {
93       case PROP_SETTINGS:
94         g_value_set_object (value, priv->settings);
95         break;
96       default:
97         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
98         break;
99     }
100 }
101
102 static void
103 unset_server_params (EmpathyIrcNetworkChooser *self)
104 {
105   EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self);
106
107   DEBUG ("Unset server, port and use-ssl");
108   empathy_account_settings_unset (priv->settings, "server");
109   empathy_account_settings_unset (priv->settings, "port");
110   empathy_account_settings_unset (priv->settings, "use-ssl");
111 }
112
113 static gchar *
114 dup_network_service (EmpathyIrcNetwork *network)
115 {
116   /* Account.Service has to be a lower case alphanumeric string which may
117    * also contain '-' but not start with it. */
118 #define VALID G_CSET_a_2_z G_CSET_DIGITS "-"
119   gchar *service, *tmp;
120
121   service = g_strdup (empathy_irc_network_get_name (network));
122   service = g_strstrip (service);
123
124   if (tp_str_empty (service))
125     {
126       g_free (service);
127       return NULL;
128     }
129
130   tmp = service;
131   service = g_ascii_strdown (service, -1);
132   g_free (tmp);
133
134   service = g_strcanon (service, VALID, '-');
135
136   if (service[0] == '-')
137     {
138       tmp = service;
139       service = g_strdup (service + 1);
140
141       g_free (tmp);
142     }
143
144   return service;
145 }
146
147 static void
148 update_server_params (EmpathyIrcNetworkChooser *self)
149 {
150   EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self);
151   GSList *servers;
152   const gchar *charset;
153
154   g_assert (priv->network != NULL);
155
156   charset = empathy_irc_network_get_charset (priv->network);
157   DEBUG ("Setting charset to %s", charset);
158   empathy_account_settings_set (priv->settings, "charset",
159       g_variant_new_string (charset));
160
161   servers = empathy_irc_network_get_servers (priv->network);
162   if (g_slist_length (servers) > 0)
163     {
164       /* set the first server as CM server */
165       EmpathyIrcServer *server = servers->data;
166       gchar *address;
167       guint port;
168       gboolean ssl;
169       gchar *service;
170
171       g_object_get (server,
172           "address", &address,
173           "port", &port,
174           "ssl", &ssl,
175           NULL);
176
177       DEBUG ("Setting server to %s", address);
178       empathy_account_settings_set (priv->settings, "server",
179           g_variant_new_string (address));
180       DEBUG ("Setting port to %u", port);
181       empathy_account_settings_set (priv->settings, "port",
182           g_variant_new_uint32 (port));
183       DEBUG ("Setting use-ssl to %s", ssl ? "TRUE": "FALSE" );
184       empathy_account_settings_set (priv->settings, "use-ssl",
185           g_variant_new_boolean (ssl));
186
187       /* Set Account.Service */
188       service = dup_network_service (priv->network);
189       DEBUG ("Setting Service to %s", service);
190       empathy_account_settings_set_service (priv->settings, service);
191
192       g_free (address);
193       g_free (service);
194     }
195   else
196     {
197       /* No server. Unset values */
198       unset_server_params (self);
199     }
200
201   g_slist_foreach (servers, (GFunc) g_object_unref, NULL);
202   g_slist_free (servers);
203 }
204
205 static void
206 set_label (EmpathyIrcNetworkChooser *self)
207 {
208   EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self);
209
210   g_assert (priv->network != NULL);
211
212   gtk_button_set_label (GTK_BUTTON (self),
213       empathy_irc_network_get_name (priv->network));
214 }
215
216 static void
217 set_label_from_settings (EmpathyIrcNetworkChooser *self)
218 {
219   EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self);
220   gchar *server;
221
222   tp_clear_object (&priv->network);
223
224   server = empathy_account_settings_dup_string (priv->settings, "server");
225
226   if (server != NULL)
227     {
228       EmpathyIrcServer *srv;
229       gint port;
230       gboolean ssl;
231
232       priv->network = empathy_irc_network_manager_find_network_by_address (
233           priv->network_manager, server);
234
235       if (priv->network != NULL)
236         {
237           /* The network is known */
238           g_object_ref (priv->network);
239           set_label (self);
240           return;
241         }
242
243       /* We don't have this network. Let's create it */
244       port = empathy_account_settings_get_uint32 (priv->settings, "port");
245       ssl = empathy_account_settings_get_boolean (priv->settings,
246           "use-ssl");
247
248       DEBUG ("Create a network %s", server);
249       priv->network = empathy_irc_network_new (server);
250       srv = empathy_irc_server_new (server, port, ssl);
251
252       empathy_irc_network_append_server (priv->network, srv);
253       empathy_irc_network_manager_add (priv->network_manager, priv->network);
254
255       set_label (self);
256
257       g_object_unref (srv);
258       g_free (server);
259       return;
260     }
261
262   /* Set default network */
263   priv->network = empathy_irc_network_manager_find_network_by_address (
264           priv->network_manager, DEFAULT_IRC_NETWORK);
265
266   if (priv->network == NULL)
267     {
268       /* Default network is not known, recreate it */
269       EmpathyIrcServer *srv;
270
271       priv->network = empathy_irc_network_new (DEFAULT_IRC_NETWORK);
272
273       srv = empathy_irc_server_new (DEFAULT_IRC_NETWORK, DEFAULT_IRC_PORT,
274           DEFAULT_IRC_SSL);
275
276       empathy_irc_network_append_server (priv->network, srv);
277       empathy_irc_network_manager_add (priv->network_manager, priv->network);
278
279       g_object_unref (srv);
280     }
281
282   set_label (self);
283   update_server_params (self);
284   g_object_ref (priv->network);
285 }
286
287 static void
288 dialog_response_cb (GtkDialog *dialog,
289     gint response,
290     EmpathyIrcNetworkChooser *self)
291 {
292   EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self);
293   EmpathyIrcNetworkChooserDialog *chooser =
294     EMPATHY_IRC_NETWORK_CHOOSER_DIALOG (priv->dialog);
295
296   if (response != GTK_RESPONSE_CLOSE &&
297       response != GTK_RESPONSE_DELETE_EVENT)
298     return;
299
300   if (empathy_irc_network_chooser_dialog_get_changed (chooser))
301     {
302       tp_clear_object (&priv->network);
303
304       priv->network = g_object_ref (
305           empathy_irc_network_chooser_dialog_get_network (chooser));
306
307       update_server_params (self);
308       set_label (self);
309
310       g_signal_emit (self, signals[SIG_CHANGED], 0);
311     }
312
313   gtk_widget_destroy (priv->dialog);
314   priv->dialog = NULL;
315 }
316
317 static void
318 clicked_cb (GtkButton *button,
319     gpointer user_data)
320 {
321   EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (button);
322   GtkWindow *window;
323
324   if (priv->dialog != NULL)
325     goto out;
326
327   window = empathy_get_toplevel_window (GTK_WIDGET (button));
328
329   priv->dialog = empathy_irc_network_chooser_dialog_new (priv->settings,
330       priv->network, window);
331   gtk_widget_show_all (priv->dialog);
332
333   tp_g_signal_connect_object (priv->dialog, "response",
334       G_CALLBACK (dialog_response_cb), button, 0);
335
336 out:
337   empathy_window_present (GTK_WINDOW (priv->dialog));
338 }
339
340 static void
341 empathy_irc_network_chooser_constructed (GObject *object)
342 {
343   EmpathyIrcNetworkChooser *self = (EmpathyIrcNetworkChooser *) object;
344   EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self);
345
346   g_assert (priv->settings != NULL);
347
348   set_label_from_settings (self);
349
350   g_signal_connect (self, "clicked", G_CALLBACK (clicked_cb), self);
351 }
352
353 static void
354 empathy_irc_network_chooser_dispose (GObject *object)
355 {
356   EmpathyIrcNetworkManager *self = (EmpathyIrcNetworkManager *) object;
357   EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self);
358
359   tp_clear_object (&priv->settings);
360   tp_clear_object (&priv->network_manager);
361   tp_clear_object (&priv->network);
362
363   if (G_OBJECT_CLASS (empathy_irc_network_chooser_parent_class)->dispose)
364     G_OBJECT_CLASS (empathy_irc_network_chooser_parent_class)->dispose (object);
365 }
366
367 static void
368 empathy_irc_network_chooser_class_init (EmpathyIrcNetworkChooserClass *klass)
369 {
370   GObjectClass *object_class = G_OBJECT_CLASS (klass);
371
372   object_class->get_property = empathy_irc_network_chooser_get_property;
373   object_class->set_property = empathy_irc_network_chooser_set_property;
374   object_class->constructed = empathy_irc_network_chooser_constructed;
375   object_class->dispose = empathy_irc_network_chooser_dispose;
376
377   g_object_class_install_property (object_class, PROP_SETTINGS,
378     g_param_spec_object ("settings",
379       "Settings",
380       "The EmpathyAccountSettings to show and edit",
381       EMPATHY_TYPE_ACCOUNT_SETTINGS,
382       G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
383
384   signals[SIG_CHANGED] = g_signal_new ("changed",
385       G_OBJECT_CLASS_TYPE (object_class),
386       G_SIGNAL_RUN_LAST,
387       0,
388       NULL, NULL,
389       g_cclosure_marshal_generic,
390       G_TYPE_NONE,
391       0);
392
393   g_type_class_add_private (object_class,
394       sizeof (EmpathyIrcNetworkChooserPriv));
395 }
396
397 static void
398 empathy_irc_network_chooser_init (EmpathyIrcNetworkChooser *self)
399 {
400   EmpathyIrcNetworkChooserPriv *priv;
401
402   priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
403       EMPATHY_TYPE_IRC_NETWORK_CHOOSER, EmpathyIrcNetworkChooserPriv);
404   self->priv = priv;
405
406   priv->network_manager = empathy_irc_network_manager_dup_default ();
407 }
408
409 GtkWidget *
410 empathy_irc_network_chooser_new (EmpathyAccountSettings *settings)
411 {
412   return g_object_new (EMPATHY_TYPE_IRC_NETWORK_CHOOSER,
413       "settings", settings,
414       NULL);
415 }
416
417 EmpathyIrcNetwork *
418 empathy_irc_network_chooser_get_network (EmpathyIrcNetworkChooser *self)
419 {
420   EmpathyIrcNetworkChooserPriv *priv = GET_PRIV (self);
421
422   return priv->network;
423 }