]> git.0d.be Git - empathy.git/blob - src/empathy-accounts-dialog.c
Merge branch 'sjoerd-mc5' into mc5
[empathy.git] / src / empathy-accounts-dialog.c
1 /*
2  * Copyright (C) 2005-2007 Imendio AB
3  * Copyright (C) 2007-2009 Collabora Ltd.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program 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  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA  02110-1301  USA
19  *
20  * Authors: Martyn Russell <martyn@imendio.com>
21  *          Xavier Claessens <xclaesse@gmail.com>
22  *          Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
23  */
24
25 #include <config.h>
26
27 #include <string.h>
28 #include <stdlib.h>
29
30 #include <gtk/gtk.h>
31 #include <glib/gi18n.h>
32 #include <dbus/dbus-glib.h>
33
34 #include <telepathy-glib/util.h>
35
36 #include <libempathy/empathy-utils.h>
37 #include <libempathy/empathy-account-manager.h>
38 #include <libempathy/empathy-connection-managers.h>
39 #include <libempathy-gtk/empathy-ui-utils.h>
40
41 #include <libempathy-gtk/empathy-protocol-chooser.h>
42 #include <libempathy-gtk/empathy-account-widget.h>
43 #include <libempathy-gtk/empathy-account-widget-irc.h>
44 #include <libempathy-gtk/empathy-account-widget-sip.h>
45 #include <libempathy-gtk/empathy-conf.h>
46
47 #include "empathy-accounts-dialog.h"
48 #if 0
49 /* FIXME MC-5 */
50 #include "empathy-import-dialog.h"
51 #endif
52
53 #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
54 #include <libempathy/empathy-debug.h>
55
56 /* Flashing delay for icons (milliseconds). */
57 #define FLASH_TIMEOUT 500
58
59 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountsDialog)
60 G_DEFINE_TYPE (EmpathyAccountsDialog, empathy_accounts_dialog, G_TYPE_OBJECT);
61
62 static EmpathyAccountsDialog *dialog_singleton = NULL;
63
64 typedef struct {
65   GtkWidget *window;
66
67   GtkWidget *alignment_settings;
68
69   GtkWidget *vbox_details;
70   GtkWidget *frame_no_protocol;
71
72   GtkWidget *treeview;
73
74   GtkWidget *button_add;
75   GtkWidget *button_remove;
76   GtkWidget *button_import;
77
78   GtkWidget *frame_new_account;
79   GtkWidget *combobox_protocol;
80   GtkWidget *hbox_type;
81   GtkWidget *button_create;
82   GtkWidget *button_back;
83   GtkWidget *radiobutton_reuse;
84   GtkWidget *radiobutton_register;
85
86   GtkWidget *image_type;
87   GtkWidget *label_name;
88   GtkWidget *label_type;
89   GtkWidget *settings_widget;
90
91   gboolean  connecting_show;
92   guint connecting_id;
93
94   gulong  settings_ready_id;
95   EmpathyAccountSettings *settings_ready;
96
97   EmpathyAccountManager *account_manager;
98   EmpathyConnectionManagers *cms;
99
100   GtkWindow *parent_window;
101   EmpathyAccount *initial_selection;
102 } EmpathyAccountsDialogPriv;
103
104 enum {
105   COL_ENABLED,
106   COL_NAME,
107   COL_STATUS,
108   COL_ACCOUNT_POINTER,
109   COL_ACCOUNT_SETTINGS_POINTER,
110   COL_COUNT
111 };
112
113 enum {
114   PROP_PARENT = 1
115 };
116
117 static void accounts_dialog_update_settings (EmpathyAccountsDialog *dialog,
118     EmpathyAccountSettings *settings);
119
120 #if 0
121 /* FIXME MC-5 */
122 static void accounts_dialog_button_import_clicked_cb  (GtkWidget *button,
123     EmpathyAccountsDialog *dialog);
124 #endif
125
126 static void
127 accounts_dialog_update_name_label (EmpathyAccountsDialog *dialog,
128     EmpathyAccountSettings *settings)
129 {
130   gchar *text;
131   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
132
133   text = g_markup_printf_escaped ("<big><b>%s</b></big>",
134       empathy_account_settings_get_display_name (settings));
135   gtk_label_set_markup (GTK_LABEL (priv->label_name), text);
136
137   g_free (text);
138 }
139
140 static GtkWidget *
141 get_account_setup_widget (EmpathyAccountSettings *settings)
142 {
143   const gchar *cm = empathy_account_settings_get_cm (settings);
144   const gchar *proto = empathy_account_settings_get_protocol (settings);
145
146   struct {
147     const gchar *cm;
148     const gchar *proto;
149   } dialogs[] = {
150     { "gabble", "jabber" },
151     { "butterfly", "msn" },
152     { "salut", "local-xmpp" },
153     { "idle", "irc" },
154     { "haze", "icq" },
155     { "haze", "aim" },
156     { "haze", "yahoo" },
157     { "haze", "groupwise" },
158     { "sofiasip", "sip" },
159     { NULL, NULL }
160   };
161   int i;
162
163   for (i = 0; dialogs[i].cm != NULL; i++)
164     {
165       if (!tp_strdiff (cm, dialogs[i].cm)
166           && !tp_strdiff (proto, dialogs[i].proto))
167         return empathy_account_widget_new_for_protocol (dialogs[i].proto, settings);
168     }
169
170   return empathy_account_widget_new_for_protocol ("generic", settings);
171 }
172
173 static void
174 account_dialog_create_settings_widget (EmpathyAccountsDialog *dialog,
175     EmpathyAccountSettings *settings)
176 {
177   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
178   gchar *icon_name;
179
180   priv->settings_widget = get_account_setup_widget (settings);
181
182   gtk_container_add (GTK_CONTAINER (priv->alignment_settings),
183       priv->settings_widget);
184   gtk_widget_show (priv->settings_widget);
185
186   icon_name = empathy_account_settings_get_icon_name (settings);
187
188   gtk_image_set_from_icon_name (GTK_IMAGE (priv->image_type),
189       icon_name, GTK_ICON_SIZE_DIALOG);
190   gtk_widget_set_tooltip_text (priv->image_type,
191       empathy_account_settings_get_protocol (settings));
192
193   accounts_dialog_update_name_label (dialog, settings);
194
195   g_free (icon_name);
196 }
197
198 static void
199 account_dialog_settings_ready_cb (EmpathyAccountSettings *settings,
200     GParamSpec *spec,
201     EmpathyAccountsDialog *dialog)
202 {
203   if (empathy_account_settings_is_ready (settings))
204     account_dialog_create_settings_widget (dialog, settings);
205 }
206
207 static void
208 accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog)
209 {
210   GtkTreeView      *view;
211   GtkTreeModel     *model;
212   GtkTreeSelection *selection;
213   GtkTreeIter       iter;
214   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
215
216   /* select first */
217   view = GTK_TREE_VIEW (priv->treeview);
218   model = gtk_tree_view_get_model (view);
219
220   if (gtk_tree_model_get_iter_first (model, &iter))
221     {
222       selection = gtk_tree_view_get_selection (view);
223       gtk_tree_selection_select_iter (selection, &iter);
224     }
225   else
226     {
227       accounts_dialog_update_settings (dialog, NULL);
228     }
229 }
230
231 static void
232 accounts_dialog_protocol_changed_cb (GtkWidget *widget,
233     EmpathyAccountsDialog *dialog)
234 {
235   TpConnectionManager *cm;
236   TpConnectionManagerProtocol *proto;
237   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
238
239   cm = empathy_protocol_chooser_dup_selected (
240       EMPATHY_PROTOCOL_CHOOSER (priv->combobox_protocol), &proto);
241
242   if (tp_connection_manager_protocol_can_register (proto))
243     {
244       gtk_widget_show (priv->radiobutton_register);
245       gtk_widget_show (priv->radiobutton_reuse);
246     }
247   else
248     {
249       gtk_widget_hide (priv->radiobutton_register);
250       gtk_widget_hide (priv->radiobutton_reuse);
251     }
252   g_object_unref (cm);
253 }
254
255 static void
256 accounts_dialog_button_add_clicked_cb (GtkWidget *button,
257     EmpathyAccountsDialog *dialog)
258 {
259   GtkTreeView      *view;
260   GtkTreeSelection *selection;
261   GtkTreeModel     *model;
262   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
263
264   view = GTK_TREE_VIEW (priv->treeview);
265   model = gtk_tree_view_get_model (view);
266   selection = gtk_tree_view_get_selection (view);
267   gtk_tree_selection_unselect_all (selection);
268
269   gtk_widget_set_sensitive (priv->button_add, FALSE);
270   gtk_widget_set_sensitive (priv->button_remove, FALSE);
271   gtk_widget_hide (priv->vbox_details);
272   gtk_widget_hide (priv->frame_no_protocol);
273   gtk_widget_show (priv->frame_new_account);
274
275   /* If we have no account, no need of a back button */
276   if (gtk_tree_model_iter_n_children (model, NULL) > 0)
277     gtk_widget_show (priv->button_back);
278   else
279     gtk_widget_hide (priv->button_back);
280
281   accounts_dialog_protocol_changed_cb (priv->radiobutton_register, dialog);
282   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->radiobutton_reuse),
283       TRUE);
284   gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combobox_protocol), 0);
285   gtk_widget_grab_focus (priv->combobox_protocol);
286 }
287
288 static void
289 accounts_dialog_update_settings (EmpathyAccountsDialog *dialog,
290     EmpathyAccountSettings *settings)
291 {
292   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
293
294   if (priv->settings_ready != NULL)
295     {
296       g_signal_handler_disconnect (priv->settings_ready,
297           priv->settings_ready_id);
298       priv->settings_ready = NULL;
299       priv->settings_ready_id = 0;
300     }
301
302   if (!settings)
303     {
304       GtkTreeView  *view;
305       GtkTreeModel *model;
306
307       view = GTK_TREE_VIEW (priv->treeview);
308       model = gtk_tree_view_get_model (view);
309
310       if (gtk_tree_model_iter_n_children (model, NULL) > 0)
311         {
312           /* We have configured accounts, select the first one */
313           accounts_dialog_model_select_first (dialog);
314           return;
315         }
316       if (empathy_connection_managers_get_cms_num (priv->cms) > 0)
317         {
318           /* We have no account configured but we have some
319            * profiles instsalled. The user obviously wants to add
320            * an account. Click on the Add button for him. */
321           accounts_dialog_button_add_clicked_cb (priv->button_add,
322               dialog);
323           return;
324         }
325
326       /* No account and no profile, warn the user */
327       gtk_widget_hide (priv->vbox_details);
328       gtk_widget_hide (priv->frame_new_account);
329       gtk_widget_show (priv->frame_no_protocol);
330       gtk_widget_set_sensitive (priv->button_add, FALSE);
331       gtk_widget_set_sensitive (priv->button_remove, FALSE);
332       return;
333     }
334
335   /* We have an account selected, destroy old settings and create a new
336    * one for the account selected */
337   gtk_widget_hide (priv->frame_new_account);
338   gtk_widget_hide (priv->frame_no_protocol);
339   gtk_widget_show (priv->vbox_details);
340   gtk_widget_set_sensitive (priv->button_add, TRUE);
341   gtk_widget_set_sensitive (priv->button_remove, TRUE);
342
343   if (priv->settings_widget)
344     {
345       gtk_widget_destroy (priv->settings_widget);
346       priv->settings_widget = NULL;
347     }
348
349   if (empathy_account_settings_is_ready (settings))
350     {
351       account_dialog_create_settings_widget (dialog, settings);
352     }
353   else
354     {
355       priv->settings_ready = settings;
356       priv->settings_ready_id =
357         g_signal_connect (settings, "notify::ready",
358             G_CALLBACK (account_dialog_settings_ready_cb), dialog);
359     }
360
361 }
362
363 static void
364 accounts_dialog_name_editing_started_cb (GtkCellRenderer *renderer,
365     GtkCellEditable *editable,
366     gchar *path,
367     EmpathyAccountsDialog *dialog)
368 {
369   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
370
371   if (priv->connecting_id)
372     g_source_remove (priv->connecting_id);
373
374   DEBUG ("Editing account name started; stopping flashing");
375 }
376
377 static void
378 accounts_dialog_model_pixbuf_data_func (GtkTreeViewColumn *tree_column,
379     GtkCellRenderer *cell,
380     GtkTreeModel *model,
381     GtkTreeIter *iter,
382     EmpathyAccountsDialog *dialog)
383 {
384   EmpathyAccountSettings  *settings;
385   gchar              *icon_name;
386   GdkPixbuf          *pixbuf;
387   TpConnectionStatus  status;
388   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
389
390   gtk_tree_model_get (model, iter,
391       COL_STATUS, &status,
392       COL_ACCOUNT_SETTINGS_POINTER, &settings,
393       -1);
394
395   icon_name = empathy_account_settings_get_icon_name (settings);
396   pixbuf = empathy_pixbuf_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
397
398   g_free (icon_name);
399
400   if (pixbuf)
401     {
402       if (status == TP_CONNECTION_STATUS_DISCONNECTED ||
403           (status == TP_CONNECTION_STATUS_CONNECTING &&
404               !priv->connecting_show))
405         {
406           GdkPixbuf *modded_pixbuf;
407
408           modded_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
409               TRUE,
410               8,
411               gdk_pixbuf_get_width (pixbuf),
412               gdk_pixbuf_get_height (pixbuf));
413
414           gdk_pixbuf_saturate_and_pixelate (pixbuf,
415               modded_pixbuf,
416               1.0,
417               TRUE);
418           g_object_unref (pixbuf);
419           pixbuf = modded_pixbuf;
420         }
421     }
422
423   g_object_set (cell,
424       "visible", TRUE,
425       "pixbuf", pixbuf,
426       NULL);
427
428   g_object_unref (settings);
429
430   if (pixbuf)
431     g_object_unref (pixbuf);
432 }
433
434 static void
435 accounts_dialog_enable_toggled_cb (GtkCellRendererToggle *cell_renderer,
436     gchar *path,
437     EmpathyAccountsDialog *dialog)
438 {
439   EmpathyAccount    *account;
440   GtkTreeModel *model;
441   GtkTreePath  *treepath;
442   GtkTreeIter   iter;
443   gboolean      enabled;
444   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
445
446   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
447   treepath = gtk_tree_path_new_from_string (path);
448   gtk_tree_model_get_iter (model, &iter, treepath);
449   gtk_tree_model_get (model, &iter,
450       COL_ACCOUNT_POINTER, &account,
451       -1);
452   gtk_tree_path_free (treepath);
453
454   if (account == NULL)
455     return;
456
457   enabled = empathy_account_is_enabled (account);
458   empathy_account_set_enabled (account, !enabled);
459
460   DEBUG ("%s account %s", enabled ? "Disabled" : "Enable",
461       empathy_account_get_display_name (account));
462
463   g_object_unref (account);
464 }
465
466 static gboolean
467 accounts_dialog_row_changed_foreach (GtkTreeModel *model,
468     GtkTreePath *path,
469     GtkTreeIter *iter,
470     gpointer user_data)
471 {
472   gtk_tree_model_row_changed (model, path, iter);
473
474   return FALSE;
475 }
476
477 static gboolean
478 accounts_dialog_flash_connecting_cb (EmpathyAccountsDialog *dialog)
479 {
480   GtkTreeView  *view;
481   GtkTreeModel *model;
482   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
483
484   priv->connecting_show = !priv->connecting_show;
485
486   view = GTK_TREE_VIEW (priv->treeview);
487   model = gtk_tree_view_get_model (view);
488
489   gtk_tree_model_foreach (model, accounts_dialog_row_changed_foreach, NULL);
490
491   return TRUE;
492 }
493
494 static void
495 accounts_dialog_name_edited_cb (GtkCellRendererText *renderer,
496     gchar *path,
497     gchar *new_text,
498     EmpathyAccountsDialog *dialog)
499 {
500   EmpathyAccountSettings    *settings;
501   GtkTreeModel *model;
502   GtkTreePath  *treepath;
503   GtkTreeIter   iter;
504   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
505
506   if (empathy_account_manager_get_connecting_accounts
507       (priv->account_manager) > 0)
508     {
509       priv->connecting_id = g_timeout_add (FLASH_TIMEOUT,
510           (GSourceFunc) accounts_dialog_flash_connecting_cb,
511           dialog);
512     }
513
514   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
515   treepath = gtk_tree_path_new_from_string (path);
516   gtk_tree_model_get_iter (model, &iter, treepath);
517   gtk_tree_model_get (model, &iter,
518       COL_ACCOUNT_SETTINGS_POINTER, &settings,
519       -1);
520   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
521       COL_NAME, new_text,
522       -1);
523   gtk_tree_path_free (treepath);
524
525   empathy_account_settings_set_display_name_async (settings, new_text,
526       NULL, NULL);
527   g_object_unref (settings);
528 }
529
530 static void
531 accounts_dialog_model_add_columns (EmpathyAccountsDialog *dialog)
532 {
533   GtkTreeView       *view;
534   GtkTreeViewColumn *column;
535   GtkCellRenderer   *cell;
536   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
537
538   view = GTK_TREE_VIEW (priv->treeview);
539   gtk_tree_view_set_headers_visible (view, TRUE);
540
541   /* Enabled column */
542   cell = gtk_cell_renderer_toggle_new ();
543   gtk_tree_view_insert_column_with_attributes (view, -1,
544       _("Enabled"),
545       cell,
546       "active", COL_ENABLED,
547       NULL);
548   g_signal_connect (cell, "toggled",
549       G_CALLBACK (accounts_dialog_enable_toggled_cb),
550       dialog);
551
552   /* Account column */
553   column = gtk_tree_view_column_new ();
554   gtk_tree_view_column_set_title (column, _("Accounts"));
555   gtk_tree_view_column_set_expand (column, TRUE);
556   gtk_tree_view_append_column (view, column);
557
558   /* Icon renderer */
559   cell = gtk_cell_renderer_pixbuf_new ();
560   gtk_tree_view_column_pack_start (column, cell, FALSE);
561   gtk_tree_view_column_set_cell_data_func (column, cell,
562       (GtkTreeCellDataFunc)
563       accounts_dialog_model_pixbuf_data_func,
564       dialog,
565       NULL);
566
567   /* Name renderer */
568   cell = gtk_cell_renderer_text_new ();
569   g_object_set (cell,
570       "ellipsize", PANGO_ELLIPSIZE_END,
571       "width-chars", 25,
572       "editable", TRUE,
573       NULL);
574   gtk_tree_view_column_pack_start (column, cell, TRUE);
575   gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME);
576   g_signal_connect (cell, "edited",
577       G_CALLBACK (accounts_dialog_name_edited_cb),
578       dialog);
579   g_signal_connect (cell, "editing-started",
580       G_CALLBACK (accounts_dialog_name_editing_started_cb),
581       dialog);
582 }
583
584 static EmpathyAccountSettings *
585 accounts_dialog_model_get_selected_settings (EmpathyAccountsDialog *dialog)
586 {
587   GtkTreeView      *view;
588   GtkTreeModel     *model;
589   GtkTreeSelection *selection;
590   GtkTreeIter       iter;
591   EmpathyAccountSettings   *settings;
592   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
593
594   view = GTK_TREE_VIEW (priv->treeview);
595   selection = gtk_tree_view_get_selection (view);
596
597   if (!gtk_tree_selection_get_selected (selection, &model, &iter))
598     return NULL;
599
600   gtk_tree_model_get (model, &iter,
601       COL_ACCOUNT_SETTINGS_POINTER, &settings, -1);
602
603   return settings;
604 }
605
606 static void
607 accounts_dialog_model_selection_changed (GtkTreeSelection *selection,
608     EmpathyAccountsDialog *dialog)
609 {
610   EmpathyAccountSettings *settings;
611   GtkTreeModel *model;
612   GtkTreeIter   iter;
613   gboolean      is_selection;
614
615   is_selection = gtk_tree_selection_get_selected (selection, &model, &iter);
616
617   settings = accounts_dialog_model_get_selected_settings (dialog);
618   accounts_dialog_update_settings (dialog, settings);
619
620   if (settings)
621     g_object_unref (settings);
622 }
623
624 static void
625 accounts_dialog_model_setup (EmpathyAccountsDialog *dialog)
626 {
627   GtkListStore     *store;
628   GtkTreeSelection *selection;
629   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
630
631   store = gtk_list_store_new (COL_COUNT,
632       G_TYPE_BOOLEAN,        /* enabled */
633       G_TYPE_STRING,         /* name */
634       G_TYPE_UINT,           /* status */
635       EMPATHY_TYPE_ACCOUNT,   /* account */
636       EMPATHY_TYPE_ACCOUNT_SETTINGS); /* settings */
637
638   gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview),
639       GTK_TREE_MODEL (store));
640
641   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
642   gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
643
644   g_signal_connect (selection, "changed",
645       G_CALLBACK (accounts_dialog_model_selection_changed),
646       dialog);
647
648   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
649       COL_NAME, GTK_SORT_ASCENDING);
650
651   accounts_dialog_model_add_columns (dialog);
652
653   g_object_unref (store);
654 }
655
656 static gboolean
657 accounts_dialog_get_settings_iter (EmpathyAccountsDialog *dialog,
658     EmpathyAccountSettings *settings,
659     GtkTreeIter *iter)
660 {
661   GtkTreeView      *view;
662   GtkTreeSelection *selection;
663   GtkTreeModel     *model;
664   gboolean          ok;
665   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
666
667   /* Update the status in the model */
668   view = GTK_TREE_VIEW (priv->treeview);
669   selection = gtk_tree_view_get_selection (view);
670   model = gtk_tree_view_get_model (view);
671
672   for (ok = gtk_tree_model_get_iter_first (model, iter);
673        ok;
674        ok = gtk_tree_model_iter_next (model, iter))
675     {
676       EmpathyAccountSettings *this_settings;
677       gboolean   equal;
678
679       gtk_tree_model_get (model, iter,
680           COL_ACCOUNT_SETTINGS_POINTER, &this_settings,
681           -1);
682
683       equal = (this_settings == settings);
684       g_object_unref (this_settings);
685
686       if (equal)
687         return TRUE;
688     }
689
690   return FALSE;
691 }
692
693 static gboolean
694 accounts_dialog_get_account_iter (EmpathyAccountsDialog *dialog,
695     EmpathyAccount *account,
696     GtkTreeIter *iter)
697 {
698   GtkTreeView      *view;
699   GtkTreeSelection *selection;
700   GtkTreeModel     *model;
701   gboolean          ok;
702   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
703
704   /* Update the status in the model */
705   view = GTK_TREE_VIEW (priv->treeview);
706   selection = gtk_tree_view_get_selection (view);
707   model = gtk_tree_view_get_model (view);
708
709   for (ok = gtk_tree_model_get_iter_first (model, iter);
710        ok;
711        ok = gtk_tree_model_iter_next (model, iter))
712     {
713       EmpathyAccountSettings *settings;
714       gboolean   equal;
715
716       gtk_tree_model_get (model, iter,
717           COL_ACCOUNT_SETTINGS_POINTER, &settings,
718           -1);
719
720       equal = empathy_account_settings_has_account
721         (settings, account);
722       g_object_unref (settings);
723
724       if (equal)
725         return TRUE;
726     }
727
728   return FALSE;
729 }
730
731 static EmpathyAccount *
732 accounts_dialog_model_get_selected_account (EmpathyAccountsDialog *dialog)
733 {
734   GtkTreeView      *view;
735   GtkTreeModel     *model;
736   GtkTreeSelection *selection;
737   GtkTreeIter       iter;
738   EmpathyAccount   *account;
739   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
740
741   view = GTK_TREE_VIEW (priv->treeview);
742   selection = gtk_tree_view_get_selection (view);
743
744   if (!gtk_tree_selection_get_selected (selection, &model, &iter))
745     return NULL;
746
747   gtk_tree_model_get (model, &iter, COL_ACCOUNT_POINTER, &account, -1);
748
749   return account;
750 }
751
752 static void
753 accounts_dialog_model_set_selected (EmpathyAccountsDialog *dialog,
754     EmpathyAccountSettings *settings)
755 {
756   GtkTreeSelection *selection;
757   GtkTreeIter       iter;
758   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
759
760   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
761   if (accounts_dialog_get_settings_iter (dialog, settings, &iter))
762     gtk_tree_selection_select_iter (selection, &iter);
763 }
764
765 static gboolean
766 accounts_dialog_model_remove_selected (EmpathyAccountsDialog *dialog)
767 {
768   GtkTreeView      *view;
769   GtkTreeModel     *model;
770   GtkTreeSelection *selection;
771   GtkTreeIter       iter;
772   EmpathyAccount *account;
773   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
774
775   view = GTK_TREE_VIEW (priv->treeview);
776   selection = gtk_tree_view_get_selection (view);
777
778   if (!gtk_tree_selection_get_selected (selection, &model, &iter))
779     return FALSE;
780
781   gtk_tree_model_get (model, &iter,
782       COL_ACCOUNT_POINTER, &account,
783       -1);
784
785   if (account != NULL)
786     empathy_account_remove_async (account, NULL, NULL);
787
788   return gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
789 }
790
791 static void
792 accounts_dialog_add (EmpathyAccountsDialog *dialog,
793     EmpathyAccountSettings *settings)
794 {
795   GtkTreeModel       *model;
796   GtkTreeIter         iter;
797   const gchar        *name;
798   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
799
800   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
801   name = empathy_account_settings_get_display_name (settings);
802
803   gtk_list_store_append (GTK_LIST_STORE (model), &iter);
804
805   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
806       COL_ENABLED, FALSE,
807       COL_NAME, name,
808       COL_STATUS, TP_CONNECTION_STATUS_DISCONNECTED,
809       COL_ACCOUNT_SETTINGS_POINTER, settings,
810       -1);
811 }
812
813 static void
814 accounts_dialog_connection_changed_cb     (EmpathyAccountManager *manager,
815     EmpathyAccount *account,
816     TpConnectionStatusReason reason,
817     TpConnectionStatus current,
818     TpConnectionStatus previous,
819     EmpathyAccountsDialog *dialog)
820 {
821   GtkTreeModel *model;
822   GtkTreeIter   iter;
823   gboolean      found;
824   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
825
826   /* Update the status in the model */
827   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
828
829   if (accounts_dialog_get_account_iter (dialog, account, &iter))
830     {
831       GtkTreePath *path;
832
833       gtk_list_store_set (GTK_LIST_STORE (model), &iter,
834           COL_STATUS, current,
835           -1);
836
837       path = gtk_tree_model_get_path (model, &iter);
838       gtk_tree_model_row_changed (model, path, &iter);
839       gtk_tree_path_free (path);
840     }
841
842   found = (empathy_account_manager_get_connecting_accounts (manager) > 0);
843
844   if (!found && priv->connecting_id)
845     {
846       g_source_remove (priv->connecting_id);
847       priv->connecting_id = 0;
848     }
849
850   if (found && !priv->connecting_id)
851     priv->connecting_id = g_timeout_add (FLASH_TIMEOUT,
852         (GSourceFunc) accounts_dialog_flash_connecting_cb,
853         dialog);
854 }
855
856 static void
857 accounts_dialog_add_account (EmpathyAccountsDialog *dialog,
858     EmpathyAccount *account)
859 {
860   EmpathyAccountSettings *settings;
861   GtkTreeModel       *model;
862   GtkTreeIter         iter;
863   TpConnectionStatus  status;
864   const gchar        *name;
865   gboolean            enabled;
866   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
867
868   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
869   g_object_get (account, "connection-status", &status, NULL);
870   name = empathy_account_get_display_name (account);
871   enabled = empathy_account_is_enabled (account);
872
873   if (!accounts_dialog_get_account_iter (dialog, account, &iter))
874     gtk_list_store_append (GTK_LIST_STORE (model), &iter);
875
876   settings = empathy_account_settings_new_for_account (account);
877
878   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
879       COL_ENABLED, enabled,
880       COL_NAME, name,
881       COL_STATUS, status,
882       COL_ACCOUNT_POINTER, account,
883       COL_ACCOUNT_SETTINGS_POINTER, settings,
884       -1);
885
886   accounts_dialog_connection_changed_cb (priv->account_manager,
887       account,
888       TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED,
889       status,
890       TP_CONNECTION_STATUS_DISCONNECTED,
891       dialog);
892
893   g_object_unref (settings);
894 }
895
896 static void
897 accounts_dialog_update (EmpathyAccountsDialog *dialog,
898     EmpathyAccountSettings *settings)
899 {
900   GtkTreeModel       *model;
901   GtkTreeIter         iter;
902   TpConnectionStatus  status = TP_CONNECTION_STATUS_DISCONNECTED;
903   const gchar        *name;
904   gboolean            enabled = FALSE;
905   EmpathyAccount     *account;
906   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
907
908   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
909   name = empathy_account_settings_get_display_name (settings);
910
911   account = empathy_account_settings_get_account (settings);
912   if (account != NULL)
913     {
914       enabled = empathy_account_is_enabled (account);
915       g_object_get (account, "connection-status", &status, NULL);
916     }
917
918   accounts_dialog_get_settings_iter (dialog, settings, &iter);
919   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
920       COL_ENABLED, enabled,
921       COL_NAME, name,
922       COL_STATUS, status,
923       COL_ACCOUNT_POINTER, account,
924       COL_ACCOUNT_SETTINGS_POINTER, settings,
925       -1);
926 }
927
928 static void
929 accounts_dialog_account_added_cb (EmpathyAccountManager *manager,
930     EmpathyAccount *account,
931     EmpathyAccountsDialog *dialog)
932 {
933   accounts_dialog_add_account (dialog, account);
934 }
935
936
937 static void
938 accounts_dialog_account_removed_cb (EmpathyAccountManager *manager,
939     EmpathyAccount *account,
940     EmpathyAccountsDialog *dialog)
941 {
942   GtkTreeIter iter;
943   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
944
945   if (accounts_dialog_get_account_iter (dialog, account, &iter))
946     gtk_list_store_remove (GTK_LIST_STORE (
947             gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview))), &iter);
948 }
949
950 static void
951 enable_or_disable_account (EmpathyAccountsDialog *dialog,
952     EmpathyAccount *account,
953     gboolean enabled)
954 {
955   GtkTreeModel *model;
956   GtkTreeIter   iter;
957   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
958
959   /* Update the status in the model */
960   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
961
962   DEBUG ("Account %s is now %s",
963       empathy_account_get_display_name (account),
964       enabled ? "enabled" : "disabled");
965
966   if (accounts_dialog_get_account_iter (dialog, account, &iter))
967     gtk_list_store_set (GTK_LIST_STORE (model), &iter,
968         COL_ENABLED, enabled,
969         -1);
970 }
971
972 static void
973 accounts_dialog_account_disabled_cb (EmpathyAccountManager *manager,
974     EmpathyAccount *account,
975     EmpathyAccountsDialog *dialog)
976 {
977   enable_or_disable_account (dialog, account, FALSE);
978 }
979
980 static void
981 accounts_dialog_account_enabled_cb (EmpathyAccountManager *manager,
982     EmpathyAccount *account,
983     EmpathyAccountsDialog *dialog)
984 {
985   enable_or_disable_account (dialog, account, TRUE);
986 }
987
988 static void
989 accounts_dialog_account_changed_cb (EmpathyAccountManager *manager,
990     EmpathyAccount *account,
991     EmpathyAccountsDialog  *dialog)
992 {
993   EmpathyAccountSettings *settings, *selected_settings;
994   GtkTreeModel *model;
995   GtkTreeIter iter;
996   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
997
998   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
999
1000   if (!accounts_dialog_get_account_iter (dialog, account, &iter))
1001     return;
1002
1003   gtk_tree_model_get (model, &iter,
1004       COL_ACCOUNT_SETTINGS_POINTER, &settings,
1005       -1);
1006
1007   accounts_dialog_update (dialog, settings);
1008   selected_settings = accounts_dialog_model_get_selected_settings (dialog);
1009
1010   if (settings == selected_settings)
1011     accounts_dialog_update_name_label (dialog, settings);
1012 }
1013
1014 static void
1015 accounts_dialog_button_create_clicked_cb (GtkWidget *button,
1016     EmpathyAccountsDialog *dialog)
1017 {
1018   EmpathyAccountSettings *settings;
1019   gchar     *str;
1020   TpConnectionManager *cm;
1021   TpConnectionManagerProtocol *proto;
1022   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1023
1024   cm = empathy_protocol_chooser_dup_selected (
1025       EMPATHY_PROTOCOL_CHOOSER (priv->combobox_protocol), &proto);
1026
1027   /* Create account */
1028   /* To translator: %s is the protocol name */
1029   str = g_strdup_printf (_("New %s account"), proto->name);
1030
1031   settings = empathy_account_settings_new (cm->name, proto->name, str);
1032
1033   g_free (str);
1034
1035   if (tp_connection_manager_protocol_can_register (proto))
1036     {
1037       gboolean active;
1038
1039       active = gtk_toggle_button_get_active
1040           (GTK_TOGGLE_BUTTON (priv->radiobutton_register));
1041       if (active)
1042         empathy_account_settings_set_boolean (settings, "register", TRUE);
1043     }
1044
1045   accounts_dialog_add (dialog, settings);
1046   accounts_dialog_model_set_selected (dialog, settings);
1047
1048   g_object_unref (settings);
1049   g_object_unref (cm);
1050 }
1051
1052 static void
1053 accounts_dialog_button_back_clicked_cb (GtkWidget *button,
1054     EmpathyAccountsDialog *dialog)
1055 {
1056   EmpathyAccountSettings *settings;
1057
1058   settings = accounts_dialog_model_get_selected_settings (dialog);
1059   accounts_dialog_update (dialog, settings);
1060 }
1061
1062 static void
1063 accounts_dialog_button_help_clicked_cb (GtkWidget *button,
1064     EmpathyAccountsDialog *dialog)
1065 {
1066   empathy_url_show (button, "ghelp:empathy?empathy-create-account");
1067 }
1068
1069 static void
1070 accounts_dialog_button_remove_clicked_cb (GtkWidget *button,
1071     EmpathyAccountsDialog *dialog)
1072 {
1073   EmpathyAccount *account;
1074   GtkWidget *message_dialog;
1075   gint       res;
1076   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1077
1078   account = accounts_dialog_model_get_selected_account (dialog);
1079
1080   if (account == NULL || !empathy_account_is_valid (account))
1081     {
1082       accounts_dialog_model_remove_selected (dialog);
1083       accounts_dialog_model_select_first (dialog);
1084       return;
1085     }
1086   message_dialog = gtk_message_dialog_new
1087     (GTK_WINDOW (priv->window),
1088         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1089         GTK_MESSAGE_QUESTION,
1090         GTK_BUTTONS_NONE,
1091         _("You are about to remove your %s account!\n"
1092             "Are you sure you want to proceed?"),
1093         empathy_account_get_display_name (account));
1094
1095   gtk_message_dialog_format_secondary_text
1096     (GTK_MESSAGE_DIALOG (message_dialog),
1097         _("Any associated conversations and chat rooms will NOT be "
1098             "removed if you decide to proceed.\n"
1099             "\n"
1100             "Should you decide to add the account back at a later time, "
1101             "they will still be available."));
1102
1103   gtk_dialog_add_button (GTK_DIALOG (message_dialog),
1104       GTK_STOCK_CANCEL,
1105       GTK_RESPONSE_NO);
1106   gtk_dialog_add_button (GTK_DIALOG (message_dialog),
1107       GTK_STOCK_REMOVE,
1108       GTK_RESPONSE_YES);
1109
1110   gtk_widget_show (message_dialog);
1111   res = gtk_dialog_run (GTK_DIALOG (message_dialog));
1112
1113   if (res == GTK_RESPONSE_YES)
1114     {
1115       accounts_dialog_model_remove_selected (dialog);
1116       accounts_dialog_model_select_first (dialog);
1117     }
1118   gtk_widget_destroy (message_dialog);
1119 }
1120
1121 #if 0
1122 /* FIXME MC-5 */
1123 static void
1124 accounts_dialog_button_import_clicked_cb (GtkWidget *button,
1125     EmpathyAccountsDialog *dialog)
1126 {
1127   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1128
1129   empathy_import_dialog_show (GTK_WINDOW (priv->window), TRUE);
1130 }
1131 #endif
1132
1133 static void
1134 accounts_dialog_response_cb (GtkWidget *widget,
1135     gint response,
1136     EmpathyAccountsDialog *dialog)
1137 {
1138   GList *accounts, *l;
1139   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1140
1141   if (response == GTK_RESPONSE_CLOSE)
1142     {
1143       /* Delete incomplete accounts */
1144       accounts = empathy_account_manager_dup_accounts
1145         (priv->account_manager);
1146       for (l = accounts; l; l = l->next)
1147         {
1148           EmpathyAccount *account;
1149
1150           account = l->data;
1151           if (!empathy_account_is_valid (account))
1152             /* FIXME: Warn the user the account is not
1153              * complete and is going to be removed.
1154              */
1155             empathy_account_manager_remove
1156               (priv->account_manager, account);
1157
1158           g_object_unref (account);
1159         }
1160       g_list_free (accounts);
1161
1162       gtk_widget_destroy (widget);
1163     }
1164 }
1165
1166 static void
1167 accounts_dialog_destroy_cb (GtkObject *obj,
1168     EmpathyAccountsDialog *dialog)
1169 {
1170   DEBUG ("%p", obj);
1171
1172   g_object_unref (dialog);
1173 }
1174
1175 static void
1176 accounts_dialog_set_selected_account (EmpathyAccountsDialog *dialog,
1177     EmpathyAccount *account)
1178 {
1179   GtkTreeSelection *selection;
1180   GtkTreeIter       iter;
1181   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1182
1183   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
1184   if (accounts_dialog_get_account_iter (dialog, account, &iter))
1185     gtk_tree_selection_select_iter (selection, &iter);
1186 }
1187
1188 static void
1189 accounts_dialog_cms_ready_cb (EmpathyConnectionManagers *cms,
1190     GParamSpec *pspec,
1191     EmpathyAccountsDialog *dialog)
1192 {
1193   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1194
1195   if (empathy_connection_managers_is_ready (cms))
1196     {
1197       accounts_dialog_update_settings (dialog, NULL);
1198
1199       if (priv->initial_selection != NULL)
1200         {
1201           accounts_dialog_set_selected_account
1202               (dialog, priv->initial_selection);
1203           priv->initial_selection = NULL;
1204         }
1205     }
1206 }
1207
1208 static void
1209 accounts_dialog_build_ui (EmpathyAccountsDialog *dialog)
1210 {
1211   GtkBuilder                   *gui;
1212   gchar                        *filename;
1213   EmpathyAccountsDialogPriv    *priv = GET_PRIV (dialog);
1214
1215   filename = empathy_file_lookup ("empathy-accounts-dialog.ui", "src");
1216
1217   gui = empathy_builder_get_file (filename,
1218       "accounts_dialog", &priv->window,
1219       "vbox_details", &priv->vbox_details,
1220       "frame_no_protocol", &priv->frame_no_protocol,
1221       "alignment_settings", &priv->alignment_settings,
1222       "treeview", &priv->treeview,
1223       "frame_new_account", &priv->frame_new_account,
1224       "hbox_type", &priv->hbox_type,
1225       "button_create", &priv->button_create,
1226       "button_back", &priv->button_back,
1227       "radiobutton_reuse", &priv->radiobutton_reuse,
1228       "radiobutton_register", &priv->radiobutton_register,
1229       "image_type", &priv->image_type,
1230       "label_name", &priv->label_name,
1231       "button_add", &priv->button_add,
1232       "button_remove", &priv->button_remove,
1233       "button_import", &priv->button_import,
1234       NULL);
1235   g_free (filename);
1236
1237   empathy_builder_connect (gui, dialog,
1238       "accounts_dialog", "response", accounts_dialog_response_cb,
1239       "accounts_dialog", "destroy", accounts_dialog_destroy_cb,
1240       "button_create", "clicked", accounts_dialog_button_create_clicked_cb,
1241       "button_back", "clicked", accounts_dialog_button_back_clicked_cb,
1242       "button_add", "clicked", accounts_dialog_button_add_clicked_cb,
1243       "button_remove", "clicked", accounts_dialog_button_remove_clicked_cb,
1244 #if 0
1245       /* FIXME MC-5  */
1246       "button_import", "clicked", accounts_dialog_button_import_clicked_cb,
1247 #endif
1248       "button_help", "clicked", accounts_dialog_button_help_clicked_cb,
1249       NULL);
1250
1251   g_object_unref (gui);
1252
1253   priv->combobox_protocol = empathy_protocol_chooser_new ();
1254   gtk_box_pack_end (GTK_BOX (priv->hbox_type),
1255       priv->combobox_protocol,
1256       TRUE, TRUE, 0);
1257   gtk_widget_show (priv->combobox_protocol);
1258   g_signal_connect (priv->combobox_protocol, "changed",
1259       G_CALLBACK (accounts_dialog_protocol_changed_cb),
1260       dialog);
1261
1262   if (priv->parent_window)
1263     gtk_window_set_transient_for (GTK_WINDOW (priv->window),
1264         priv->parent_window);
1265 }
1266
1267 static void
1268 do_dispose (GObject *obj)
1269 {
1270   EmpathyAccountsDialog *dialog = EMPATHY_ACCOUNTS_DIALOG (obj);
1271   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1272
1273   /* Disconnect signals */
1274   g_signal_handlers_disconnect_by_func (priv->account_manager,
1275       accounts_dialog_account_added_cb,
1276       dialog);
1277   g_signal_handlers_disconnect_by_func (priv->account_manager,
1278       accounts_dialog_account_removed_cb,
1279       dialog);
1280   g_signal_handlers_disconnect_by_func (priv->account_manager,
1281       accounts_dialog_account_enabled_cb,
1282       dialog);
1283   g_signal_handlers_disconnect_by_func (priv->account_manager,
1284       accounts_dialog_account_disabled_cb,
1285       dialog);
1286   g_signal_handlers_disconnect_by_func (priv->account_manager,
1287       accounts_dialog_account_changed_cb,
1288       dialog);
1289   g_signal_handlers_disconnect_by_func (priv->account_manager,
1290       accounts_dialog_connection_changed_cb,
1291       dialog);
1292
1293   if (priv->connecting_id)
1294     g_source_remove (priv->connecting_id);
1295
1296   if (priv->account_manager != NULL)
1297     {
1298       g_object_unref (priv->account_manager);
1299       priv->account_manager = NULL;
1300     }
1301
1302   if (priv->cms != NULL)
1303     {
1304       g_object_unref (priv->cms);
1305       priv->cms = NULL;
1306     }
1307
1308   G_OBJECT_CLASS (empathy_accounts_dialog_parent_class)->dispose (obj);
1309 }
1310
1311 static GObject *
1312 do_constructor (GType type,
1313     guint n_props,
1314     GObjectConstructParam *props)
1315 {
1316   GObject *retval;
1317
1318   if (dialog_singleton)
1319     {
1320       retval = G_OBJECT (dialog_singleton);
1321     }
1322   else
1323     {
1324       retval =
1325         G_OBJECT_CLASS (empathy_accounts_dialog_parent_class)->constructor
1326             (type, n_props, props);
1327
1328       dialog_singleton = EMPATHY_ACCOUNTS_DIALOG (retval);
1329       g_object_add_weak_pointer (retval, (gpointer) &dialog_singleton);
1330     }
1331
1332   return retval;
1333 }
1334
1335 static void
1336 do_get_property (GObject *object,
1337     guint property_id,
1338     GValue *value,
1339     GParamSpec *pspec)
1340 {
1341   EmpathyAccountsDialogPriv *priv = GET_PRIV (object);
1342
1343   switch (property_id)
1344     {
1345     case PROP_PARENT:
1346       g_value_set_object (value, priv->parent_window);
1347       break;
1348     default:
1349       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1350     }
1351 }
1352
1353 static void
1354 do_set_property (GObject *object,
1355     guint property_id,
1356     const GValue *value,
1357     GParamSpec *pspec)
1358 {
1359   EmpathyAccountsDialogPriv *priv = GET_PRIV (object);
1360
1361   switch (property_id)
1362     {
1363     case PROP_PARENT:
1364       priv->parent_window = g_value_get_object (value);
1365       break;
1366     default:
1367       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1368     }
1369 }
1370
1371 static void
1372 do_constructed (GObject *object)
1373 {
1374   EmpathyAccountsDialog *dialog = EMPATHY_ACCOUNTS_DIALOG (object);
1375   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1376   GList *accounts, *l;
1377   gboolean import_asked;
1378
1379   accounts_dialog_build_ui (dialog);
1380
1381   /* Set up signalling */
1382   priv->account_manager = empathy_account_manager_dup_singleton ();
1383
1384   g_signal_connect (priv->account_manager, "account-created",
1385       G_CALLBACK (accounts_dialog_account_added_cb),
1386       dialog);
1387   g_signal_connect (priv->account_manager, "account-deleted",
1388       G_CALLBACK (accounts_dialog_account_removed_cb),
1389       dialog);
1390   g_signal_connect (priv->account_manager, "account-enabled",
1391       G_CALLBACK (accounts_dialog_account_enabled_cb),
1392       dialog);
1393   g_signal_connect (priv->account_manager, "account-disabled",
1394       G_CALLBACK (accounts_dialog_account_disabled_cb),
1395       dialog);
1396   g_signal_connect (priv->account_manager, "account-changed",
1397       G_CALLBACK (accounts_dialog_account_changed_cb),
1398       dialog);
1399   g_signal_connect (priv->account_manager, "account-connection-changed",
1400       G_CALLBACK (accounts_dialog_connection_changed_cb),
1401       dialog);
1402
1403   accounts_dialog_model_setup (dialog);
1404
1405   /* Add existing accounts */
1406   accounts = empathy_account_manager_dup_accounts (priv->account_manager);
1407   for (l = accounts; l; l = l->next)
1408     {
1409       accounts_dialog_add_account (dialog, l->data);
1410       g_object_unref (l->data);
1411     }
1412   g_list_free (accounts);
1413
1414   priv->cms = empathy_connection_managers_dup_singleton ();
1415   if (!empathy_connection_managers_is_ready (priv->cms))
1416     g_signal_connect (priv->cms, "notify::ready",
1417         G_CALLBACK (accounts_dialog_cms_ready_cb), dialog);
1418
1419   accounts_dialog_model_select_first (dialog);
1420
1421   empathy_conf_get_bool (empathy_conf_get (),
1422       EMPATHY_PREFS_IMPORT_ASKED, &import_asked);
1423
1424
1425 #if 0
1426   /* FIXME MC-5 */
1427   if (empathy_import_dialog_accounts_to_import ())
1428     {
1429
1430       if (!import_asked)
1431         {
1432           empathy_conf_set_bool (empathy_conf_get (),
1433               EMPATHY_PREFS_IMPORT_ASKED, TRUE);
1434           empathy_import_dialog_show (GTK_WINDOW (priv->window),
1435               FALSE);
1436         }
1437     }
1438   else
1439     {
1440       gtk_widget_set_sensitive (priv->button_import, FALSE);
1441     }
1442 #endif
1443 }
1444
1445 static void
1446 empathy_accounts_dialog_class_init (EmpathyAccountsDialogClass *klass)
1447 {
1448   GObjectClass *oclass = G_OBJECT_CLASS (klass);
1449   GParamSpec *param_spec;
1450
1451   oclass->constructor = do_constructor;
1452   oclass->dispose = do_dispose;
1453   oclass->constructed = do_constructed;
1454   oclass->set_property = do_set_property;
1455   oclass->get_property = do_get_property;
1456
1457   param_spec = g_param_spec_object ("parent",
1458       "parent", "The parent window",
1459       GTK_TYPE_WINDOW,
1460       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1461   g_object_class_install_property (oclass, PROP_PARENT, param_spec);
1462
1463   g_type_class_add_private (klass, sizeof (EmpathyAccountsDialogPriv));
1464 }
1465
1466 static void
1467 empathy_accounts_dialog_init (EmpathyAccountsDialog *dialog)
1468 {
1469   EmpathyAccountsDialogPriv *priv;
1470
1471   priv = G_TYPE_INSTANCE_GET_PRIVATE ((dialog),
1472       EMPATHY_TYPE_ACCOUNTS_DIALOG,
1473       EmpathyAccountsDialogPriv);
1474   dialog->priv = priv;
1475 }
1476
1477 /* public methods */
1478
1479 GtkWidget *
1480 empathy_accounts_dialog_show (GtkWindow *parent,
1481     EmpathyAccount *selected_account)
1482 {
1483   EmpathyAccountsDialog *dialog;
1484   EmpathyAccountsDialogPriv *priv;
1485
1486   dialog = g_object_new (EMPATHY_TYPE_ACCOUNTS_DIALOG,
1487       "parent", parent, NULL);
1488
1489   priv = GET_PRIV (dialog);
1490
1491   if (selected_account && empathy_connection_managers_is_ready (priv->cms))
1492     accounts_dialog_set_selected_account (dialog, selected_account);
1493   else
1494     /* save the selection to set it later when the cms
1495      * becomes ready.
1496      */
1497     priv->initial_selection = selected_account;
1498
1499   gtk_window_present (GTK_WINDOW (priv->window));
1500
1501   return priv->window;
1502 }