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