]> git.0d.be Git - empathy.git/blob - src/empathy-account-assistant.c
Merge branch 'debug-window'
[empathy.git] / src / empathy-account-assistant.c
1 /*
2  * Copyright (C) 2009 Collabora Ltd.
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: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
19  */
20
21 /* empathy-account-assistant.c */
22
23 #include <glib/gi18n.h>
24 #include <telepathy-glib/util.h>
25 #include <gdk/gdkkeysyms.h>
26
27 #include "empathy-account-assistant.h"
28 #include "empathy-import-widget.h"
29 #include "empathy-import-utils.h"
30
31 #include <libempathy/empathy-account-settings.h>
32 #include <libempathy/empathy-utils.h>
33
34 #include <libempathy-gtk/empathy-account-widget.h>
35 #include <libempathy-gtk/empathy-protocol-chooser.h>
36 #include <libempathy-gtk/empathy-ui-utils.h>
37
38 G_DEFINE_TYPE (EmpathyAccountAssistant, empathy_account_assistant,
39     GTK_TYPE_ASSISTANT)
40
41 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountAssistant)
42
43 typedef enum {
44   RESPONSE_IMPORT = 1,
45   RESPONSE_ENTER_ACCOUNT = 2,
46   RESPONSE_CREATE_ACCOUNT = 3,
47   RESPONSE_SALUT_ONLY = 4
48 } FirstPageResponse;
49
50 typedef enum {
51   RESPONSE_CREATE_AGAIN = 1,
52   RESPONSE_CREATE_STOP = 2
53 } CreateEnterPageResponse;
54
55 enum {
56   PAGE_INTRO = 0,
57   PAGE_IMPORT = 1,
58   PAGE_ENTER_CREATE = 2,
59 };
60
61 enum {
62   PROP_PARENT = 1
63 };
64
65 typedef struct {
66   FirstPageResponse first_resp;
67   CreateEnterPageResponse create_enter_resp;
68   gboolean enter_create_forward;
69
70   /* enter or create page */
71   GtkWidget *enter_or_create_page;
72   GtkWidget *current_account_widget;
73   EmpathyAccountWidget *current_widget_object;
74   GtkWidget *first_label;
75   GtkWidget *second_label;
76   GtkWidget *chooser;
77   GtkWidget *create_again_radio;
78   EmpathyAccountSettings *settings;
79   gboolean is_creating;
80
81   /* import page */
82   EmpathyImportWidget *iw;
83
84   GtkWindow *parent_window;
85
86   gboolean dispose_run;
87 } EmpathyAccountAssistantPriv;
88
89 static GtkWidget * account_assistant_build_enter_or_create_page (
90     EmpathyAccountAssistant *self);
91 static void account_assistant_finish_enter_or_create_page (
92     EmpathyAccountAssistant *self,
93     gboolean is_enter);
94
95 static GtkWidget *
96 account_assistant_build_error_page (EmpathyAccountAssistant *self,
97     GError *error, gint page_num)
98 {
99   GtkWidget *main_vbox, *w, *hbox;
100   GString *str;
101   char *message;
102   PangoAttrList *list;
103   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
104
105   main_vbox = gtk_vbox_new (FALSE, 12);
106   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
107   gtk_widget_show (main_vbox);
108
109   hbox = gtk_hbox_new (FALSE, 12);
110   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
111   gtk_widget_show (hbox);
112
113   w = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR,
114       GTK_ICON_SIZE_DIALOG);
115   gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
116   gtk_widget_show (w);
117
118   /* translators: this is followed by the "while ..." strings some lines
119    * down this file.
120    */
121   str = g_string_new (_("There has been an error "));
122
123   if (page_num == PAGE_IMPORT)
124     /* translators: this follows the "There has been an error " string */
125     str = g_string_append (str, _("while importing the accounts."));
126   else if (page_num >= PAGE_ENTER_CREATE &&
127       priv->first_resp == RESPONSE_ENTER_ACCOUNT)
128     /* translators: this follows the "There has been an error " string */
129     str = g_string_append (str, _("while parsing the account details."));
130   else if (page_num >= PAGE_ENTER_CREATE &&
131       priv->first_resp == RESPONSE_CREATE_ACCOUNT)
132     /* translators: this follows the "There has been an error " string */
133     str = g_string_append (str, _("while creating the account."));
134
135   message = g_string_free (str, FALSE);
136
137   w = gtk_label_new (message);
138   gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
139   list = pango_attr_list_new ();
140   pango_attr_list_insert (list, pango_attr_scale_new (PANGO_SCALE_LARGE));
141   pango_attr_list_insert (list, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
142   gtk_label_set_attributes (GTK_LABEL (w), list);
143   gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5);
144   gtk_label_set_line_wrap (GTK_LABEL (w), TRUE);
145   gtk_widget_show (w);
146
147   g_free (message);
148   pango_attr_list_unref (list);
149
150   message = g_markup_printf_escaped
151     (_("The error message was: <span style=\"italic\">%s</span>"),
152         error->message);
153   w = gtk_label_new (message);
154   gtk_label_set_use_markup (GTK_LABEL (w), TRUE);
155   gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0);
156   gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5);
157   gtk_widget_show (w);
158
159   w = gtk_label_new (_("You can either go back and try to enter your "
160           "accounts' details again or quit this wizard and add accounts "
161           "later from the Edit menu."));
162   gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 6);
163   gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5);
164   gtk_label_set_line_wrap (GTK_LABEL (w), TRUE);
165   gtk_widget_show (w);
166
167   return main_vbox;
168 }
169
170 static void
171 account_assistant_back_button_clicked_cb (GtkButton *button,
172     EmpathyAccountAssistant *self)
173 {
174   gint page_num;
175
176   page_num = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
177           "page-num"));
178   gtk_assistant_remove_action_widget (GTK_ASSISTANT (self),
179       GTK_WIDGET (button));
180   gtk_assistant_set_current_page (GTK_ASSISTANT (self), page_num);
181 }
182
183 static void
184 account_assistant_present_error_page (EmpathyAccountAssistant *self,
185     GError *error, gint page_num)
186 {
187   GtkWidget *error_page, *back_button;
188   gint num;
189
190   error_page = account_assistant_build_error_page (self, error,
191       page_num);
192   num = gtk_assistant_append_page (GTK_ASSISTANT (self), error_page);
193   gtk_assistant_set_page_title (GTK_ASSISTANT (self), error_page,
194       _("An error occurred"));
195   gtk_assistant_set_page_type (GTK_ASSISTANT (self), error_page,
196       GTK_ASSISTANT_PAGE_SUMMARY);
197
198   back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
199   gtk_assistant_add_action_widget (GTK_ASSISTANT (self), back_button);
200   g_object_set_data (G_OBJECT (back_button),
201       "page-num", GINT_TO_POINTER (page_num));
202   g_signal_connect (back_button, "clicked",
203       G_CALLBACK (account_assistant_back_button_clicked_cb), self);
204   gtk_widget_show (back_button);
205
206   gtk_assistant_set_current_page (GTK_ASSISTANT (self), num);
207 }
208
209 static void
210 account_assistant_reset_enter_create_page (EmpathyAccountAssistant *self)
211 {
212   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
213   GtkWidget *page;
214   gint idx;
215
216   page = account_assistant_build_enter_or_create_page (self);
217   idx = gtk_assistant_append_page (GTK_ASSISTANT (self), page);
218   gtk_assistant_set_page_type (GTK_ASSISTANT (self), page,
219       GTK_ASSISTANT_PAGE_CONFIRM);
220   priv->enter_or_create_page = page;
221
222   gtk_assistant_set_current_page (GTK_ASSISTANT (self), idx);
223
224   account_assistant_finish_enter_or_create_page (self,
225       priv->first_resp == RESPONSE_ENTER_ACCOUNT ?
226       TRUE : FALSE);
227 }
228
229 static void
230 account_assistant_account_enabled_cb (GObject *source,
231     GAsyncResult *result,
232     gpointer user_data)
233 {
234   GError *error = NULL;
235   EmpathyAccountAssistant *self = user_data;
236   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
237
238   empathy_account_set_enabled_finish (EMPATHY_ACCOUNT (source),
239       result, &error);
240
241   if (error)
242     {
243       g_warning ("Error enabling an account: %s", error->message);
244       g_error_free (error);
245     }
246
247   if (priv->create_enter_resp == RESPONSE_CREATE_STOP)
248     g_signal_emit_by_name (self, "close");
249   else
250     account_assistant_reset_enter_create_page (self);
251 }
252
253 static void
254 account_assistant_apply_account_cb (GObject *source,
255     GAsyncResult *result,
256     gpointer user_data)
257 {
258   GError *error = NULL;
259   EmpathyAccountAssistant *self = user_data;
260   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
261   EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (source);
262   EmpathyAccount *account;
263
264   empathy_account_settings_apply_finish (settings, result, &error);
265
266   priv->is_creating = FALSE;
267
268   if (error != NULL)
269     {
270       account_assistant_present_error_page (self, error,
271           gtk_assistant_get_current_page (GTK_ASSISTANT (self)));
272       g_error_free (error);
273       return;
274     }
275
276   /* enable the newly created account */
277   account = empathy_account_settings_get_account (settings);
278   empathy_account_set_enabled_async (account, TRUE,
279       account_assistant_account_enabled_cb, self);
280 }
281
282 static void
283 account_assistant_apply_account_and_finish (EmpathyAccountAssistant *self)
284 {
285   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
286
287   if (priv->settings == NULL)
288     return;
289
290   priv->is_creating = TRUE;
291
292   empathy_account_settings_apply_async (priv->settings,
293       account_assistant_apply_account_cb, self);
294 }
295
296 static void
297 account_assistant_handle_apply_cb (EmpathyAccountWidget *widget_object,
298     gboolean is_valid,
299     EmpathyAccountAssistant *self)
300 {
301   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
302
303   gtk_assistant_set_page_complete (GTK_ASSISTANT (self),
304       priv->enter_or_create_page, is_valid);
305 }
306
307 static void
308 account_assistant_protocol_changed_cb (GtkComboBox *chooser,
309     EmpathyAccountAssistant *self)
310 {
311   TpConnectionManager *cm;
312   TpConnectionManagerProtocol *proto;
313   EmpathyAccountSettings *settings;
314   EmpathyAccountAssistantPriv *priv;
315   char *str;
316   GtkWidget *account_widget;
317   EmpathyAccountWidget *widget_object = NULL;
318
319   priv = GET_PRIV (self);
320
321   cm = empathy_protocol_chooser_dup_selected (
322       EMPATHY_PROTOCOL_CHOOSER (chooser), &proto);
323
324   if (cm == NULL || proto == NULL)
325     /* we are not ready yet */
326     return;
327
328   /* Create account */
329   /* To translator: %s is the protocol name */
330   str = g_strdup_printf (_("New %s account"), proto->name);
331
332   settings = empathy_account_settings_new (cm->name, proto->name, str);
333
334   if (priv->first_resp == RESPONSE_CREATE_ACCOUNT)
335     empathy_account_settings_set_boolean (settings, "register", TRUE);
336
337   widget_object = empathy_account_widget_new_for_protocol (proto->name,
338       settings, TRUE);
339   account_widget = empathy_account_widget_get_widget (widget_object);
340
341   if (priv->current_account_widget != NULL)
342     {
343       g_signal_handlers_disconnect_by_func (priv->current_widget_object,
344           account_assistant_handle_apply_cb, self);
345       gtk_widget_destroy (priv->current_account_widget);
346     }
347
348   priv->current_account_widget = account_widget;
349   priv->current_widget_object = widget_object;
350
351   if (priv->settings != NULL)
352     g_object_unref (priv->settings);
353
354   priv->settings = settings;
355
356   g_signal_connect (priv->current_widget_object, "handle-apply",
357       G_CALLBACK (account_assistant_handle_apply_cb), self);
358
359   gtk_box_pack_start (GTK_BOX (priv->enter_or_create_page), account_widget,
360       FALSE, FALSE, 0);
361   gtk_widget_show (account_widget);
362
363   g_free (str);
364 }
365
366 static gboolean
367 account_assistant_chooser_enter_details_filter_func (
368     TpConnectionManager *cm,
369     TpConnectionManagerProtocol *protocol,
370     gpointer user_data)
371 {
372   if (!tp_strdiff (protocol->name, "local-xmpp") ||
373       !tp_strdiff (protocol->name, "irc"))
374     return FALSE;
375
376   return TRUE;
377 }
378
379 static gboolean
380 account_assistant_chooser_create_account_filter_func (
381     TpConnectionManager *cm,
382     TpConnectionManagerProtocol *protocol,
383     gpointer user_data)
384 {
385   return tp_connection_manager_protocol_can_register (protocol);
386 }
387
388 static void
389 account_assistant_finish_enter_or_create_page (EmpathyAccountAssistant *self,
390     gboolean is_enter)
391 {
392   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
393
394   if (is_enter)
395     {
396       gtk_label_set_label (GTK_LABEL (priv->first_label),
397           _("What kind of chat account do you have?"));
398       /*      gtk_label_set_label (GTK_LABEL (priv->second_label),
399           _("If you have other accounts to set up, you can do "
400               "that at any time from the Edit menu."));
401       */
402       gtk_label_set_label (GTK_LABEL (priv->second_label),
403           _("Do you have any other chat accounts you want to set up?"));
404       empathy_protocol_chooser_set_visible (
405           EMPATHY_PROTOCOL_CHOOSER (priv->chooser),
406           account_assistant_chooser_enter_details_filter_func, self);
407
408       gtk_assistant_set_page_title (GTK_ASSISTANT (self),
409           priv->enter_or_create_page, _("Enter your account details"));
410     }
411   else
412     {
413       gtk_label_set_label (GTK_LABEL (priv->first_label),
414           _("What kind of chat account do you want to create?"));
415       /*      gtk_label_set_label (GTK_LABEL (priv->second_label),
416           _("You can register other accounts, or setup "
417               "an existing one at any time from the Edit menu."));
418       */
419       gtk_label_set_label (GTK_LABEL (priv->second_label),
420           _("Do you want to create other chat accounts?"));
421       empathy_protocol_chooser_set_visible (
422           EMPATHY_PROTOCOL_CHOOSER (priv->chooser),
423           account_assistant_chooser_create_account_filter_func, self);
424
425       gtk_assistant_set_page_title (GTK_ASSISTANT (self),
426           priv->enter_or_create_page,
427           _("Enter the details for the new account"));
428     }
429
430   g_signal_connect (priv->chooser, "changed",
431       G_CALLBACK (account_assistant_protocol_changed_cb), self);
432
433   /* trigger show the first account widget */
434   account_assistant_protocol_changed_cb (GTK_COMBO_BOX (priv->chooser), self);
435 }
436
437 static gint
438 account_assistant_page_forward_func (gint current_page,
439     gpointer user_data)
440 {
441   EmpathyAccountAssistant *self = user_data;
442   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
443   gint retval;
444
445   retval = current_page;
446
447   if (current_page == PAGE_INTRO)
448     {
449       if (priv->first_resp == RESPONSE_ENTER_ACCOUNT ||
450           priv->first_resp == RESPONSE_CREATE_ACCOUNT)
451         retval = PAGE_ENTER_CREATE;
452       if (priv->first_resp == RESPONSE_IMPORT)
453         retval = PAGE_IMPORT;
454     }
455
456   if (current_page == PAGE_IMPORT ||
457       current_page >= PAGE_ENTER_CREATE)
458     /* don't forward anymore */
459     retval = -1;
460
461   if (current_page >= PAGE_ENTER_CREATE &&
462       priv->create_enter_resp == RESPONSE_CREATE_AGAIN)
463     {
464       priv->enter_create_forward = TRUE;
465       retval = current_page;
466     }
467
468   return retval;
469 }
470
471 static void
472 account_assistant_radio_choice_toggled_cb (GtkToggleButton *button,
473     EmpathyAccountAssistant *self)
474 {
475   FirstPageResponse response;
476   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
477   GtkWidget *intro_page;
478
479   response = GPOINTER_TO_INT (g_object_get_data
480       (G_OBJECT (button), "response"));
481
482   priv->first_resp = response;
483
484   intro_page = gtk_assistant_get_nth_page (GTK_ASSISTANT (self),
485       PAGE_INTRO);
486
487   if (response == RESPONSE_SALUT_ONLY)
488     gtk_assistant_set_page_type (GTK_ASSISTANT (self), intro_page,
489         GTK_ASSISTANT_PAGE_SUMMARY);
490   else
491     gtk_assistant_set_page_type (GTK_ASSISTANT (self), intro_page,
492         GTK_ASSISTANT_PAGE_INTRO);
493 }
494
495 static GtkWidget *
496 account_assistant_build_introduction_page (EmpathyAccountAssistant *self)
497 {
498   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
499   GtkWidget *main_vbox, *hbox_1, *w, *vbox_1;
500   GtkWidget *radio = NULL;
501   GdkPixbuf *pix;
502   const gchar *str;
503
504   main_vbox = gtk_vbox_new (FALSE, 12);
505   gtk_widget_show (main_vbox);
506   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
507
508   hbox_1 = gtk_hbox_new (FALSE, 12);
509   gtk_box_pack_start (GTK_BOX (main_vbox), hbox_1, TRUE, TRUE, 0);
510   gtk_widget_show (hbox_1);
511
512   w = gtk_label_new (
513       _("With Empathy you can chat with people "
514         "online nearby and with friends and colleagues "
515         "who use Google Talk, AIM, Windows Live "
516         "and many other chat programs. With a microphone "
517         "or a webcam you can also have audio or video calls."));
518   gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5);
519   gtk_label_set_line_wrap (GTK_LABEL (w), TRUE);
520   gtk_box_pack_start (GTK_BOX (hbox_1), w, FALSE, FALSE, 0);
521   gtk_widget_show (w);
522
523   pix = empathy_pixbuf_from_icon_name_sized ("empathy", 80);
524   w = gtk_image_new_from_pixbuf (pix);
525   gtk_box_pack_start (GTK_BOX (hbox_1), w, FALSE, FALSE, 6);
526   gtk_widget_show (w);
527
528   g_object_unref (pix);
529
530   w = gtk_label_new (_("Do you have an account you've been using "
531           "with another chat program?"));
532   gtk_misc_set_alignment (GTK_MISC (w), 0, 0);
533   gtk_label_set_line_wrap (GTK_LABEL (w), TRUE);
534   gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0);
535   gtk_widget_show (w);
536
537   w = gtk_alignment_new (0, 0, 0, 0);
538   gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0);
539   gtk_box_pack_start (GTK_BOX (main_vbox), w, TRUE, TRUE, 0);
540   gtk_widget_show (w);
541
542   vbox_1 = gtk_vbox_new (TRUE, 0);
543   gtk_container_add (GTK_CONTAINER (w), vbox_1);
544   gtk_widget_show (vbox_1);
545
546   if (empathy_import_accounts_to_import ())
547     {
548       hbox_1 = gtk_hbox_new (FALSE, 0);
549       gtk_box_pack_start (GTK_BOX (vbox_1), hbox_1, TRUE, TRUE, 0);
550       gtk_widget_show (hbox_1);
551
552       radio = gtk_radio_button_new_with_label (NULL,
553           _("Yes, import my account details from "));
554       gtk_box_pack_start (GTK_BOX (hbox_1), radio, TRUE, TRUE, 0);
555       g_object_set_data (G_OBJECT (radio), "response",
556           GINT_TO_POINTER (RESPONSE_IMPORT));
557       gtk_widget_show (radio);
558
559       w = gtk_combo_box_new_text ();
560       gtk_combo_box_append_text (GTK_COMBO_BOX (w), "Pidgin");
561       gtk_box_pack_start (GTK_BOX (hbox_1), w, TRUE, TRUE, 0);
562       gtk_combo_box_set_active (GTK_COMBO_BOX (w), 0);
563       gtk_widget_show (w);
564
565       g_signal_connect (radio, "clicked",
566           G_CALLBACK (account_assistant_radio_choice_toggled_cb), self);
567       priv->first_resp = RESPONSE_IMPORT;
568     }
569   else
570     {
571       priv->first_resp = RESPONSE_ENTER_ACCOUNT;
572     }
573
574   str = _("Yes, I'll enter my account details now");
575
576   if (radio == NULL)
577     {
578       radio = gtk_radio_button_new_with_label (NULL, str);
579       w = radio;
580     }
581   else
582     {
583       w = gtk_radio_button_new_with_label_from_widget (
584           GTK_RADIO_BUTTON (radio), str);
585     }
586
587   gtk_box_pack_start (GTK_BOX (vbox_1), w, TRUE, TRUE, 0);
588   g_object_set_data (G_OBJECT (w), "response",
589       GINT_TO_POINTER (RESPONSE_ENTER_ACCOUNT));
590   gtk_widget_show (w);
591
592   g_signal_connect (w, "clicked",
593       G_CALLBACK (account_assistant_radio_choice_toggled_cb), self);
594
595   w = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio),
596       _("No, I want a new account"));
597   gtk_box_pack_start (GTK_BOX (vbox_1), w, TRUE, TRUE, 0);
598   g_object_set_data (G_OBJECT (w), "response",
599       GINT_TO_POINTER (RESPONSE_CREATE_ACCOUNT));
600   gtk_widget_show (w);
601
602   g_signal_connect (w, "clicked",
603       G_CALLBACK (account_assistant_radio_choice_toggled_cb), self);
604
605   w = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio),
606       _("No, I just want to see people online nearby for now"));
607   gtk_box_pack_start (GTK_BOX (vbox_1), w, TRUE, TRUE, 0);
608   g_object_set_data (G_OBJECT (w), "response",
609       GINT_TO_POINTER (RESPONSE_SALUT_ONLY));
610   gtk_widget_show (w);
611
612   g_signal_connect (w, "clicked",
613       G_CALLBACK (account_assistant_radio_choice_toggled_cb), self);
614
615   return main_vbox;
616 }
617
618 static GtkWidget *
619 account_assistant_build_import_page (EmpathyAccountAssistant *self)
620 {
621   GtkWidget *main_vbox, *w, *import;
622   EmpathyImportWidget *iw;
623   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
624
625   main_vbox = gtk_vbox_new (FALSE, 12);
626   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
627   w = gtk_label_new (_("Select the accounts you want to import:"));
628   gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5);
629   gtk_widget_show (w);
630   gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 6);
631
632   w = gtk_alignment_new (0, 0, 0, 0);
633   gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0);
634   gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0);
635   gtk_widget_show (w);
636
637   /* NOTE: this is hardcoded as we support pidgin only */
638   iw = empathy_import_widget_new (EMPATHY_IMPORT_APPLICATION_PIDGIN);
639   import = empathy_import_widget_get_widget (iw);
640   gtk_container_add (GTK_CONTAINER (w), import);
641   gtk_widget_show (import);
642
643   priv->iw = iw;
644
645   gtk_widget_show (main_vbox);
646
647   return main_vbox;
648 }
649
650 static void
651 account_assistant_radio_create_again_clicked_cb (GtkButton *button,
652     EmpathyAccountAssistant *self)
653 {
654   CreateEnterPageResponse response;
655   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
656
657   response = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
658           "response"));
659
660   priv->create_enter_resp = response;
661
662   gtk_assistant_set_page_type (GTK_ASSISTANT (self),
663       priv->enter_or_create_page,
664       (response == RESPONSE_CREATE_AGAIN) ?
665       GTK_ASSISTANT_PAGE_CONTENT : GTK_ASSISTANT_PAGE_CONFIRM);
666 }
667
668 static GtkWidget *
669 account_assistant_build_enter_or_create_page (EmpathyAccountAssistant *self)
670 {
671   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
672   GtkWidget *main_vbox, *w, *chooser, *vbox, *hbox, *radio;
673
674   main_vbox = gtk_vbox_new (FALSE, 12);
675   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
676   gtk_widget_show (main_vbox);
677
678   w = gtk_label_new (NULL);
679   gtk_misc_set_alignment (GTK_MISC (w), 0, 0);
680   gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0);
681   gtk_widget_show (w);
682   priv->first_label = w;
683
684   w = gtk_alignment_new (0, 0, 0, 0);
685   gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0);
686   gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0);
687   gtk_widget_show (w);
688
689   chooser = empathy_protocol_chooser_new ();
690   gtk_container_add (GTK_CONTAINER (w), chooser);
691   gtk_widget_show (chooser);
692   priv->chooser = chooser;
693
694   vbox = gtk_vbox_new (FALSE, 6);
695   gtk_box_pack_end (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
696   gtk_widget_show (vbox);
697
698   w = gtk_label_new (NULL);
699   gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);
700   gtk_label_set_line_wrap (GTK_LABEL (w), TRUE);
701   gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5);
702   gtk_widget_show (w);
703   priv->second_label = w;
704
705   w = gtk_alignment_new (0, 0, 0, 0);
706   gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0);
707   gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);
708   gtk_widget_show (w);
709
710   hbox = gtk_hbox_new (FALSE, 6);
711   gtk_container_add (GTK_CONTAINER (w), hbox);
712   gtk_widget_show (hbox);
713
714   radio = gtk_radio_button_new_with_label (NULL, _("Yes"));
715   gtk_box_pack_start (GTK_BOX (hbox), radio, FALSE, FALSE, 0);
716   g_object_set_data (G_OBJECT (radio), "response",
717       GINT_TO_POINTER (RESPONSE_CREATE_AGAIN));
718   gtk_widget_show (radio);
719
720   w = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio),
721       _("No, that's all for now"));
722   gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
723   g_object_set_data (G_OBJECT (w), "response",
724       GINT_TO_POINTER (RESPONSE_CREATE_STOP));
725   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), TRUE);
726   priv->create_enter_resp = RESPONSE_CREATE_STOP;
727   priv->create_again_radio = w;
728   gtk_widget_show (w);
729
730   g_signal_connect (w, "clicked",
731       G_CALLBACK (account_assistant_radio_create_again_clicked_cb), self);
732   g_signal_connect (radio, "clicked",
733       G_CALLBACK (account_assistant_radio_create_again_clicked_cb), self);
734
735   return main_vbox;
736 }
737
738 static void
739 account_assistant_close_cb (GtkAssistant *assistant,
740     gpointer user_data)
741 {
742   EmpathyAccountAssistantPriv *priv = GET_PRIV (assistant);
743
744   if (priv->is_creating)
745     return;
746
747   gtk_widget_destroy (GTK_WIDGET (assistant));
748 }
749
750 static void
751 impl_signal_apply (GtkAssistant *assistant)
752 {
753   EmpathyAccountAssistant *self = EMPATHY_ACCOUNT_ASSISTANT (assistant);
754   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
755   gint current_page;
756
757   current_page = gtk_assistant_get_current_page (assistant);
758
759   if (current_page >= PAGE_ENTER_CREATE)
760     account_assistant_apply_account_and_finish (self);
761
762   if (current_page == PAGE_IMPORT)
763     empathy_import_widget_add_selected_accounts (priv->iw);
764 }
765
766 static void
767 impl_signal_cancel (GtkAssistant *assistant)
768 {
769   gtk_widget_destroy (GTK_WIDGET (assistant));
770 }
771
772 static void
773 impl_signal_prepare (GtkAssistant *assistant,
774     GtkWidget *current_page)
775 {
776   EmpathyAccountAssistant *self = EMPATHY_ACCOUNT_ASSISTANT (assistant);
777   EmpathyAccountAssistantPriv *priv = GET_PRIV (self);
778   gint current_idx;
779
780   current_idx = gtk_assistant_get_current_page (assistant);
781
782   if (current_idx >= PAGE_ENTER_CREATE)
783     {
784       if (!priv->enter_create_forward)
785         {
786           account_assistant_finish_enter_or_create_page (self,
787               priv->first_resp == RESPONSE_ENTER_ACCOUNT ?
788               TRUE : FALSE);
789         }
790       else
791         {
792           priv->enter_create_forward = FALSE;
793           account_assistant_apply_account_and_finish (self);
794         }
795     }
796 }
797
798 static void
799 do_get_property (GObject *object,
800     guint property_id,
801     GValue *value,
802     GParamSpec *pspec)
803 {
804   EmpathyAccountAssistantPriv *priv = GET_PRIV (object);
805
806   switch (property_id)
807     {
808     case PROP_PARENT:
809       g_value_set_object (value, priv->parent_window);
810       break;
811     default:
812       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
813     }
814 }
815
816 static void
817 do_set_property (GObject *object,
818     guint property_id,
819     const GValue *value,
820     GParamSpec *pspec)
821 {
822   EmpathyAccountAssistantPriv *priv = GET_PRIV (object);
823
824   switch (property_id)
825     {
826     case PROP_PARENT:
827       priv->parent_window = g_value_get_object (value);
828       break;
829     default:
830       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
831     }
832 }
833
834 static void
835 do_constructed (GObject *object)
836 {
837   EmpathyAccountAssistantPriv *priv = GET_PRIV (object);
838
839   /* set us as transient for the parent window if any */
840   if (priv->parent_window)
841     gtk_window_set_transient_for (GTK_WINDOW (object),
842         priv->parent_window);
843
844   /* set the dialog hint, so this will be centered over the parent window */
845   gtk_window_set_type_hint (GTK_WINDOW (object), GDK_WINDOW_TYPE_HINT_DIALOG);
846 }
847
848 static void
849 do_dispose (GObject *obj)
850 {
851   EmpathyAccountAssistantPriv *priv = GET_PRIV (obj);
852
853   if (priv->dispose_run)
854     return;
855
856   priv->dispose_run = TRUE;
857
858   if (priv->settings != NULL)
859     {
860       g_object_unref (priv->settings);
861       priv->settings = NULL;
862     }
863
864   if (G_OBJECT_CLASS (empathy_account_assistant_parent_class)->dispose != NULL)
865     G_OBJECT_CLASS (empathy_account_assistant_parent_class)->dispose (obj);
866 }
867
868 static void
869 empathy_account_assistant_class_init (EmpathyAccountAssistantClass *klass)
870 {
871   GObjectClass *oclass = G_OBJECT_CLASS (klass);
872   GtkAssistantClass *gtkclass = GTK_ASSISTANT_CLASS (klass);
873   GParamSpec *param_spec;
874
875   oclass->get_property = do_get_property;
876   oclass->set_property = do_set_property;
877   oclass->constructed = do_constructed;
878   oclass->dispose = do_dispose;
879
880   gtkclass->apply = impl_signal_apply;
881   gtkclass->prepare = impl_signal_prepare;
882   gtkclass->cancel = impl_signal_cancel;
883
884   param_spec = g_param_spec_object ("parent-window",
885       "parent-window", "The parent window",
886       GTK_TYPE_WINDOW,
887       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
888   g_object_class_install_property (oclass, PROP_PARENT, param_spec);
889
890   g_type_class_add_private (klass, sizeof (EmpathyAccountAssistantPriv));
891 }
892
893 static void
894 empathy_account_assistant_init (EmpathyAccountAssistant *self)
895 {
896   EmpathyAccountAssistantPriv *priv;
897   GtkAssistant *assistant = GTK_ASSISTANT (self);
898   GtkWidget *page;
899
900   priv = G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_ACCOUNT_ASSISTANT,
901       EmpathyAccountAssistantPriv);
902   self->priv = priv;
903
904   g_signal_connect (self, "close",
905       G_CALLBACK (account_assistant_close_cb), NULL);
906
907   gtk_assistant_set_forward_page_func (assistant,
908       account_assistant_page_forward_func, self, NULL);
909
910   /* first page (introduction) */
911   page = account_assistant_build_introduction_page (self);
912   gtk_assistant_append_page (assistant, page);
913   gtk_assistant_set_page_title (assistant, page,
914       _("Welcome to Empathy"));
915   gtk_assistant_set_page_type (assistant, page,
916       GTK_ASSISTANT_PAGE_INTRO);
917   gtk_assistant_set_page_complete (assistant, page, TRUE);
918
919   /* second page (import accounts) */
920   page = account_assistant_build_import_page (self);
921   gtk_assistant_append_page (assistant, page);
922   gtk_assistant_set_page_title (assistant, page,
923       _("Import your existing accounts"));
924   gtk_assistant_set_page_complete (assistant, page, TRUE);
925   gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONFIRM);
926
927   /* third page (enter account details) */
928   page = account_assistant_build_enter_or_create_page (self);
929   gtk_assistant_append_page (assistant, page);
930   gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONFIRM);
931   priv->enter_or_create_page = page;
932
933   gtk_window_set_resizable (GTK_WINDOW (self), FALSE);
934 }
935
936 GtkWidget *
937 empathy_account_assistant_new (GtkWindow *window)
938 {
939   return g_object_new (EMPATHY_TYPE_ACCOUNT_ASSISTANT, "parent-window",
940       window, NULL);
941 }