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