]> git.0d.be Git - empathy.git/blob - src/empathy-accounts-dialog.c
Make sure the account dialog respects the initial selection
[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                 EmpathyAccount *this_account;
617                 gboolean   equal;
618
619                 gtk_tree_model_get (model, iter,
620                                     COL_ACCOUNT_POINTER, &this_account,
621                                     -1);
622
623                 equal = (this_account == account);
624                 g_object_unref (this_account);
625
626                 if (equal) {
627                         return TRUE;
628                 }
629         }
630
631         return FALSE;
632 }
633
634 static EmpathyAccountSettings *
635 accounts_dialog_model_get_selected_settings (EmpathyAccountsDialog *dialog)
636 {
637         GtkTreeView      *view;
638         GtkTreeModel     *model;
639         GtkTreeSelection *selection;
640         GtkTreeIter       iter;
641         EmpathyAccountSettings   *settings;
642         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
643
644         view = GTK_TREE_VIEW (priv->treeview);
645         selection = gtk_tree_view_get_selection (view);
646
647         if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
648                 return NULL;
649         }
650
651         gtk_tree_model_get (model, &iter,
652                 COL_ACCOUNT_SETTINGS_POINTER, &settings, -1);
653
654         return settings;
655 }
656
657
658 static EmpathyAccount *
659 accounts_dialog_model_get_selected_account (EmpathyAccountsDialog *dialog)
660 {
661         GtkTreeView      *view;
662         GtkTreeModel     *model;
663         GtkTreeSelection *selection;
664         GtkTreeIter       iter;
665         EmpathyAccount   *account;
666         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
667
668         view = GTK_TREE_VIEW (priv->treeview);
669         selection = gtk_tree_view_get_selection (view);
670
671         if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
672                 return NULL;
673         }
674
675         gtk_tree_model_get (model, &iter, COL_ACCOUNT_POINTER, &account, -1);
676
677         return account;
678 }
679
680 static void
681 accounts_dialog_model_set_selected (EmpathyAccountsDialog *dialog,
682                                     EmpathyAccountSettings        *settings)
683 {
684         GtkTreeSelection *selection;
685         GtkTreeIter       iter;
686         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
687
688         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
689         if (accounts_dialog_get_settings_iter (dialog, settings, &iter)) {
690                 gtk_tree_selection_select_iter (selection, &iter);
691         }
692 }
693
694 static gboolean
695 accounts_dialog_model_remove_selected (EmpathyAccountsDialog *dialog)
696 {
697         GtkTreeView      *view;
698         GtkTreeModel     *model;
699         GtkTreeSelection *selection;
700         GtkTreeIter       iter;
701         EmpathyAccount *account;
702         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
703
704         view = GTK_TREE_VIEW (priv->treeview);
705         selection = gtk_tree_view_get_selection (view);
706
707         if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
708                 return FALSE;
709         }
710
711         gtk_tree_model_get (model, &iter,
712                             COL_ACCOUNT_POINTER, &account,
713                             -1);
714
715         if (account != NULL)
716                 empathy_account_remove_async (account, NULL, NULL);
717
718         return gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
719 }
720
721 static void
722 accounts_dialog_model_selection_changed (GtkTreeSelection     *selection,
723                                          EmpathyAccountsDialog *dialog)
724 {
725         EmpathyAccountSettings *settings;
726         GtkTreeModel *model;
727         GtkTreeIter   iter;
728         gboolean      is_selection;
729
730         is_selection = gtk_tree_selection_get_selected (selection, &model, &iter);
731
732         settings = accounts_dialog_model_get_selected_settings (dialog);
733         accounts_dialog_update_settings (dialog, settings);
734
735         if (settings) {
736                 g_object_unref (settings);
737         }
738 }
739
740 static void
741 accounts_dialog_add (EmpathyAccountsDialog *dialog,
742                                        EmpathyAccountSettings        *settings)
743 {
744         GtkTreeModel       *model;
745         GtkTreeIter         iter;
746         const gchar        *name;
747         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
748
749         model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
750         name = empathy_account_settings_get_display_name (settings);
751
752         gtk_list_store_append (GTK_LIST_STORE (model), &iter);
753
754         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
755                             COL_ENABLED, FALSE,
756                             COL_NAME, name,
757                             COL_STATUS, TP_CONNECTION_STATUS_DISCONNECTED,
758                             COL_ACCOUNT_SETTINGS_POINTER, settings,
759                             -1);
760 }
761
762
763 static void
764 accounts_dialog_add_account (EmpathyAccountsDialog *dialog,
765                                        EmpathyAccount        *account)
766 {
767         EmpathyAccountSettings *settings;
768         GtkTreeModel       *model;
769         GtkTreeIter         iter;
770         TpConnectionStatus  status;
771         const gchar        *name;
772         gboolean            enabled;
773         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
774
775         model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
776         g_object_get (account, "status", &status, NULL);
777         name = empathy_account_get_display_name (account);
778         enabled = empathy_account_is_enabled (account);
779
780         gtk_list_store_append (GTK_LIST_STORE (model), &iter);
781
782         settings = empathy_account_settings_new_for_account (account);
783
784         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
785                             COL_ENABLED, enabled,
786                             COL_NAME, name,
787                             COL_STATUS, status,
788                             COL_ACCOUNT_POINTER, account,
789                             COL_ACCOUNT_SETTINGS_POINTER, settings,
790                             -1);
791
792         accounts_dialog_connection_changed_cb (priv->account_manager,
793                                                account,
794                                                TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED,
795                                                status,
796                                                TP_CONNECTION_STATUS_DISCONNECTED,
797                                                dialog);
798
799         g_object_unref (settings);
800 }
801
802 static void
803 accounts_dialog_update (EmpathyAccountsDialog *dialog,
804                                        EmpathyAccountSettings        *settings)
805 {
806         GtkTreeModel       *model;
807         GtkTreeIter         iter;
808         TpConnectionStatus  status = TP_CONNECTION_STATUS_DISCONNECTED;
809         const gchar        *name;
810         gboolean            enabled = FALSE;
811         EmpathyAccount     *account;
812         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
813
814         model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
815         name = empathy_account_settings_get_display_name (settings);
816
817         account = empathy_account_settings_get_account (settings);
818         if (account != NULL)
819                 {
820                         enabled = empathy_account_is_enabled (account);
821                         g_object_get (account, "connection-status", &status, NULL);
822                 }
823
824         accounts_dialog_get_settings_iter (dialog, settings, &iter);
825         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
826                             COL_ENABLED, enabled,
827                             COL_NAME, name,
828                             COL_STATUS, status,
829                             COL_ACCOUNT_POINTER, account,
830                             COL_ACCOUNT_SETTINGS_POINTER, settings,
831                             -1);
832 }
833
834 static void
835 accounts_dialog_account_added_cb (EmpathyAccountManager *manager,
836                                   EmpathyAccount *account,
837                                   EmpathyAccountsDialog *dialog)
838 {
839         accounts_dialog_add_account (dialog, account);
840 }
841
842
843 static void
844 accounts_dialog_account_removed_cb (EmpathyAccountManager *manager,
845                                     EmpathyAccount       *account,
846                                     EmpathyAccountsDialog *dialog)
847 {
848         GtkTreeIter iter;
849         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
850
851         if (accounts_dialog_get_account_iter (dialog, account, &iter))
852                 gtk_list_store_remove (GTK_LIST_STORE (
853                         gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview))), &iter);
854 }
855
856 static gboolean
857 accounts_dialog_row_changed_foreach (GtkTreeModel *model,
858                                      GtkTreePath  *path,
859                                      GtkTreeIter  *iter,
860                                      gpointer      user_data)
861 {
862         gtk_tree_model_row_changed (model, path, iter);
863
864         return FALSE;
865 }
866
867 static gboolean
868 accounts_dialog_flash_connecting_cb (EmpathyAccountsDialog *dialog)
869 {
870         GtkTreeView  *view;
871         GtkTreeModel *model;
872         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
873
874         priv->connecting_show = !priv->connecting_show;
875
876         view = GTK_TREE_VIEW (priv->treeview);
877         model = gtk_tree_view_get_model (view);
878
879         gtk_tree_model_foreach (model, accounts_dialog_row_changed_foreach, NULL);
880
881         return TRUE;
882 }
883
884 static void
885 accounts_dialog_connection_changed_cb     (EmpathyAccountManager    *manager,
886                                            EmpathyAccount           *account,
887                                            TpConnectionStatusReason  reason,
888                                            TpConnectionStatus        current,
889                                            TpConnectionStatus        previous,
890                                            EmpathyAccountsDialog    *dialog)
891 {
892         GtkTreeModel *model;
893         GtkTreeIter   iter;
894         gboolean      found;
895         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
896
897         /* Update the status in the model */
898         model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
899
900         if (accounts_dialog_get_account_iter (dialog, account, &iter)) {
901                 GtkTreePath *path;
902
903                 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
904                                     COL_STATUS, current,
905                                     -1);
906
907                 path = gtk_tree_model_get_path (model, &iter);
908                 gtk_tree_model_row_changed (model, path, &iter);
909                 gtk_tree_path_free (path);
910         }
911
912         found = (empathy_account_manager_get_connecting_accounts (manager) > 0);
913
914         if (!found && priv->connecting_id) {
915                 g_source_remove (priv->connecting_id);
916                 priv->connecting_id = 0;
917         }
918
919         if (found && !priv->connecting_id) {
920                 priv->connecting_id = g_timeout_add (FLASH_TIMEOUT,
921                                                        (GSourceFunc) accounts_dialog_flash_connecting_cb,
922                                                        dialog);
923         }
924 }
925
926 static void
927 enable_or_disable_account (EmpathyAccountsDialog *dialog,
928                            EmpathyAccount *account,
929                            gboolean enabled)
930 {
931         GtkTreeModel *model;
932         GtkTreeIter   iter;
933         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
934
935         /* Update the status in the model */
936         model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
937
938         DEBUG ("Account %s is now %s",
939                 empathy_account_get_display_name (account),
940                 enabled ? "enabled" : "disabled");
941
942         if (accounts_dialog_get_account_iter (dialog, account, &iter)) {
943                 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
944                                     COL_ENABLED, enabled,
945                                     -1);
946         }
947 }
948
949 static void
950 accounts_dialog_account_disabled_cb (EmpathyAccountManager *manager,
951                                      EmpathyAccount        *account,
952                                      EmpathyAccountsDialog *dialog)
953 {
954         enable_or_disable_account (dialog, account, FALSE);
955 }
956
957 static void
958 accounts_dialog_account_enabled_cb (EmpathyAccountManager *manager,
959                                     EmpathyAccount        *account,
960                                     EmpathyAccountsDialog *dialog)
961 {
962         enable_or_disable_account (dialog, account, TRUE);
963 }
964
965 static void
966 accounts_dialog_account_changed_cb (EmpathyAccountManager *manager,
967                                     EmpathyAccount        *account,
968                                     EmpathyAccountsDialog  *dialog)
969 {
970         EmpathyAccountSettings *settings, *selected_settings;
971         GtkTreeModel *model;
972         GtkTreeIter iter;
973         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
974
975         model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
976
977         if (!accounts_dialog_get_account_iter (dialog, account, &iter))
978                 return;
979
980         gtk_tree_model_get (model, &iter,
981                 COL_ACCOUNT_SETTINGS_POINTER, &settings,
982                 -1);
983
984         accounts_dialog_update (dialog, settings);
985         selected_settings = accounts_dialog_model_get_selected_settings (dialog);
986
987         if (settings == selected_settings)
988                 accounts_dialog_update_name_label (dialog, settings);
989 }
990
991 static void
992 accounts_dialog_button_create_clicked_cb (GtkWidget             *button,
993                                           EmpathyAccountsDialog  *dialog)
994 {
995         EmpathyAccountSettings *settings;
996         gchar     *str;
997         TpConnectionManager *cm;
998         TpConnectionManagerProtocol *proto;
999         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1000
1001         cm = empathy_protocol_chooser_dup_selected (
1002             EMPATHY_PROTOCOL_CHOOSER (priv->combobox_protocol), &proto);
1003
1004         /* Create account */
1005         /* To translator: %s is the protocol name */
1006         str = g_strdup_printf (_("New %s account"), proto->name);
1007
1008         settings = empathy_account_settings_new (cm->name, proto->name, str);
1009
1010         g_free (str);
1011
1012         if (tp_connection_manager_protocol_can_register (proto)) {
1013                 gboolean active;
1014
1015                 active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->radiobutton_register));
1016                 if (active) {
1017                         empathy_account_settings_set_boolean (settings, "register", TRUE);
1018                 }
1019         }
1020
1021         accounts_dialog_add (dialog, settings);
1022         accounts_dialog_model_set_selected (dialog, settings);
1023
1024         g_object_unref (settings);
1025         g_object_unref (cm);
1026 }
1027
1028 static void
1029 accounts_dialog_button_back_clicked_cb (GtkWidget             *button,
1030                                         EmpathyAccountsDialog  *dialog)
1031 {
1032         EmpathyAccountSettings *settings;
1033
1034         settings = accounts_dialog_model_get_selected_settings (dialog);
1035         accounts_dialog_update (dialog, settings);
1036 }
1037
1038 static void
1039 accounts_dialog_protocol_changed_cb (GtkWidget             *widget,
1040                                     EmpathyAccountsDialog *dialog)
1041 {
1042         TpConnectionManager *cm;
1043         TpConnectionManagerProtocol *proto;
1044         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1045
1046         cm = empathy_protocol_chooser_dup_selected (
1047             EMPATHY_PROTOCOL_CHOOSER (priv->combobox_protocol), &proto);
1048
1049         if (tp_connection_manager_protocol_can_register (proto)) {
1050                 gtk_widget_show (priv->radiobutton_register);
1051                 gtk_widget_show (priv->radiobutton_reuse);
1052         } else {
1053                 gtk_widget_hide (priv->radiobutton_register);
1054                 gtk_widget_hide (priv->radiobutton_reuse);
1055         }
1056         g_object_unref (cm);
1057 }
1058
1059 static void
1060 accounts_dialog_button_add_clicked_cb (GtkWidget             *button,
1061                                        EmpathyAccountsDialog *dialog)
1062 {
1063         GtkTreeView      *view;
1064         GtkTreeSelection *selection;
1065         GtkTreeModel     *model;
1066         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1067
1068         view = GTK_TREE_VIEW (priv->treeview);
1069         model = gtk_tree_view_get_model (view);
1070         selection = gtk_tree_view_get_selection (view);
1071         gtk_tree_selection_unselect_all (selection);
1072
1073         gtk_widget_set_sensitive (priv->button_add, FALSE);
1074         gtk_widget_set_sensitive (priv->button_remove, FALSE);
1075         gtk_widget_hide (priv->vbox_details);
1076         gtk_widget_hide (priv->frame_no_protocol);
1077         gtk_widget_show (priv->frame_new_account);
1078
1079         /* If we have no account, no need of a back button */
1080         if (gtk_tree_model_iter_n_children (model, NULL) > 0) {
1081                 gtk_widget_show (priv->button_back);
1082         } else {
1083                 gtk_widget_hide (priv->button_back);
1084         }
1085
1086         accounts_dialog_protocol_changed_cb (priv->radiobutton_register, dialog);
1087         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->radiobutton_reuse),
1088                                       TRUE);
1089         gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combobox_protocol), 0);
1090         gtk_widget_grab_focus (priv->combobox_protocol);
1091 }
1092
1093 static void
1094 accounts_dialog_button_help_clicked_cb (GtkWidget             *button,
1095                                         EmpathyAccountsDialog *dialog)
1096 {
1097         empathy_url_show (button, "ghelp:empathy?empathy-create-account");
1098 }
1099
1100 static void
1101 accounts_dialog_button_remove_clicked_cb (GtkWidget            *button,
1102                                           EmpathyAccountsDialog *dialog)
1103 {
1104         EmpathyAccount *account;
1105         GtkWidget *message_dialog;
1106         gint       res;
1107         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1108
1109         account = accounts_dialog_model_get_selected_account (dialog);
1110
1111         if (account == NULL || !empathy_account_is_valid (account)) {
1112                 accounts_dialog_model_remove_selected (dialog);
1113                 accounts_dialog_model_select_first (dialog);
1114                 return;
1115         }
1116         message_dialog = gtk_message_dialog_new
1117                 (GTK_WINDOW (priv->window),
1118                  GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1119                  GTK_MESSAGE_QUESTION,
1120                  GTK_BUTTONS_NONE,
1121                  _("You are about to remove your %s account!\n"
1122                    "Are you sure you want to proceed?"),
1123                  empathy_account_get_display_name (account));
1124
1125         gtk_message_dialog_format_secondary_text
1126                 (GTK_MESSAGE_DIALOG (message_dialog),
1127                  _("Any associated conversations and chat rooms will NOT be "
1128                    "removed if you decide to proceed.\n"
1129                    "\n"
1130                    "Should you decide to add the account back at a later time, "
1131                    "they will still be available."));
1132
1133         gtk_dialog_add_button (GTK_DIALOG (message_dialog),
1134                                GTK_STOCK_CANCEL,
1135                                GTK_RESPONSE_NO);
1136         gtk_dialog_add_button (GTK_DIALOG (message_dialog),
1137                                GTK_STOCK_REMOVE,
1138                                GTK_RESPONSE_YES);
1139
1140         gtk_widget_show (message_dialog);
1141         res = gtk_dialog_run (GTK_DIALOG (message_dialog));
1142
1143         if (res == GTK_RESPONSE_YES) {
1144                 accounts_dialog_model_remove_selected (dialog);
1145                 accounts_dialog_model_select_first (dialog);
1146         }
1147         gtk_widget_destroy (message_dialog);
1148 }
1149
1150 #if 0
1151 /* FIXME MC-5 */
1152 static void
1153 accounts_dialog_button_import_clicked_cb (GtkWidget             *button,
1154                                           EmpathyAccountsDialog *dialog)
1155 {
1156         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1157
1158         empathy_import_dialog_show (GTK_WINDOW (priv->window), TRUE);
1159 }
1160 #endif
1161
1162 static void
1163 accounts_dialog_response_cb (GtkWidget            *widget,
1164                              gint                  response,
1165                              EmpathyAccountsDialog *dialog)
1166 {
1167         GList *accounts, *l;
1168         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1169
1170         if (response == GTK_RESPONSE_CLOSE) {
1171                 /* Delete incomplete accounts */
1172                 accounts = empathy_account_manager_dup_accounts
1173                         (priv->account_manager);
1174                 for (l = accounts; l; l = l->next) {
1175                         EmpathyAccount *account;
1176
1177                         account = l->data;
1178                         if (!empathy_account_is_valid (account)) {
1179                                 /* FIXME: Warn the user the account is not
1180                                  * complete and is going to be removed.
1181                                  */
1182                                 empathy_account_manager_remove
1183                                         (priv->account_manager, account);
1184                         }
1185
1186                         g_object_unref (account);
1187                 }
1188                 g_list_free (accounts);
1189
1190                 gtk_widget_destroy (widget);
1191         }
1192 }
1193
1194 static void
1195 accounts_dialog_destroy_cb (GtkObject *obj,
1196                             EmpathyAccountsDialog *dialog)
1197 {
1198         DEBUG ("%p", obj);
1199
1200         g_object_unref (dialog);
1201 }
1202
1203 static void
1204 accounts_dialog_set_selected_account (EmpathyAccountsDialog *dialog,
1205                                       EmpathyAccount *account)
1206 {
1207         GtkTreeSelection *selection;
1208         GtkTreeIter       iter;
1209         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1210
1211         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
1212         if (accounts_dialog_get_account_iter (dialog, account, &iter)) {
1213                 gtk_tree_selection_select_iter (selection, &iter);
1214         }
1215 }
1216
1217 static void
1218 accounts_dialog_cms_ready_cb (EmpathyConnectionManagers *cms,
1219                               GParamSpec *pspec,
1220                               EmpathyAccountsDialog *dialog)
1221 {
1222         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1223
1224         if (empathy_connection_managers_is_ready (cms)) {
1225                 accounts_dialog_update_settings (dialog, NULL);
1226
1227                 if (priv->initial_selection != NULL) {
1228                         accounts_dialog_set_selected_account (dialog, priv->initial_selection);
1229                         priv->initial_selection = NULL;
1230                 }
1231         }
1232 }
1233
1234 static void
1235 accounts_dialog_build_ui (EmpathyAccountsDialog *dialog)
1236 {       
1237         GtkBuilder                   *gui;
1238         gchar                        *filename;
1239         EmpathyAccountsDialogPriv    *priv = GET_PRIV (dialog);
1240
1241         filename = empathy_file_lookup ("empathy-accounts-dialog.ui", "src");
1242
1243         gui = empathy_builder_get_file (filename,
1244                                        "accounts_dialog", &priv->window,
1245                                        "vbox_details", &priv->vbox_details,
1246                                        "frame_no_protocol", &priv->frame_no_protocol,
1247                                        "alignment_settings", &priv->alignment_settings,
1248                                        "treeview", &priv->treeview,
1249                                        "frame_new_account", &priv->frame_new_account,
1250                                        "hbox_type", &priv->hbox_type,
1251                                        "button_create", &priv->button_create,
1252                                        "button_back", &priv->button_back,
1253                                        "radiobutton_reuse", &priv->radiobutton_reuse,
1254                                        "radiobutton_register", &priv->radiobutton_register,
1255                                        "image_type", &priv->image_type,
1256                                        "label_name", &priv->label_name,
1257                                        "button_add", &priv->button_add,
1258                                        "button_remove", &priv->button_remove,
1259                                        "button_import", &priv->button_import,
1260                                        NULL);
1261         g_free (filename);
1262
1263         empathy_builder_connect (gui, dialog,
1264                               "accounts_dialog", "response", accounts_dialog_response_cb,
1265                               "accounts_dialog", "destroy", accounts_dialog_destroy_cb,
1266                               "button_create", "clicked", accounts_dialog_button_create_clicked_cb,
1267                               "button_back", "clicked", accounts_dialog_button_back_clicked_cb,
1268                               "button_add", "clicked", accounts_dialog_button_add_clicked_cb,
1269                               "button_remove", "clicked", accounts_dialog_button_remove_clicked_cb,
1270 #if 0
1271 /* FIXME MC-5  */
1272                               "button_import", "clicked", accounts_dialog_button_import_clicked_cb,
1273 #endif
1274                               "button_help", "clicked", accounts_dialog_button_help_clicked_cb,
1275                               NULL);
1276
1277         g_object_unref (gui);
1278
1279         priv->combobox_protocol = empathy_protocol_chooser_new ();
1280         gtk_box_pack_end (GTK_BOX (priv->hbox_type),
1281                           priv->combobox_protocol,
1282                           TRUE, TRUE, 0);
1283         gtk_widget_show (priv->combobox_protocol);
1284         g_signal_connect (priv->combobox_protocol, "changed",
1285                           G_CALLBACK (accounts_dialog_protocol_changed_cb),
1286                           dialog);
1287
1288         if (priv->parent_window) {
1289                 gtk_window_set_transient_for (GTK_WINDOW (priv->window),
1290                                               priv->parent_window);
1291         }
1292 }
1293
1294 static void
1295 do_dispose (GObject *obj)
1296 {
1297         EmpathyAccountsDialog *dialog = EMPATHY_ACCOUNTS_DIALOG (obj);
1298         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1299
1300         /* Disconnect signals */
1301         g_signal_handlers_disconnect_by_func (priv->account_manager,
1302                                               accounts_dialog_account_added_cb,
1303                                               dialog);
1304         g_signal_handlers_disconnect_by_func (priv->account_manager,
1305                                               accounts_dialog_account_removed_cb,
1306                                               dialog);
1307         g_signal_handlers_disconnect_by_func (priv->account_manager,
1308                                               accounts_dialog_account_enabled_cb,
1309                                               dialog);
1310         g_signal_handlers_disconnect_by_func (priv->account_manager,
1311                                               accounts_dialog_account_disabled_cb,
1312                                               dialog);
1313         g_signal_handlers_disconnect_by_func (priv->account_manager,
1314                                               accounts_dialog_account_changed_cb,
1315                                               dialog);
1316         g_signal_handlers_disconnect_by_func (priv->account_manager,
1317                                               accounts_dialog_connection_changed_cb,
1318                                               dialog);
1319
1320         if (priv->connecting_id) {
1321                 g_source_remove (priv->connecting_id);
1322         }
1323
1324         if (priv->account_manager != NULL) {
1325                 g_object_unref (priv->account_manager);
1326                 priv->account_manager = NULL;
1327         }
1328
1329         if (priv->cms != NULL) {
1330                 g_object_unref (priv->cms);
1331                 priv->cms = NULL;
1332         }
1333
1334         G_OBJECT_CLASS (empathy_accounts_dialog_parent_class)->dispose (obj);
1335 }
1336
1337 static GObject *
1338 do_constructor (GType type,
1339                 guint n_props,
1340                 GObjectConstructParam *props)
1341 {
1342         GObject *retval;
1343
1344         if (dialog_singleton)   {
1345                 retval = G_OBJECT (dialog_singleton);
1346         } else  {
1347                 retval = G_OBJECT_CLASS (empathy_accounts_dialog_parent_class)->constructor
1348                         (type, n_props, props);
1349
1350                 dialog_singleton = EMPATHY_ACCOUNTS_DIALOG (retval);
1351                 g_object_add_weak_pointer (retval, (gpointer) &dialog_singleton);
1352         }
1353
1354         return retval;
1355 }
1356
1357 static void
1358 do_get_property (GObject *object,
1359                  guint property_id,
1360                  GValue *value,
1361                  GParamSpec *pspec)
1362 {
1363         EmpathyAccountsDialogPriv *priv = GET_PRIV (object);
1364
1365         switch (property_id) {
1366         case PROP_PARENT:
1367                 g_value_set_object (value, priv->parent_window);
1368                 break;
1369         default:
1370                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1371         }
1372 }
1373
1374 static void
1375 do_set_property (GObject *object,
1376                  guint property_id,
1377                  const GValue *value,
1378                  GParamSpec *pspec)
1379 {
1380         EmpathyAccountsDialogPriv *priv = GET_PRIV (object);
1381
1382         switch (property_id) {
1383         case PROP_PARENT:
1384                 priv->parent_window = g_value_get_object (value);
1385                 break;
1386         default:
1387                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1388         }
1389 }
1390
1391 static void
1392 do_constructed (GObject *object)
1393 {
1394         EmpathyAccountsDialog *dialog = EMPATHY_ACCOUNTS_DIALOG (object);
1395         EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1396         GList *accounts, *l;
1397         gboolean import_asked;
1398
1399         accounts_dialog_build_ui (dialog);
1400
1401         /* Set up signalling */
1402         priv->account_manager = empathy_account_manager_dup_singleton ();
1403
1404         g_signal_connect (priv->account_manager, "account-created",
1405                           G_CALLBACK (accounts_dialog_account_added_cb),
1406                           dialog);
1407         g_signal_connect (priv->account_manager, "account-deleted",
1408                           G_CALLBACK (accounts_dialog_account_removed_cb),
1409                           dialog);
1410         g_signal_connect (priv->account_manager, "account-enabled",
1411                           G_CALLBACK (accounts_dialog_account_enabled_cb),
1412                           dialog);
1413         g_signal_connect (priv->account_manager, "account-disabled",
1414                           G_CALLBACK (accounts_dialog_account_disabled_cb),
1415                           dialog);
1416         g_signal_connect (priv->account_manager, "account-changed",
1417                           G_CALLBACK (accounts_dialog_account_changed_cb),
1418                           dialog);
1419         g_signal_connect (priv->account_manager, "account-connection-changed",
1420                           G_CALLBACK (accounts_dialog_connection_changed_cb),
1421                           dialog);
1422
1423         accounts_dialog_model_setup (dialog);
1424
1425         /* Add existing accounts */
1426         accounts = empathy_account_manager_dup_accounts (priv->account_manager);
1427         for (l = accounts; l; l = l->next) {
1428                 accounts_dialog_add_account (dialog, l->data);
1429                 g_object_unref (l->data);
1430         }
1431         g_list_free (accounts);
1432
1433         priv->cms = empathy_connection_managers_dup_singleton ();
1434         if (!empathy_connection_managers_is_ready (priv->cms)) {
1435                 g_signal_connect (priv->cms, "notify::ready",
1436                                   G_CALLBACK (accounts_dialog_cms_ready_cb), dialog);
1437         }
1438
1439         accounts_dialog_model_select_first (dialog);
1440
1441         empathy_conf_get_bool (empathy_conf_get (),
1442                                EMPATHY_PREFS_IMPORT_ASKED, &import_asked);
1443
1444
1445 #if 0
1446 /* FIXME MC-5 */
1447         if (empathy_import_dialog_accounts_to_import ()) {
1448
1449                 if (!import_asked) {
1450                         empathy_conf_set_bool (empathy_conf_get (),
1451                                                EMPATHY_PREFS_IMPORT_ASKED, TRUE);
1452                         empathy_import_dialog_show (GTK_WINDOW (priv->window),
1453                                                     FALSE);
1454                 }
1455         } else {
1456                 gtk_widget_set_sensitive (priv->button_import, FALSE);
1457         }
1458 #endif
1459 }
1460
1461 static void
1462 empathy_accounts_dialog_class_init (EmpathyAccountsDialogClass *klass)
1463 {
1464         GObjectClass *oclass = G_OBJECT_CLASS (klass);
1465         GParamSpec *param_spec;
1466
1467         oclass->constructor = do_constructor;
1468         oclass->dispose = do_dispose;
1469         oclass->constructed = do_constructed;
1470         oclass->set_property = do_set_property;
1471         oclass->get_property = do_get_property;
1472
1473         param_spec = g_param_spec_object ("parent",
1474                                           "parent", "The parent window",
1475                                           GTK_TYPE_WINDOW,
1476                                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1477         g_object_class_install_property (oclass, PROP_PARENT, param_spec);
1478
1479         g_type_class_add_private (klass, sizeof (EmpathyAccountsDialogPriv));
1480 }
1481
1482 static void
1483 empathy_accounts_dialog_init (EmpathyAccountsDialog *dialog)
1484 {
1485         EmpathyAccountsDialogPriv *priv;
1486
1487         priv = G_TYPE_INSTANCE_GET_PRIVATE ((dialog),
1488                                             EMPATHY_TYPE_ACCOUNTS_DIALOG,
1489                                             EmpathyAccountsDialogPriv);
1490         dialog->priv = priv;
1491 }
1492
1493 /* public methods */
1494
1495 GtkWidget *
1496 empathy_accounts_dialog_show (GtkWindow *parent,
1497                               EmpathyAccount *selected_account)
1498 {
1499         EmpathyAccountsDialog *dialog;
1500         EmpathyAccountsDialogPriv *priv;
1501
1502         dialog = g_object_new (EMPATHY_TYPE_ACCOUNTS_DIALOG,
1503             "parent", parent, NULL);
1504
1505         priv = GET_PRIV (dialog);
1506
1507         if (selected_account && empathy_connection_managers_is_ready (priv->cms)) {
1508                 accounts_dialog_set_selected_account (dialog, selected_account);
1509         } else {
1510                 /* save the selection to set it later when the cms
1511                  * becomes ready.
1512                  */
1513                 priv->initial_selection = selected_account;
1514         }
1515
1516         gtk_window_present (GTK_WINDOW (priv->window));
1517
1518         return priv->window;
1519 }