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